Implement one-to-one mapping in Spring Data JPA. In case you want to know what is Spring Data JPA check this article https://codedec.com/tutorials/spring-data-jpa-in-spring-boot-with-example/
What is One To One Mapping in Spring?
The One-to-One mapping means when an instance of one entity is associated with an instance of another entity. For eg, consider a relationship between employee and address; one employee will have one address, so this can be shown using @OneToOne mapping in Spring Data JPA.
Following is the database representation of @OneToOne Relationship
Here, the parent table is ’emp’ which has a foreign key ‘address_id’ referring to address table ‘id’.
The one-to-one mapping can be shown in two ways: unidirectional & bidirectional.
- unidirectional association: In unidirectional association, the parent entity has a relationship field that refers to the child entity. (In the database, the parent table will have the foreign key of child table)
- bidirectional association: In bidirectional association, both the parent and child have a relationship referring to each other. (child table contains the foreign key)
Let us implement one-to-one mapping with Spring Data JPA in the Spring boot Application using unidirectional association.
Implement one to one mapping in Spring Data JPA
Step 1: Open IDE STS- Spring Tool Suite
Step 2: Go to File > Spring Starter Project.
Step 3: Now, fill all the fields as shown below and click Next.
Step 4: Now, Add the dependencies of spring data JPA, MYSQL Driver, Lombok, and spring web.
Now, wait for some time and your project structure will be ready. Go to the pom.xml file and you will see the following dependencies will be added automatically.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
Create a Database in MYSQL
create database one_to_onejpa;
Configure application. properties file
This is the file provided by spring boot to configure JDBC URL, username, password, and driver class name. Also, configure JPA-related information.
spring.jpa.hibernate.ddl-auto=update spring.datasource.url=jdbc:mysql://localhost:3306/one_to_oneJPA spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name =com.mysql.jdbc.Driver spring.jpa.show-sql= true ## Hibernate Properties # The SQL dialect makes Hibernate generate better SQL for the chosen database spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect #To format SQL queries generated by Hibernate spring.jpa.properties.hibernate.format_sql=true #change port number server.port=8888
- spring.jpa.hibernate.ddl-auto is set to update so that whatever changes we will do will be reflected in the schema.
- spring.datasource.url is used to set the URL of the MYSQL DB.
- spring.datasource.username is used to set the username and spring. datasource. password is used to set the password.
- spring.datasource.driver-class-name is used to set the driver class name.
- spring.jpa.show-sql is set to true to show SQL generated by the Hibernate.
- spring.jpa.properties.hibernate.dialect is used to generate better SQL for the chosen database.
- spring.jpa.properties.hibernate.format_sql is set to true to format SQL queries.
- server.port is set to 8888.
Create an Entity Class
Create two Entity Employee and Address that will have an OneToOne relationship.
Employee.java
package com.abc.example.mapping.model; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table; import lombok.Data; @Data @Entity @Table(name = "emp") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "emp_name") private String empName; @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "address_id",referencedColumnName = "id") private Address address; }
Address.java
package com.abc.example.mapping.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import lombok.Data; @Data @Entity @Table(name = "address") public class Address { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "zip_code") private String zipCode; @Column(name = "state") private String state; @Column(name = "country") private String country; }
- @Entity is used to annotate the classes to indicate that they are JPA entities.
- @Table annotation is used to specify the name of the table that should be mapped with entities.
- @Id annotation is used for the primary key.
- The relationship between entities is shown using @OneToOne mapping. The source entity Employee has a field of target entity mapped with @OneToOne. (In the database, the employee table will have a foreign key referring to address table id)
- @JoinColumn is used to specify the foreign key column.
- I have used the Lombok library to remove boilerplate code. In case you want to know what is Lombok check this article https://codedec.com/tutorials/how-to-configure-lombok-into-eclipse/
- Cascade.ALL will make sure that all persistence events that are performed on the parent object will be transferred to the child entity.
Create Repository Interface
The repository here is the DAO layer, which performs all the database operations. EmployeeRepository and AddressRepository interface is created which will extend JPARepository<ClassName, ID>.
EmployeeRepository
package com.abc.example.mapping.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import com.abc.example.mapping.model.Employee; @Repository public interface EmployeeRepository extends JpaRepository<Employee, Long>{ }
AddressRepository
package com.abc.example.mapping.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import com.abc.example.mapping.model.Address; @Repository public interface AddressRepository extends JpaRepository<Address, Long> { Address findByZipCode(String id) ; }
Now, Go to OneToOneJpaApplication class and test our one-to-one relationship.
package com.abc.example.mapping; import java.util.List; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import com.abc.example.mapping.model.Address; import com.abc.example.mapping.model.Employee; import com.abc.example.mapping.repository.AddressRepository; import com.abc.example.mapping.repository.EmployeeRepository; @SpringBootApplication public class OneToOneJpaApplication { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(OneToOneJpaApplication.class, args); EmployeeRepository employeeRepository = context.getBean(EmployeeRepository.class); AddressRepository addressRepository = context.getBean(AddressRepository.class); // Save into db Address address = new Address(); address.setZipCode("425201"); address.setCountry("USA"); address.setState("Newyork"); Employee employee = new Employee(); employee.setEmpName("Nicolas"); employee.setAddress(address); employeeRepository.save(employee); } }
Now, Go to Run As > Spring Boot App. The tables will be created inside the database along with mapping.
Now, if we want to fetch records add the following code in the Application class:
// fetching records List<Employee> list = employeeRepository.findAll(); System.out.println(list); Address addresses = addressRepository.findByZipCode("425201"); System.out.println(addresses);
Run the Application once again and see the console for output. In this way, we learned how to map one-to-one relationships in Spring Data JPA.