One to one relationship mapping annotation @ OneToOne application in SpringData JPA

Keywords: Java Spring Spring Boot

One to one relationship mapping annotation @ OneToOne application in SpringData JPA

Spring Data JPA has one-to-one, one to many, many to many and other relationship mapping. This time, we mainly study one-to-one relationship mapping.
One to one relationship mapping is very common in life. For example, a college student has only one all-in-one card, and one all-in-one card belongs to only one college student. Another example is that the relationship between people and ID cards is also one-to-one.

In Spring Data JPA, the one-to-one mapping relationship can be described in two ways: one is through foreign keys, that is, one entity is associated with another entity through foreign keys, and the other is to save the one-to-one mapping relationship between two entities through association tables.

Next, learn to use Spring Data JPA to realize the one-to-one relationship mapping between person and ID card.

1 - create a SpringBoot Web application based on Spring Data JPA, and create a database named springbootjpa in MySQL.

2 - add related dependencies in pom.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>ch6_1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <!--to configure SpringBoot Core initiator for-->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <!--add to starter modular-->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--JPA Dependent module-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--add to MySQL rely on-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.45</version>

        </dependency>
        <!-- add to JDBC rely on -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

3 - configure the data source in the configuration file application.properties.

server.port=8080
#Data source information configuration
spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?characterEncoding=utf8&useSSL=false
#Database user name
spring.datasource.username = root
#Database password
spring.datasource.password = 123456
#Database driven
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#Specify database type
spring.jpa.database = MYSQL
#Specifies whether to display SQL statements in the log
spring.jpa.show-sql = true
#Specify automatic creation and update of database tables and other configurations
spring.jpa.hibernate.ddl-auto = update
#Make the controller output JSON string format more beautiful
spring.jackson.serialization.indent-output = true
#When uploading files, the default upload file size is 1MB, and max file size sets the upload size of a single file
spring.servlet.multipart.max-file-size=50MB
#The default total file size is 10MB. Max request size sets the size of the total uploaded files
spring.servlet.multipart.max-request-size=500MB

4 - create com.entity package in src/main/java directory, and create persistence classes named Person and IdCard in the package.

Person class:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "person_table")
@JsonIgnoreProperties(value = {"hibernateLazyInitializer"})
public class Person implements Serializable {
    private static final long serialVersionUID = 1L ;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id ;
    private String pname ;
    private String psex ;
    private int page ;
    @OneToOne(
            optional = true , //The ID number can be empty, and the child can have ID number.
            fetch = FetchType.LAZY, //When an entity is loaded, it will not be loaded from the database immediately
            targetEntity = IdCard.class, //The target entity class associated with this entity class
            cascade = CascadeType.ALL //Select cascade new, delete, refresh and update at the same time
    )
    @JoinColumn(
            name = "id_Card_id", //Specifies the id of the Person table_ Card_ The id column is associated with the id column corresponding to the IdCard table as a foreign key
            referencedColumnName = "id", //Specifies the primary key of the reference
            unique = true //Specify ID_ Card_ The value of ID column cannot be repeated
    )
    @JsonIgnore
    private IdCard idCard ;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public String getPsex() {
        return psex;
    }

    public void setPsex(String psex) {
        this.psex = psex;
    }

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public IdCard getIdCard() {
        return idCard;
    }

    public void setIdCard(IdCard idCard) {
        this.idCard = idCard;
    }
}

IdCard class:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Calendar;

@Entity
@Table(name = "idcard_table")
@JsonIgnoreProperties(value = {"hibernateLazyInitializer"})
public class IdCard implements Serializable {
    private static final long serialVersionUID = 1L ;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id ; //Auto increment of primary key
    private String code ;
    @Temporal(value = TemporalType.DATE) //Specify date format
    private Calendar birthday ;
    private String address ;

    @OneToOne(
            optional = false, //People with ID number must exist, person can not be empty.
            fetch = FetchType.LAZY,//When an entity is loaded, it will not be loaded from the database immediately
            mappedBy = "idCard",//Consistent with idCard attribute of Person class
            cascade = CascadeType.ALL //Cascade creation, deletion, refresh and update at the same time
    )
    private Person person ;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Calendar getBirthday() {
        return birthday;
    }

