Talk about how to use Spring Data JPA to persist data

1 JPA

JPA is called Java Persistence API (Java Persistence API), it is the Java Persistence specification proposed in jdk 5. It provides developers with an object/association mapping tool to manage relational data in applications, thereby simplifying the persistence of Java objects. Many ORM frameworks implement JPA specifications, such as Hibernate, EclipseLink, etc.

1.1 Java Persistence Framework

There are two ways for the Java Persistence Framework to access the database. A kind of JDBC operation that takes SQL as the core and encapsulates a certain degree, such as: MyBatis framework. The other is based on Java entity classes to establish the mapping relationship between entity classes and database tables, that is, ORM frameworks, such as Hibernate, Spring Data JPA.

1.2 JPA specification

  1. ORM mapping metadata: JPA supports two metadata formats: XML and annotations. Metadata is used to describe the mapping relationship between objects and tables, and the framework will persist entity objects to database tables accordingly.

  2. JPA API: used to manipulate entity objects and perform CRUD operations. For simple CRUD operations, developers do not need to write code.

  3. JPQL query language: query data in an object-oriented way.

1.3 Hibernate

The Hibernate framework can map data model objects in applications to relational database tables.

JPA is a specification, and Hibernate is an implementation framework of JPA.

2 Spring Data JPA

Spring Data JPA is a set of JPA application framework encapsulated on the basis of implementing the JPA specification. Use Spring Data JPA to easily switch between different ORM frameworks without changing the code. The goal of Spring Data JPA is to unify the access persistence layer operation of the ORM framework to improve development efficiency.

Spring Data JPA is just an abstraction layer, mainly used to reduce the amount of boilerplate code required to implement the data access layer for various persistence layer storage. Its JPA implementation layer is implemented using the Hibernate framework.

2.1 Introducing dependency packages

In Spring Boot applications, you only need to open pom.xml and add a Spring Data JPA dependency. This dependency will not only introduce Spring Data JPA, but also transitively introduce Hibernate as a JPA implementation.

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

2.2 Entity class annotation

(1)@Entity

Class annotation, used to identify this entity class is a JPA entity.

(2) @Table (name = "custom table name")

Class annotation, used to customize the table name corresponding to the entity class in the database, the default is the entity class name. Especially those entity class names that are used as database keywords, this annotation will be used to specify the table name.

(3)@Id

Class variable annotation, used to specify the primary key.

(4)@GeneratedValue

Class variable annotations are used to specify the generation strategy of the primary key.

It contains the strategy attribute, which is described as follows:

strategy Description
AUTO Controlled by the program, default option
IDENTITY Generated by the database self-growth model, suitable for MySQL
SEQUENCE Generated by database sequence, suitable for Oracle
Table Generated from the specified table

(5)@Basic

Specify the mapping relationship between the read method of class variables and the database table fields. For getXxxx() methods without any special annotations, the @Basic annotation is attached by default. In other words, unless there are special circumstances, all class variables are annotated with @Basic, and these variables are mapped to the specified table fields.

The @Basic annotation has a fetch attribute to indicate the read strategy. There are two strategies, EAGER and LAZY, which are respectively expressed as active read and lazy loading. The default is EAGER.

(6)@Column

Indicates the description of the column. If the field name is the same as the column name, it can be omitted.

The @Column annotation has the following attributes:

Attributes Description
name The name of the corresponding field in the database table.
length The length of the field. It is valid when the field type is varchar; the default is 255 characters.
nullable Whether it can be a null value, the default is true.
precision and scale Represents precision. When the field type is double, precision represents the total length of the value, and scale represents the number of digits occupied by the decimal point.

(7)@Transient

The annotation of the class variable indicates that the variable is not a field mapping to a database table. Because the default annotation of class variables is @Basic, this annotation will be used for non-persistent class variables in some scenarios.

(8)@Temporal

Class variable annotation (also available on the getXxx method), indicating the time format. The specific instructions are as follows:

grammar Description
@Temporal(TemporalType.DATE) Date, like 2020-10-10
@Temporal(TemporalType.TIME) Time, like 10:10:10
@Temporal(TemporalType.TIMESTAMP) Default value; date + time, like 2020-10-10 10:10:10

Craig Walls gave such an example of entity code:

@Data
@RequiredArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)
@Entity
public class Ingredient {
    @Id
    private final String id;
    private final String name;
    private final Type type;

    public static enum Type {
        WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
    }
}

In addition to applying @Entity and @Id annotations in the example, @NoArgsConstructor annotations are also added at the class level. Because JPA requires entity classes to provide a no-argument constructor, we use Lombok's @NoArgsConstructor annotation to generate this constructor.

