x "Welcome To Ashok IT" "Spring Boot and MicroServices" Topic : Spring Data JPA - Association Date : 01/11/2024 (Session - 57) _____________________________________________________________________________________________________________________________ Association =========== * Association means establishing relationship between two or more DB tables using Primary Key & Foreign Key in the same way we can establish relationship between the entity classes i.e.,Association. * Association between two or more things is refers to the state of being associated i.e. how the things are related to each other. * Association in hibernate tells the relationship between the objects of POJO classes i.e. how the entities are related to each other. Association or entities relationship can be unidirectional or bidirectional. Example ======= one - one Student <---------------------> Ashokit portal one - one company <---------------------> WebSite one - one Citizen <---------------------> ID Proofs(Aadhar,Pancard,VoterID,DriverLicense etc.,) one - one Employee <---------------------> Job Band (or) Job Code one- many Student <---------------------> courses one- many cart <---------------------> Items one- many Person <---------------------> PhoneNumber,EmailId's one-many Trainer <---------------------> Courses many-many Student <---------------------> courses many-many Account <----------------------> Transaction many-many Customer <----------------------> Products * In ORM Framework we have multiple annotations to support and work with different types of associations 1) @OneToOne <------------> Establishing one-one relationship between Entity classes. 2) @OneToMany <------------> Establishing one-Many relationship between Entity classes. 3) @ManyToOne <------------> Establishing many-one relationship between Entity classes. 4) @ManyToMany <------------> Establishing many-Many relationship between Entity classes. 5) @JoinColumn <------------> To specify the foreign key column name. * We can establish the relationship between entities in ORM Frameworks using two techniques 1) uni-directional(--------->) : Either parent to child (or) child to parent navigation possible. Example ======= ashokit_students -------------------------------------------- ashokit_logins ================ ============== Students Information Students login information | | DB Columns DB Columns | | StudentId login_id StudentName loging_pwd ContactNo login_created_date EmailId DateOfJoining 1) If we want to pull the data using above two database tables that will not possible because there is no common column between the above two tables. 2) To Overcome this problem we need to create common column either in one of the Database Tables. ashokit_students >>>>> Primary Key (student_id) >>>>> Foreign key(login_id(ashokit_logins)) ****** ashokit_logins >>>>> Primary Key (login_id) >>>>> Foreign Key(student_id(ashokit_students)) 2) bi-directional(<-------->) : Both parent to child and child to parent navigation possible. One-To-One Association ======================= * One-to-one association (or) relationship is used to map row of one entity to another row of another entity. * We can achieve this association (or) relationship using annotation "@OneToOne" * As part of this association will be consider below relationship ashokit_portal ============== one To One ashokit_student <---------------> ashokit_login ashokit_students >>>>>>>>>>>>>>> For storing the information about students |-> student_id,student_name,contact_no,email_id,location ashokit_logins >>>>>>>>>>>>>>>> For storing the information about login |-> login_id,username,password,status,student_id(FK) ashokit_students >>>>>>>>>>>>>>>> student_id >>>>>>>>>>>>>>>primary key ashokit_logins >>>>>>>>>>>>>>>>>>login_id >>>>>>>>>>>>>>>>>>primary key student_id >>>>>>>>>>>>>>>> foreign key * We can create the foreign key either any one of the above two tables and hence we can find below mapping in entity classes respectively. 1) We can create the foreign key in "ashokit_logins" table for create foreign key of "student_id" from "ashokit_students" table, In this case we need to define "Has-a" property of Student Class Object in Login Entity Class. @Entity public class Login{ @OneToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER) private Student student; //student_studentId } Database Tables =============== student_id, student_name,student_email,student_contact_no,created_date >>>>>>>>>>>ashokit_students(Table) login_id,login_name,login_pwd,login_status,created_date,student_id >>>>>>>>>>>>>>>>>ashokit_logins(Table) 2) We can create foreign key in "ashokit_students" table for create foregin key of "login_id" from "ashokit_logins" table, In this case we need to defined "Has-a" property of Login Class Object in Student Entity Class. @Entity public class Student{ @OneToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER) @JoinColumn(name="login_id") private Login login; } Database Tables =============== student_id, student_name,student_email,student_contact_no,created_date,login_id >>>>>>>>>>>ashokit_students(Table) login_id,login_name,login_pwd,login_status,created_date >>>>>>>>>>>>>>>>>ashokit_logins(Table) Cascade ======= * CascadeType is one type of enumeration in Java. * Cascade property is used to define at @OneToOne Annotation. Create Student with login information student login setting login object into student object save(student) >>>>> student information will be saved ashokit_students login information will be saved ashokit_logins * The main purpose of this property is when we save parent object associated child object will be saved into database tables respectivey and at the same time when we delete the parent object automatically child object will be deleted. 1) CascadeType.PERSIST: When a new parent entity is persisted (i.e., saved to the database), all associated child entities will also be persisted automatically. 2) CascadeType.REMOVE: When a parent entity is removed (i.e., deleted from the database), all associated child entities will also be removed. 3) CascadeType.MERGE: When a detached parent entity is merged (i.e., its state is updated and then reattached to the persistence context), all associated child entities will also be merged. 4) CascadeType.REFRESH: When a parent entity is refreshed (i.e., its state is reloaded from the database), all associated child entities will also be refreshed. 5) CascadeType.DETACH: When a parent entity is detached from the persistence context (e.g., after a transaction ends), all associated child entities will also be detached. 6) CascadeType.ALL: This is a shorthand for all the above cascade types, meaning that all operations should be cascaded. fetch ===== * fetch property is used to defined at @oneToOne Annotation. * The main purpose of this property is used when we load the parent object need to specify fetch type whether child object should be load or not. * We have two fetch types are below 1) fetch = FetchType.EAGER >>>>>>>> If using this strategy when load the parent object automatically loads the child object into memory. 2) fetch = FetchType.LAZY >>>>>>> If using this strategy when load the parent object it should not load the child objects until need to be called getxxxx(). Student.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_students") public class Student { @Id @Column(name = "student_id") @GeneratedValue(strategy = GenerationType.AUTO) private Integer studentId; @Column(name = "name",nullable = false) private String studentName; @Column(name = "location") private String studentLocation; @Column(name = "email") private String studentEmail; @Column(name = "contact_no") private String studentContactNo; @Column(name = "created_date") @Temporal(TemporalType.DATE) private Date CreatedDate; public Integer getStudentId() { return studentId; } public void setStudentId(Integer studentId) { this.studentId = studentId; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public String getStudentLocation() { return studentLocation; } public void setStudentLocation(String studentLocation) { this.studentLocation = studentLocation; } public String getStudentEmail() { return studentEmail; } public void setStudentEmail(String studentEmail) { this.studentEmail = studentEmail; } public String getStudentContactNo() { return studentContactNo; } public void setStudentContactNo(String studentContactNo) { this.studentContactNo = studentContactNo; } public Date getCreatedDate() { return CreatedDate; } public void setCreatedDate(Date createdDate) { CreatedDate = createdDate; } @Override public String toString() { return "Student [studentId=" + studentId + ", studentName=" + studentName + ", studentLocation=" + studentLocation + ", studentEmail=" + studentEmail + ", studentContactNo=" + studentContactNo+ ", CreatedDate=" + CreatedDate + "]"; } } Login.java ========== package com.ashokit.entity; import java.util.Date; 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.OneToOne; import jakarta.persistence.Table; import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; @Entity @Table(name = "ashokit_logins") public class Login { @Id @Column(name = "login_id") @GeneratedValue(strategy = GenerationType.AUTO) private Integer loginId; @Column(name = "login_name",nullable = false) private String username; @Column(name = "login_pwd",nullable = false) private String password; @Column(name = "login_status",nullable = false) private String status; @Column(name = "created_date") @Temporal(TemporalType.DATE) private Date CreatedDate; //Has-a property(student) student_student_id >>>>> student_id (owing side) @OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY) @JoinColumn(name="student_id") private Student student; public Integer getLoginId() { return loginId; } public void setLoginId(Integer loginId) { this.loginId = loginId; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Date getCreatedDate() { return CreatedDate; } public void setCreatedDate(Date createdDate) { CreatedDate = createdDate; } public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } @Override public String toString() { return "Login [loginId=" + loginId + ", username=" + username + ", password=" + password + ", status=" + status+ ", CreatedDate=" + CreatedDate + "]"; } } StudentDao.java =============== package com.ashokit.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.ashokit.entity.Student; public interface StudentDao extends JpaRepository{ } LoginDao.java ============= package com.ashokit.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.ashokit.entity.Login; public interface LoginDao extends JpaRepository{ } StudentService.java =================== package com.ashokit.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ashokit.dao.StudentDao; import com.ashokit.entity.Student; @Service public class StudentService { @Autowired private StudentDao studentDao; public void saveAllStudents(List students) { List saveAll = studentDao.saveAll(students); saveAll.forEach(student -> System.out.println(student)); } } LoginService.java ================= package com.ashokit.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ashokit.dao.LoginDao; import com.ashokit.entity.Login; @Service public class LoginService { @Autowired private LoginDao loginDao; public void saveAll(List logins) { List saveAll = loginDao.saveAll(logins); saveAll.forEach(login -> System.out.println(login)); } } 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 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.entity.Login; import com.ashokit.entity.Student; import com.ashokit.service.LoginService; @SpringBootApplication public class Application implements CommandLineRunner { @Autowired private LoginService loginService; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) throws Exception { //prepared the two students information Student st = new Student(); st.setStudentName("Mahesh"); st.setStudentLocation("Hyderabad"); st.setStudentContactNo("123456789"); st.setStudentEmail("mahesh.ashokit@gmail.com"); st.setCreatedDate(new Date()); Student st1 = new Student(); st1.setStudentName("Ashok"); st1.setStudentLocation("Delhi"); st1.setStudentContactNo("123456789"); st1.setStudentEmail("ashok.ashokit@gmail.com"); st1.setCreatedDate(new Date()); //preparing the two logins for two students Login login = new Login(); login.setUsername("mahesh.ashokit@gmail.com"); login.setPassword("welcome@123"); login.setStatus("Active"); login.setCreatedDate(new Date()); login.setStudent(st); Login login1 = new Login(); login1.setUsername("ashok.ashokit@gmail.com"); login1.setPassword("welcome@123"); login1.setStatus("Active"); login1.setCreatedDate(new Date()); login1.setStudent(st1); //calling the service loginService.saveAll(List.of(login,login1)); } } OUTPUT ====== . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ (v3.1.1) Hibernate: create table ashokit_logins (login_id integer not null, created_date date, login_pwd varchar(255) not null, login_status varchar(255) not null, login_name varchar(255) not null, student_id integer, primary key (login_id)) engine=InnoDB Hibernate: create table ashokit_logins_seq (next_val bigint) engine=InnoDB Hibernate: insert into ashokit_logins_seq values ( 1 ) Hibernate: create table ashokit_students (student_id integer not null, created_date date, contact_no varchar(255), email varchar(255), location varchar(255), name varchar(255) not null, primary key (student_id)) engine=InnoDB Hibernate: create table ashokit_students_seq (next_val bigint) engine=InnoDB Hibernate: insert into ashokit_students_seq values ( 1 ) Hibernate: alter table ashokit_logins drop index UK_ilhahntqtxfsps3yff398kkki Hibernate: alter table ashokit_logins add constraint UK_ilhahntqtxfsps3yff398kkki unique (student_id) Hibernate: alter table ashokit_logins add constraint FKrm6erxc9ju27mm2q3xx822iy7 foreign key (student_id) references ashokit_students (student_id) Hibernate: select next_val as id_val from ashokit_logins_seq for update Hibernate: update ashokit_logins_seq set next_val= ? where next_val=? Hibernate: select next_val as id_val from ashokit_students_seq for update Hibernate: update ashokit_students_seq set next_val= ? where next_val=? Hibernate: select next_val as id_val from ashokit_logins_seq for update Hibernate: update ashokit_logins_seq set next_val= ? where next_val=? Hibernate: select next_val as id_val from ashokit_students_seq for update Hibernate: update ashokit_students_seq set next_val= ? where next_val=? Hibernate: insert into ashokit_students (created_date,contact_no,email,location,name,student_id) values (?,?,?,?,?,?) Hibernate: insert into ashokit_logins (created_date,login_pwd,login_status,student_id,login_name,login_id) values (?,?,?,?,?,?) Hibernate: insert into ashokit_students (created_date,contact_no,email,location,name,student_id) values (?,?,?,?,?,?) Hibernate: insert into ashokit_logins (created_date,login_pwd,login_status,student_id,login_name,login_id) values (?,?,?,?,?,?) Login [loginId=1, username=mahesh.ashokit@gmail.com, password=welcome@123, status=Active, CreatedDate=Sat Jul 29 07:14:40 IST 2023] Login [loginId=2, username=ashok.ashokit@gmail.com, password=welcome@123, status=Active, CreatedDate=Sat Jul 29 07:14:40 IST 2023] ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++