    public void setBirthday(Calendar birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

In the above entity classes, the @ OneToOne annotation has five attributes: targetEntity,cascade,fetch,optional,mappedBy
targetEntity attribute: defines the category of the relationship class.
Cascade attribute: defines the cascading relationship between classes. The defined cascading relationship is treated by the container as taking the same action on the current class object and its associated objects. CascadeType.ALL indicates cascade creation, deletion, refresh and update at the same time.
fetch attribute: there are two types. FetchType.LAZY represents lazy loading, that is, the defined attributes will not be loaded from the database immediately. Fetchtype.eagle is urgent loading, and the defined attributes will be loaded from the database immediately.
optional attribute: when true, the attribute of the corresponding class can be empty; otherwise, it cannot be empty.
mappedBy attribute: it must be defined at the maintained end of the relationship and point to the maintenance end of the relationship.

5 - create a data com.repository package in src/main/java directory, create two interfaces in the package and inherit the JpaRepository interface to realize the data access layer.

import com.entity.IdCard;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface IdCardRepository extends JpaRepository<IdCard, Integer> {
    //Query identity information according to person id
    public IdCard findByPerson_id(Integer id) ;

    //Query identity information based on address and ID number
    public List<IdCard> findByAddressAndCode(String address, String code) ;
}

import com.entity.Person;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface PersonRepository extends JpaRepository<Person, Integer> {
    //Query personnel information according to identity ID
    public Person findByIdCard_id(Integer id) ;

    //Query personnel information according to person name and gender
    public List<Person> findByPnameAndPsex(String pname, String psex) ;

}

6 - create a com.service package in src/main/java directory, which is the business layer. In this package, create the interface of the business layer and the implementation class of the interface.

import com.entity.IdCard;
import com.entity.Person;

import java.util.List;

public interface PersonAndIdCardService {
    public void saveAll() ;
    public List<Person> findAllPerson() ;
    public List<IdCard> findAllIdCard() ;
    public IdCard findByPerson_id(Integer id) ;
    public List<IdCard> findByAddressAndCode(String address, String code) ;
    public Person findByIdCard_id(Integer id) ;
    public List<Person> findByPnameAndPsex(String pname, String psex) ;
    public IdCard getOneIdCard(Integer id) ;
    public Person getOnePerson(Integer id) ;
}
import com.entity.IdCard;
import com.entity.Person;
import com.repository.IdCardRepository;
import com.repository.PersonRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
@Service
public class PersonAndIdCardServiceImpl implements PersonAndIdCardService {
    @Autowired
    private IdCardRepository idCardRepository ;
    @Autowired
    private PersonRepository personRepository ;
    @Override
    public void saveAll() {
        //Save the ID card first. The ID card entity is the maintained end
        IdCard idCard = new IdCard() ;
        idCard.setCode("123456789");
        idCard.setAddress("Nanchang");
        Calendar calendar = Calendar.getInstance() ;
        calendar.set(2021, 11, 11) ;
        idCard.setBirthday(calendar);

        IdCard idCard1 = new IdCard() ;
        idCard1.setCode("1111111111");
        idCard1.setAddress("Nanjing");
        Calendar calendar1 = Calendar.getInstance() ;
        calendar1.set(2021, 11, 12) ;
        idCard1.setBirthday(calendar1);

        IdCard idCard2 = new IdCard() ;
        idCard2.setCode("222222222");
        idCard2.setAddress("Hangzhou");
        Calendar calendar2 = Calendar.getInstance() ;
        calendar2.set(2021, 11, 13) ;
        idCard2.setBirthday(calendar2);

        List<IdCard>  idCards = new ArrayList<>() ;
        idCards.add(idCard) ;
        idCards.add(idCard1) ;
        idCards.add(idCard2) ;
        idCardRepository.saveAll(idCards) ;

        //Storage personnel
        Person p1 = new Person() ;
        p1.setPname("Wang Guodong");
        p1.setPsex("male");
        p1.setPage(24);
        p1.setIdCard(idCard);

        Person p2 = new Person() ;
        p2.setPname("He Zhuoyi");
        p2.setPsex("female");
        p2.setPage(20);
        p2.setIdCard(idCard1);

        Person p3 = new Person() ;
        p3.setPname("Tang naiqiao");
        p3.setPsex("male");
        p3.setPage(24);
        p3.setIdCard(idCard2);

        List<Person> persons = new ArrayList<>() ;
        persons.add(p1) ;
        persons.add(p2) ;
        persons.add(p3) ;
        personRepository.saveAll(persons) ;
    }

    @Override
    public List<Person> findAllPerson() {
        return personRepository.findAll();
    }

    @Override
    public List<IdCard> findAllIdCard() {
        return idCardRepository.findAll();
    }

    @Override
    public IdCard findByPerson_id(Integer id) {
        return idCardRepository.findByPerson_id(id);
    }

    @Override
    public List<IdCard> findByAddressAndCode(String address, String code) {
        return idCardRepository.findByAddressAndCode(address,code);
    }

    @Override
    public Person findByIdCard_id(Integer id) {
        return personRepository.findByIdCard_id(id);
    }

    @Override
    public List<Person> findByPnameAndPsex(String pname, String psex) {
        return personRepository.findByPnameAndPsex(pname, psex);
    }

    @Override
    public IdCard getOneIdCard(Integer id) {
        return idCardRepository.getOne(id);
    }

    @Override
    public Person getOnePerson(Integer id) {
        return personRepository.getOne(id);
    }
}

7 - create com.controller package in src/main/java directory, and create controller class in this package.

import com.entity.IdCard;
import com.entity.Person;
import com.service.PersonAndIdCardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class TestOneToOneController {
    @Autowired
    private PersonAndIdCardService personAndIdCardService ;
    @RequestMapping("/save1")
    public String save(){
        personAndIdCardService.saveAll();
        return "Personnel and identity saved successfully!" ;
    }
    @RequestMapping("/findAllPerson")
    public List<Person> findAllPerson(){
        return personAndIdCardService.findAllPerson() ;
    }
    @RequestMapping("/findAllIdCard")
    public List<IdCard> findAllIdCard(){
        return personAndIdCardService.findAllIdCard() ;
    }
    //Query identity information according to personnel ID
    @RequestMapping("/findByPerson_id")
    public IdCard findByPerson_id(Integer id){
        return personAndIdCardService.findByPerson_id(id) ;
    }
    @RequestMapping("/findByAddressAndCode")
    public List<IdCard> findByAddressAndCode(String address, String code){
        return personAndIdCardService.findByAddressAndCode(address, code) ;
    }
    //Query personnel information according to ID card ID
    @RequestMapping("/findByIdCard_id")
    public Person findByIdCard_id(Integer id){
        return personAndIdCardService.findByIdCard_id(id) ;
    }
    @RequestMapping("/findByPnameAndPsex")
    public List<Person> findByPnameAndPsex(String pname, String psex){
        return personAndIdCardService.findByPnameAndPsex(pname, psex) ;
    }
    @RequestMapping("/getOneIdCard")
    public IdCard getOneIdCard(Integer id){
        return personAndIdCardService.getOneIdCard(id) ;
    }
    @RequestMapping("/getOnePerson")
    public Person getOnePerson(Integer id){
        return personAndIdCardService.getOnePerson(id) ;
    }
}

8 - create a startup class in src/main/java/com directory and run it.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args) ;
    }
}

9 - access http://localhost:8080/save
After saving the data, view the database data as follows:



10 - test related queries
(1) Query personnel information with id 1

(2) Query the identity information of the person with id 1

(3) Query all personnel information

(4) Query all identity information

The remaining queries are self tested and will not be demonstrated this time.

Posted by jonemo on Thu, 11 Nov 2021 14:02:25 -0800