The @NoArgsConstructor annotation can also privatize this no-argument constructor (access = AccessLevel.PRIVATE) so that it cannot be called directly from outside.

Because the variables id, name and type of this class have not been initialized, we also need to set force to true and initialize it to null.

Although the @Data annotation will add a parameterized constructor for us, because the @NoArgsConstructor annotation was added before, the parameterized constructor is gone. Therefore, you must add another @RequiredArgsConstructor annotation to force the generation of a parameterized constructor.

2.3 Entity class relationship annotation

Spring Data JPA has four kinds of relationship annotations, they are @OneToOne, @OneToMany, @ManyToOne and @ManyToMany.

These four relationship annotations have two attributes, fetch and cascade.

The fetch attribute is used to specify the data delay loading strategy:

Strategy Description
FetchType.LAZY Default value; lazy loading
FetchType.EAGER Load now

The cascade attribute is used to specify the cascade strategy:

Strategy Description
CascadeType.PERSIST Cascade persistence; when the parent entity is saved, the child entity is also saved at the same time.
CascadeType.MERGE Level union; if the child entity is modified, the child entity (commonly used) will also be saved when the parent entity is saved.
CascadeType.REMOVE Cascading delete; when deleting the parent entity, the associated child entities will be deleted in cascade.
CascadeType.REFRESH Cascading refresh; getting the parent entity will also re-get the latest child entity.
CascadeType.ALL The above four strategies
no Defaults

Because these four annotations can only express a few-to-several relationship between entities, to specify the column field in the database table associated with the entity being operated on, the @JoinColumn annotation is required.

Suppose there is such a set of entity relationships. A user has a password; a user belongs to a department, and a department has multiple users; a user can have multiple roles, and a role can also contain multiple users.

(1)@OneToOne

@OneToOne is used to represent a one-to-one relationship and is placed on the dominant class. For example, the user class has a primary key pwd_id that specifies the password table. Putting @OneToOne on the pwd field of the user class can indicate that the user class and the password class have a one-to-one relationship, and the dominant class is the user class.

@OneToOne
@JoinColumn(name = "pwd_id")
private Password pwd;

You can also not use @JoinColumn, Hibernate will automatically generate related fields in the user table. The default naming rule for fields is "subordinate class name_subordinate primary key", such as password_id.

Sometimes you will see the annotation @PrimaryKeyJoinColumn(name = "..."), in fact it is essentially a combination of @Id and @JoinColumn(name = "...").

(2)@OneToMany

When analyzing the relationship between users and departments, it is found that a user can only belong to one department, and a department can contain multiple users. So if you look at it from the perspective of the department

When analyzing the relationship between users and departments, an employee can only belong to one department, but a department can contain multiple employees. If we look at it from the perspective of the department, there is a one-to-many relationship between departments and employees , Add the following annotation on the Department entity class Department:

1.	@OneToMany
2.	@JoinColumn(name = "department_id")
3.	private List<User> user;

If you do not specify the @JoinColumn annotation, Hibernate will automatically generate an intermediate table to bind users and departments. The default naming rule for this intermediate table is: entity class table name_attribute name specified in entity class. For example, if the department table is named t_department and the associated user collection attribute in the department entity class is named user, the default intermediate table generated is named t_department_user.
In practice, we recommend using the @JoinTable annotation to directly specify the intermediate table:

@OneToMany
@JoinTable(name = " t_department_user ", joinColumns = {
@JoinColumn(name = "department_id") }, inverseJoinColumns = { @JoinColumn(name = "user_id") })
private List<User> users;

The name attribute in @JoinColumn is used to specify the association ID of the table corresponding to the current entity class (department); the inverseJoinColumns attribute is used to specify the association ID of the associated entity class table (employee), and the @JoinColumn annotation is embedded.

(3) @ManyToOne (many to one)

If we look at the relationship between users and departments from the perspective of users, they become a many-to-one relationship (multiple users belong to a department). Add the following annotation to the user entity class User:

@ManyToOne
@JoinColumn(name = "department_id")
private Department department;

(4) @ManyToMany (many to many)

There is a many-to-many relationship between users and roles, because a user can have multiple roles, and a role can also belong to multiple employees. Many-to-many relationships are generally associated by creating an intermediate table, and the @JoinTable annotation is used at this time.

Add the following annotations to the user entity class:

@ManyToMany
@JoinTable(name = "t_user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = {
@JoinColumn(name = "role_id") })
private List<Role> roles;

Add the following annotations to the role entity class:

@ManyToMany
@JoinTable(name = "t_user_role", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns = {
@JoinColumn(name = "user_id") })
private List<User> users;

Guess you like

Origin blog.csdn.net/deniro_li/article/details/108807842