Hibernate: Save multiple association issue

Viewed 65

I have three entities with relations.

public class Site {
    @OneToMany
    private List<Page> pages;
}

public class Page {
    @OneToMany
    private List<Article> articles;

    @OneToMany
    private List<TopArticle> topArticles;
}

public class Article {
    @ManyToOne
    private Page page;
}

public class TopArticle {
    @ManyToOne
    @JoinColumn(name = "PageId")
    private Page page;
    
    @OneToOne
    @JoinColumn(name = "ArticleId")
    private Article article;
}

Fields page and arctile in TopArticle have database restrictions - NOT NULL. (Resctrictions are required)

I have to save Site with all associations.

    Article article = new Article();
    TopArticle topArticle = new TopArticle();

    Page page = new Page();
    page.getArticles().add(article);
    page.getTopArticles().add(topArticle);

    Site site = new Site();
    site.getPages().add(page);

    siteDAO.save(site);

Sometimes it saves site. But sometimes it throws an error.

com.microsoft.sqlserver.jdbc.SQLServerException: Cannot insert the value NULL into column 'ArticleId', table '...TopArticle'; column does not allow nulls. INSERT fails

It seems that after Page is saved, it tries to save associations List articles and List topArticles. Perhaps, when List articles are saved before List topArticles it works. In another way it fails.

Questions:

Is an issue in saving properties order in JPA?

How can I enforce Hibernate to save articles before topArticles?

Is there any other solutions?

Thanks

1 Answers

With a bi-directional relationship it is your responsibility to ensure both sides are set correctly on the in-memory model otherwise you will get the error you are seeing.

So you need to call:

article.setPage(page);

And ideally you should encapsulate the operation so the in-memory model is always consistent:

public class Page{

    public List<Article> getArticles(){
      return Collections.unmodifiableList(articles); //force through add method
    }

    public void addArticle(Article article){
        articles.add(article);
        article.setPage(this);
    }
}
Related