"Welcome To Ashok IT" "Spring Boot and MicroServices" Topic : Spring Data JPA - Association Date : 02/11/2024 (Session - 58) _____________________________________________________________________________________________________________________________ Last Session ============ * We Just working with "Association" in ORM Frameworks. * One-to-One Association using annotation i.e.,@OneToOne(Mapping) & @JoinColumn(Physical Relation b/w DB Tables) * We can build the One-to-One Association using two directions Not Possible Possible 1) Uni-Direction (Navigation) : Student <----------------> Login, Login <--------------> Student Example ======= Class Student{ } Class Login{ @OneToOne(cascadeType="", fetch="") @JoinColumn(name="student_id") private Student student; } Possible Possible 2) Bi-Direction (Navigation) : Student <----------------> Login, Login <--------------> Student Example ======= Class Student{ @OneToOne(cascadeType="", fetch="") private Login login; } Class Login{ @OneToOne(cascadeType="", fetch="") @JoinColumn(name="student_id") private Student student; } One-To-Many Association ======================= * In One-To-Many Association (or) Mapping means one row in a table is mapped to multiple rows in another table. * let us consider the few examples for better understanding for Realtime examples University -------------> Students ShoppingCart -------------> Items User -------------> Emails,MobileNos Post -------------> Comments Car -------------> Models Student -------------> Courses * Inorder to work with this association we need to use the following annotation in entity class as "@OneToMany" from Hibernate. * We can build Association in two modes 1) One-To-Many Uni-Direction Association ======================================== * As we discussed earlier in uni-direction association always we can build the relationship either parent to child (or) child to parent entities only i.e., one way direction only. Example ======= @Entity @Entity @Table(name="ashokit_posts) @Table(name="ashokit_comments) public Class Post{ public Class Comment{ private int postId; private int commentId private String postName; private String commentInfo; private Date createdDate; private Date createdDate; @OneToMany } @JoinColumn private List comments = new ArrayList(); } Database Tables =============== 1) ashokit_posts >>>>>>>>>>>>>>> post_id,post_name,created_date 2) ashokit_comments >>>>>>>>>>>> comment_id,comment_info,created_date,post_id * In the above two entity classes Post is an Parent Class but where as Comment as Child class. * In the uni-directional only one side is possible to retreive the records either parent to child (or) child to parent. * In @OneToMany Association default fetch strategy is "LAZY" means whenever parent is loaded the child object should not be loaded. 1) targetEntity: ================ * This attribute specifies the target entity class of the association. In most cases, you don't need to use this attribute because the target entity can be inferred from the field type. However, you might use it when dealing with generic types or interfaces. For example, targetEntity = Book.class would explicitly specify that the target entity of the one-to-many association is the Book class. 2) orphanRemoval ================ * This attribute is a boolean flag that defines whether to remove orphaned child entities automatically when they are removed from the association in the parent entity. * When orphanRemoval = true, if a book is removed from the books list of an author and the author is persisted or updated, the orphaned book will be automatically deleted from the database. * If orphanRemoval = false (the default), removing a book from the books list will only disassociate it from the author, and it will not be deleted from the database automatically. Example ======= Post.java ========= package com.ashokit.entity; import java.util.ArrayList; import java.util.Date; import java.util.List; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; @Entity @Table(name="ashokit_posts") public class Post { @Id @Column(name = "post_id") @GeneratedValue(strategy = GenerationType.AUTO) private int postId; @Column(name="post_title", nullable = false) private String postTitle; @Column(name="created_date",nullable = false) @Temporal(TemporalType.DATE) private Date createdDate; @Column(name="created_by",nullable = false) private String createdBy; //onetoMany association @OneToMany(targetEntity = Comment.class, cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) @JoinColumn(name="post_id") private List comments = new ArrayList<>(); public int getPostId() { return postId; } public void setPostId(int postId) { this.postId = postId; } public String getPostTitle() { return postTitle; } public void setPostTitle(String postTitle) { this.postTitle = postTitle; } public Date getCreatedDate() { return createdDate; } public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; } public String getCreatedBy() { return createdBy; } public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } public void setComments(List comments) { this.comments = comments; } public List getComments() { return comments; } @Override public String toString() { return "Post [postId=" + postId + ", postTitle=" + postTitle + ", createdDate=" + createdDate + ", createdBy="+ createdBy + "]"; } } Comment.java ============ package com.ashokit.entity; import java.util.Date; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; @Entity @Table(name="ashokit_comments") public class Comment { @Id @Column(name = "comment_id") @GeneratedValue(strategy = GenerationType.AUTO) private int commentId; @Column(name="comment_info", nullable = false) private String commentInfo; @Column(name="created_date",nullable = false) @Temporal(TemporalType.DATE) private Date createdDate; @Column(name="created_by",nullable = false) private String createdBy; public int getCommentId() { return commentId; } public void setCommentId(int commentId) { this.commentId = commentId; } public String getCommentInfo() { return commentInfo; } public void setCommentInfo(String commentInfo) { this.commentInfo = commentInfo; } public Date getCreatedDate() { return createdDate; } public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; } public String getCreatedBy() { return createdBy; } public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } @Override public String toString() { return "Comment [commentId=" + commentId + ", commentInfo=" + commentInfo + ", createdDate=" + createdDate + ", createdBy=" + createdBy + "]"; } } CommentDao.java =============== package com.ashokit.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.ashokit.entity.Comment; public interface CommentDao extends JpaRepository{ } PostDao.java ============ package com.ashokit.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.ashokit.entity.Post; public interface PostDao extends JpaRepository{ } application.yml =============== spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver password: root url: jdbc:mysql://localhost:3306/31_springbootms_db username: root jpa: hibernate: ddl-auto: update show-sql: true properties: hibernate: enable_lazy_load_no_trans: true Application.java ================ package com.ashokit; import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.ashokit.dao.CommentDao; import com.ashokit.dao.PostDao; import com.ashokit.entity.Comment; import com.ashokit.entity.Post; @SpringBootApplication public class Application implements CommandLineRunner{ @Autowired private PostDao postDao; @Autowired private CommentDao commentDao; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) throws Exception { //First Post Information Post post = new Post(); post.setPostTitle("Spring Boot Post"); post.setCreatedDate(new Date()); post.setCreatedBy("Mahesh"); //Binding the First comment for First Post Comment firstComment = new Comment(); firstComment.setCommentInfo("Informative Session"); firstComment.setCreatedDate(new Date()); firstComment.setCreatedBy("Suresh"); //Binding the Second comment for First Post Comment secondComment = new Comment(); secondComment.setCommentInfo("Good Session"); secondComment.setCreatedDate(new Date()); secondComment.setCreatedBy("Ramesh"); //parent to child saving records post.setComments(List.of(firstComment,secondComment)); //saving the parent object Post postInfo = postDao.save(post); System.out.println("Post Information::::" + postInfo); //Second Post Information Post post1 = new Post(); post1.setPostTitle("Devops With AWS Post"); post1.setCreatedDate(new Date()); post1.setCreatedBy("Ashok"); //Binding the First comment for Second Post Comment firstPostComment = new Comment(); firstPostComment.setCommentInfo("Informative Session"); firstPostComment.setCreatedDate(new Date()); firstPostComment.setCreatedBy("Suresh"); //Binding the First comment for Second Post Comment secondPostComment = new Comment(); secondPostComment.setCommentInfo("Good Session"); secondPostComment.setCreatedDate(new Date()); secondPostComment.setCreatedBy("Ashok"); //Binding the First comment for Second Post Comment thirdPostComment = new Comment(); thirdPostComment.setCommentInfo("Good Informative Session"); thirdPostComment.setCreatedDate(new Date()); thirdPostComment.setCreatedBy("Ashok"); //setting parent to child object post1.setComments(List.of(firstPostComment,secondPostComment,thirdPostComment)); Post savedFirstPostInfo = postDao.save(post1); System.out.println("Saved First Post Info ::::::" + savedFirstPostInfo); //loading the parent object Post post11 = postDao.findById(1).get(); System.out.println("Loading Post Information ::::" + post11); System.out.println("Loading Post & Comment Information ::::" + post11.getComments()); //deleting parent object associated child objects should be deleted postDao.deleteById(1); } }