Unidirectional associations for one-to-many

hasebul_hassanchowdhury_

Hasebul Hassan Chowdhury

Posted on November 30, 2024

Unidirectional associations for one-to-many

What is a bidirectional relationship in relational database model? let's take a quick look -
Suppose you two table Post and Post_Comment. Now you want to find out which comment are associated with which post or for a post how many comments are associated with that? How you can do that?
Image description

Here is the basic Post entity table

@Entity
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String title;

    public Post() {

    }
// ignoring setter and getter
}
Enter fullscreen mode Exit fullscreen mode

Here is the basic Post comment entity table

@Entity
public class PostComment {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column
    private String description;

    public PostComment() {

    }
// ignoring setter and getter
Enter fullscreen mode Exit fullscreen mode

Currently, both table/entity don't have any relationship between them.
Now let's try to construct a unidirectional relationship between post and post comment.

Here are a few cases to keep in mind :-

  1. Post can be owner side (one-To-Many)
  2. Post Comment can be owner side (Many-To-One)

First, let's define Case 1 :

@Entity
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String title;

    @OneToMany(cascade = CascadeType.PERSIST, orphanRemoval = true)
    private List<PostComment> postComments = new ArrayList<>();

    public Post() {

    }

    public void addComment(PostComment comment) {
        postComments.add(comment);
    }

    public void removeComment(PostComment comment) {
        postComments.remove(comment);
    }
// ignoring setter and getter
}
Enter fullscreen mode Exit fullscreen mode

Now what we have done here?
We added a list and telling Post that it can have zero, one or more than one post comment by using @OneToMany. There can be mutiple comment associated with a single Post. we are cascade = CascadeType.PERSIST, orphanRemoval = true in these two later.
@OneToMany(cascade = CascadeType.PERSIST, orphanRemoval = true)
private List<PostComment> postComments = new ArrayList<>();

we also added two method which will make our life easier to add/remove comment

        public void addComment(PostComment comment) {
        postComments.add(comment);
    }

    public void removeComment(PostComment comment) {
        postComments.remove(comment);
    }
Enter fullscreen mode Exit fullscreen mode

Okay, we are almost done with our entity design (Not fully done). Let's take a look how we can save/persist a post with a comment.

@Service
public class PostService {

    @Autowired
    EntityManager eManager;

    @Transactional
    public void addPost1() {
        Post post = new Post();
        post.setTitle("Hibernate in action is quite good");

        PostComment comment = new PostComment();
        comment.setDescription("Recommended");

        post.addComment(comment);

        eManager.persist(post);
    }
}
Enter fullscreen mode Exit fullscreen mode

Here we are creating a post and then setting the title and adding a comment. Then calling eManager.persist(post) which will save the post and its associated comment. Easy, right!!!. Lets take a look at the database (H2) :

Image description

We can see a Post table which have only one row with id and title where id is 1 and title is "Hibernate in action is quite good".
Now lets look at post comment table :

Image description
we can see a row with id and description where id is 1 and description is Recommended.

Nice. but what is that POST_POST_COMMENTS table? We did not define any entity/table in our codebase. So here's the explanation
When we used one-to-many relationship between post and comment. Each comment will be associated with a post id. So there will be a mapping between post_id and post_comment_id. But where should we store that info? Hibernate creates another table by combining the two relational entity/table name (POST and POST_COMMENTS) where it stores two column primary id from both table. In our case, id from post table (POST_ID) and id from post comment table (POST_COMMENT_ID).

Join Table

Can we improve that? An extra table is an extra burden.yes we can. lets see how we can do that?

@OneToMany(cascade = CascadeType.PERSIST, orphanRemoval = true)
@JoinColumn(name = "post_id")
private List<PostComment> postComments = new ArrayList<>();

Enter fullscreen mode Exit fullscreen mode

@JoinColumn(name = "post_id") This join column annotation tells that we don't need any extra table for mapping. Instead, POST_COMMENT table will handle it. There will be an extra column named "post_id" in POST_COMMENT table, which will store the associated post id for that comment, but good things is JPA/hibernate will do that on its own. We don't need to change our post comment entity.

POST_COMMENT table with POST_ID

lets add another comment in post with id 1.

@Transactional
    public void addCommentOnPost() {
        Post post = eManager.find(Post.class, 1);

        PostComment comment = new PostComment();
        comment.setDescription("this book is also for beginner");
        post.addComment(comment);

        eManager.persist(post);
    }
Enter fullscreen mode Exit fullscreen mode

Image description

Now lets try to fetch those comments.

@Transactional
    public void findCommentByPostId() {
        Post post = eManager.find(Post.class, 1);
        System.out.println("Number of comment " + post.getPostComments().size());
        System.out.println(post.getPostComments());
    }
/*
Number of comment 2
[
PostComment [id=1, description=Recommended], 
PostComment [id=2, description=this book is also for beginner]
]
*/
Enter fullscreen mode Exit fullscreen mode

jpa/hibernate will go to POST_COMMENT table and check on post_id if there is a match in our case post_id = 1. it will pick them up.

💖 💪 🙅 🚩
hasebul_hassanchowdhury_
Hasebul Hassan Chowdhury

Posted on November 30, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related