<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hasebul Hassan Chowdhury</title>
    <description>The latest articles on DEV Community by Hasebul Hassan Chowdhury (@hasebul_hassanchowdhury_).</description>
    <link>https://dev.to/hasebul_hassanchowdhury_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2503107%2F39338a49-e8da-4a74-987e-81d44806ecb4.jpg</url>
      <title>DEV Community: Hasebul Hassan Chowdhury</title>
      <link>https://dev.to/hasebul_hassanchowdhury_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hasebul_hassanchowdhury_"/>
    <language>en</language>
    <item>
      <title>Unidirectional associations for one-to-many</title>
      <dc:creator>Hasebul Hassan Chowdhury</dc:creator>
      <pubDate>Sat, 30 Nov 2024 09:47:04 +0000</pubDate>
      <link>https://dev.to/hasebul_hassanchowdhury_/unidirectional-relationship-for-one-to-many-and-many-to-one-4a6p</link>
      <guid>https://dev.to/hasebul_hassanchowdhury_/unidirectional-relationship-for-one-to-many-and-many-to-one-4a6p</guid>
      <description>&lt;p&gt;What is a bidirectional relationship in relational database model? let's take a quick look -&lt;br&gt;
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?&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38gnfd7hjjnlv3x570ph.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38gnfd7hjjnlv3x570ph.PNG" alt="Image description" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the basic Post entity table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Entity
public class Post {

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

    @Column
    private String title;

    public Post() {

    }
// ignoring setter and getter
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the basic Post comment entity table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Entity
public class PostComment {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column
    private String description;

    public PostComment() {

    }
// ignoring setter and getter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently, there is no relationship between the Post and PostComment entities. Now, let's establish a unidirectional relationship between them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Cases to Consider:&lt;/strong&gt;&lt;br&gt;
Post as the Owner (One-To-Many):&lt;br&gt;
This means the Post entity will manage the relationship. Each Post can have multiple PostComment entries.&lt;/p&gt;

&lt;p&gt;PostComment as the Owner (Many-To-One):&lt;br&gt;
Here, the PostComment entity will manage the relationship. Each comment will be linked to a single Post.&lt;/p&gt;

&lt;p&gt;Let’s start by implementing Case 1: Post as the Owner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Entity
public class Post {

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

    @Column
    private String title;

    @OneToMany(cascade = CascadeType.PERSIST, orphanRemoval = true)
    private List&amp;lt;PostComment&amp;gt; postComments = new ArrayList&amp;lt;&amp;gt;();

    public Post() {

    }

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

    public void removeComment(PostComment comment) {
        postComments.remove(comment);
    }
// ignoring setter and getter
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;we also added two method which will make our life easier to add/remove comment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        public void addComment(PostComment comment) {
        postComments.add(comment);
    }

    public void removeComment(PostComment comment) {
        postComments.remove(comment);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@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);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvt9b3ckodlw480jzrs5l.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvt9b3ckodlw480jzrs5l.PNG" alt="Image description" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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". &lt;br&gt;
Now lets look at post comment table : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftnin9d0tu1gotgwxnaqr.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftnin9d0tu1gotgwxnaqr.PNG" alt="Image description" width="800" height="410"&gt;&lt;/a&gt;&lt;br&gt;
We have a row with an id of 1 and a description as Recommended. Great! But what is the POST_POST_COMMENTS table? We didn’t explicitly define it in our codebase.&lt;/p&gt;

&lt;p&gt;Here’s the explanation:&lt;br&gt;
When we set up a one-to-many relationship between Post and Comment, each comment is linked to a Post using a post_id. This creates a mapping between post_id and post_comment_id. But where is this mapping stored?&lt;/p&gt;

&lt;p&gt;Hibernate automatically creates a join table, combining the names of the two entities/tables (POST and POST_COMMENTS). This table holds two columns:&lt;/p&gt;

&lt;p&gt;The primary key (POST_ID) from the Post table.&lt;br&gt;
The primary key (POST_COMMENT_ID) from the Post_Comments table.&lt;br&gt;
In this way, Hibernate manages the relationship without requiring us to define this table explicitly in the code..&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vy97e4pm2f464yl2bjf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vy97e4pm2f464yl2bjf.PNG" alt="Join Table" width="800" height="468"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Can we improve that? An extra table is an extra burden.yes we can. lets see how we can do that?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@OneToMany(cascade = CascadeType.PERSIST, orphanRemoval = true)
@JoinColumn(name = "post_id")
private List&amp;lt;PostComment&amp;gt; postComments = new ArrayList&amp;lt;&amp;gt;();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@JoinColumn(name = "post_id")&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxwmbdk8vy5qj5shfc02.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxwmbdk8vy5qj5shfc02.PNG" alt="POST_COMMENT table with POST_ID" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;lets add another comment in post with id 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@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);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7vcohhnavvmcrwlwxfb.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7vcohhnavvmcrwlwxfb.PNG" alt="Image description" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now lets try to fetch those comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@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]
]
*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How JPA/Hibernate fetches comments:&lt;/strong&gt;&lt;br&gt;
When you call post.getPostComments(), JPA/Hibernate queries the POST_COMMENT table. It checks the post_id column for entries that match the post_id (in our case, post_id=1). It then retrieves all matching rows and maps them to PostComment objects. That's how both comments associated with the post are fetched and returned&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;orphanRemoval = true&lt;/strong&gt;&lt;br&gt;
This ensures that if a PostComment is removed from the postComments list, it is automatically deleted from the database. Essentially:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If a comment is no longer associated with a Post, it becomes an orphan and is removed from the database.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Post post = entityManager.find(Post.class, 1);
PostComment comment = post.getPostComments().get(0);

post.getPostComments().remove(comment);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without orphanRemoval = true, the PostComment would still exist in the database even if it is removed from the list, potentially leading to orphaned rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CascadeType.PERSIST&lt;/strong&gt;&lt;br&gt;
This means that whenever you persist a Post entity, all associated PostComment entities will also be automatically persisted. In other words:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You don't need to explicitly save the comments.&lt;/li&gt;
&lt;li&gt;As long as they are added to the postComments list and the Post is persisted, Hibernate will ensure the comments are saved to the database.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Post post = new Post();
PostComment comment = new PostComment();
comment.setDescription("A new comment");

post.getPostComments().add(comment);

entityManager.persist(post);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without CascadeType.PERSIST, you would need to explicitly persist each PostComment&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>jpa</category>
      <category>hibernate</category>
    </item>
  </channel>
</rss>
