You can use the Fluent Interface template with JPA and Hibernate. I wrote an article that explains this topic in detail .
To summarize, if you use Hibernate, you can simply modify the setters to return an object:
@Entity(name = "Post") @Table(name = "post") public class Post { @Id private Long id; private String title; public Post() {} public Post(String title) { this.title = title; } @OneToMany( cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "post" ) private List<PostComment> comments = new ArrayList<>(); public Long getId() { return id; } public Post setId(Long id) { this.id = id; return this; } public String getTitle() { return title; } public Post setTitle(String title) { this.title = title; return this; } public List<PostComment> getComments() { return comments; } public Post addComment(PostComment comment) { comment.setPost(this); comments.add(comment); return this; } } @Entity(name = "PostComment") @Table(name = "post_comment") public class PostComment { @Id @GeneratedValue private Long id; private String review; private Date createdOn; @ManyToOne private Post post; public Long getId() { return id; } public PostComment setId(Long id) { this.id = id; return this; } public String getReview() { return review; } public PostComment setReview(String review) { this.review = review; return this; } public Date getCreatedOn() { return createdOn; } public PostComment setCreatedOn(Date createdOn) { this.createdOn = createdOn; return this; } public Post getPost() { return post; } public PostComment setPost(Post post) { this.post = post; return this; } }
Thus, you can create the parent and child objects as follows:
doInJPA(entityManager -> { Post post = new Post() .setId(1L) .setTitle("High-Performance Java Persistence") .addComment( new PostComment() .setReview("Awesome book") .setCreatedOn(Timestamp.from( LocalDateTime.now().minusDays(1).toInstant(ZoneOffset.UTC)) ) ) .addComment( new PostComment() .setReview("High-Performance Rocks!") .setCreatedOn(Timestamp.from( LocalDateTime.now().minusDays(2).toInstant(ZoneOffset.UTC)) ) ) .addComment( new PostComment() .setReview("Database essentials to the rescue!") .setCreatedOn(Timestamp.from( LocalDateTime.now().minusDays(3).toInstant(ZoneOffset.UTC)) ) ); entityManager.persist(post); });
If you need JPA portability, you can not violate the Java Bean specification, in which case you need to add Fluent Interface methods on regular setters:
@Entity(name = "Post") @Table(name = "post") public class Post { @Id private Long id; private String title; public Post() {} public Post(String title) { this.title = title; } @OneToMany( cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "post" ) private List<PostComment> comments = new ArrayList<>(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Post id(Long id) { this.id = id; return this; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Post title(String title) { this.title = title; return this; } public List<PostComment> getComments() { return comments; } public Post addComment(PostComment comment) { comments.add(comment.post(this)); return this; } } @Entity(name = "PostComment") @Table(name = "post_comment") public class PostComment { @Id @GeneratedValue private Long id; private String review; private Date createdOn; @ManyToOne private Post post; public Long getId() { return id; } public PostComment setId(Long id) { this.id = id; return this; } public String getReview() { return review; } public void setReview(String review) { this.review = review; } public PostComment review(String review) { this.review = review; return this; } public Date getCreatedOn() { return createdOn; } public void setCreatedOn(Date createdOn) { this.createdOn = createdOn; } public PostComment createdOn(Date createdOn) { this.createdOn = createdOn; return this; } public Post getPost() { return post; } public void setPost(Post post) { this.post = post; } public PostComment post(Post post) { this.post = post; return this; } }
The building of the object is almost identical to the previous one:
doInJPA(entityManager -> { Post post = new Post() .id(1L) .title("High-Performance Java Persistence") .addComment(new PostComment() .review("Awesome book") .createdOn(Timestamp.from( LocalDateTime.now().minusDays(1).toInstant(ZoneOffset.UTC)) ) ) .addComment(new PostComment() .review("High-Performance Rocks!") .createdOn(Timestamp.from( LocalDateTime.now().minusDays(2).toInstant(ZoneOffset.UTC)) ) ) .addComment(new PostComment() .review("Database essentials to the rescue!") .createdOn(Timestamp.from( LocalDateTime.now().minusDays(3).toInstant(ZoneOffset.UTC)) ) ); entityManager.persist(post); });
source share