All the code in this article has been successfully implemented

A list,

Spring Data JPA is a set of JPA application framework encapsulated by Spring ORM framework and JPA specification, which enables developers to access and operate databases with minimal code. It provides common functions including add, delete, change, check, etc., and easy to expand! (Official documentation, GitHub address)

Second, the use of

1. Import packages

Introduce the following dependencies in the POM.xml file (version is optional).

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.2.0. RELEASE</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.15</version>
</dependency>
Copy the code

2. Perform basic configuration

Create the application.yml file in the Resources folder and do the following configuration. Note: Application.yml is the same as application.properties, but the former is more concise, hierarchical, and easier to read, so use application.yml.

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/springboot-demo? serverTimezone=Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: anchor#123
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    hibernate:
      ddl-auto: update
    show-sql: true
Copy the code

Including: 1) the “url: JDBC: mysql: / / localhost: 3306 / dataBaseName? ServerTimezone =Shanghai&useUnicode=true&characterEncoding= UTF-8&usessL =true” “DataBaseName” indicates the name of the database to be connected. 2) “username” and “password” are the database account and password (reset if you forget); 3) “driver-class-name” : 4) “database-platform” : database engine 5) “DDL-auto” : update; 6) “show-sql” : indicates whether to print SQL statements of actual operations in logs.

3. Project structure

Four types of convention documents:

1)model: Stores Java classes corresponding to tables in the database.

2)repositoryEach Repository interface curds a table and is a tool for Java applications to manipulate databases.

3)service: Service operations. Generally, a Service class encapsulates a Repository operation and processes the data found in the Repository.

4)controller: a portal that interacts with the outside world (request), receives requests from the outside world and calls methods of the Service layer to process the request;

When creating a class, follow the convention above and place the corresponding class under the corresponding package!

Three, fine solution

(the users table)(the detail table)

1.Model

By default, the name of the entity class must be the same as the name of the table in the database, and the names of the attributes in the class must be the same as the names of the fields in the table. (Match the hump can also match)

@Entity                  /* The table used to annotate the database corresponding to the class */                          
@Table(name = "users")   /* For mapping table names and entity class names */                              
public class User {                                                                  
    @Id                  /* is used to mark the field as the primary key */ in the User class                            
    @GeneratedValue      /* The generation strategy for annotating primary keys */                                    
    private long id;                                                                 
    private String name;                                                               
    private int age;                                                                
    private String description;                                                      
}     /* omit getter, setter methods */                                                   
Copy the code
@Entity 
public class Detail {
    @Id
    @GeneratedValue
    private long id;
    private String position;
    private String phoneNumber;   / / hump
    @Column(name = "education")  
    private String edu;  
}       // omit getter and setter methods
Copy the code

1) @entity is used to tell Spring Boot that the class corresponds to a table in the database. 2) @table If the name of the entity class is different from the name of the database Table it maps to, use the @table annotation to specify the corresponding database Table of the entity class. @table (name = “tableName”) 3) @column If the class attribute name is different from the database Column name, use the @column annotation to specify the corresponding Column of the attribute. Column(name = “columnName”) 4) @generatedValue Generate a unique primary key for an entity. The strategy attribute specifies the generation method. There are four strategies. @generatedValue (strategy= GenerationType.auto) ①IDENTITY: select primary key (ID) from primary key (strategy= generationType.auto) (2) AUTO: JPA automatically selects an appropriate strategy, which is the default option. (AUTO is used by default if strategy is not specified.) MySql does not support the @sequenceGenerator annotation to specify the SEQUENCE name. (4) TABLE: generate the primary key from the TABLE, and the framework generates the primary key from the TABLE simulation sequence. Using this strategy can make the application easier to migrate to the database.

2.Repository

The Repository as a class of database for actual operation (interface), JPA has provided a large number of commonly used method of CURD, encapsulated in JpaRepository, PagingAndSortingRepository, CrudRepository interface, The general case inherits JpaRepository

to use all existing methods. JpaRepository

: where T is the Java class corresponding to the database table and ID is the primary key type of the Java class.
,id>
,id>

@Repository         // Use to annotate database access components (also not written, Spring Boot also works)
public interface UsersRepository extends JpaRepository<User.Long> {    // Used to manipulate the database "users" table
}
Copy the code

You can use the default method out of the box. You need to name a custom method based on the convention. You need to write an HQL/SQL statement for a custom method.

1)The default method

The following methods are provided in the three interfaces and can be used directly.

A. Additions and updates

The S save(S var1) method is used to add and update a single record. Use the overloaded saveAll method (Iterable var1) for multiple records. Note that the two methods return different values. (1) If the primary key of var1 is empty, perform the new operation; ② If the primary key is not empty but does not exist in the database, perform the new operation. 3. When the primary key is not empty and the data corresponding to the primary key exists in the database, the update operation is performed. When the @GeneratedValue annotation is used, even if the ID is assigned a specific value (for example id=999), the save is incremented instead of storing the value of ID as 999 in the database.

B. Sorting and paging

The overloaded method findAll() can pass in objects that Sort or implement Pageable for paging or sorting. The public constructor of Sort is no longer provided in spring-data-commons-2.1.0.release.jar. Instead, sort.by () is used to create Sort instances. Sort.direction. ASC = sort.direction. DESC = sort.direction. DESC = sort.direction. DESC = sort.direction. DESC = sort.direction. DESC = sort.direction. DESC = sort.direction. DESC = sort.direction. DESC = sort.direction. DESC = sort.direction.

public List<User> singleSort(a){     // Single attribute sort
    return usersRepository.findAll(Sort.by(Sort.Direction.ASC, "id"));
}
Copy the code
public List<User> multiSort(a) {    // Multi-attribute sort
    Sort.Order idOrder = Sort.Order.asc("id");
    Sort.Order ageOrder = Sort.Order.desc("age");
    return usersRepository.findAll(Sort.by(idOrder, ageOrder));  // Sort by id and then age
}
Copy the code

PageRequest is a class that implements the Pageable interface, and uses PageRequest. Of () to create an instance of PageRequest. Pagerequest.of () has three overloaded methods that you can choose from on demand.

public List<User> page(int pageNum, int pageSize){              //pageNum indicates the number of pages, and pageSize indicates the number of data items per page
    Sort sort = Sort.by(Sort.Direction.ASC, "id");              // Sort by ID
    PageRequest pageRequest = PageRequest.of(pageNum, pageSize, sort);
    Page<User> userPage = usersRepository.findAll(pageRequest);
    return userPage.getContent();                               // the getContent() method gets the query result,
}                                                               / / actual cases still need to return the total at least: userPage. GetTotalElements ()
Copy the code
C. Perform routine query

The “Example” in this case is Example. You pass an Example object to repository and JPA will use this Example to query the data that matches the criteria. In my opinion, routine query is more complicated than the conventional method, so it is not recommended to use it. To find out, Google.

2) Convention methods

Spring Data JPA framework can automatically generate the corresponding SQL statement according to the agreed method name, the main syntax is findXXBy followed by the attribute name. The Create and Update methods operate on a specific set of data, and the delete method is based on the primary key. The default method is sufficient, so the convention method is basically used for Read. ③ Use method, generate the corresponding query method according to the keywords in the table. FindXX is generally used, but readXX, queryXX, and getXX are also available.

@Repository
public interface UsersRepository extends JpaRepository<User.Long> {
    User findByNameAndAge(String name, int age);
    List<User> readByAgeLessThanEqual(int age);
    List<User> queryByNameStartingWith(String word);
    List<User> getByDescriptionIsNotNull(a);

    @Transactional
    @Modifying
    int deleteByName(String name);    

    List<User> findByAge(Sort sort);             // Convention method sort. Method name findByAge followed by "BySort" will return an error

    Page<User> findByAge(Pageable pageable);     // Convention method paging. Adding "ByPageable" to the end of the method name findByAge will cause an error
}
Copy the code
3) Custom methods

When neither of the above methods meets the operational requirements of the database, you can customize the operational methods using the ** @query ** annotation. (Custom Query statement) @query can be used to add, update, Query, and delete operations. However, it is not recommended to use the default method to add data. Annotations @transactional and @modifying are required when methods are used to add, update, or delete them. A. Using HQL Ordinary @query operations are performed using HQL. HQL statements operate on Java class names and class attribute names, not table and field names of database tables.

public interface UsersRepository extends JpaRepository<User.Long> {
    @Query("SELECT u from User u where u.name = ?1 and u.age = ?2")       / / "? 1" for the first parameter, "? 2" is the second parameter, and so on.
    User findByNameAndAge(String name, int age);

    @Query("select u from User u where u.name = :myName and u.age = :myAge")         // Specify parameters in the method with ": parameter name"
    User findByNameAndAge(@Param("myName") String name, @Param("myAge") int age);    // Use the @param annotation to inject parameters
}
Copy the code

Personally feel used? “” The serial number “method for injecting parameters is more concise. B. Use SQL set “nativeQuery = true” in the @query annotation to use native SQL.

public interface UsersRepository extends JpaRepository<User.Long> {
    @Query(value = "SELECT * from users where name= ? 1", nativeQuery = true)   // Value is a common SQL statement
    User findByName(String name);
}     // You can also use the @param annotation to inject parameters, which is not written here
Copy the code

C. Sorting and paging

@Query("select u from User u where u.age = ? 1)"
List<User> findByAge(int age, Sort sort);           // Custom sorting of methods

@Query("select u from User u where u.age = ? 1)"
Page<User> findByAge(int age, Pageable pageable);   // Custom method paging
Copy the code

D. Sort by value length

public List<User> sortByLength(int age) {
    JpaSort sort = JpaSort.unsafe(Sort.Direction.ASC, "LENGTH(name)");     //LENGTH(attribute name). Jpasort.unsafe must be used, and sort.by () is an error
    return usersRepository.findByAge(age, sort);
}
Copy the code

Note: ① Convention methods are invalid when using @query annotations. FindByName (@query, age); findByName (@query, age); findByName (@query, age); The *** @query annotation takes precedence over the convention. * * *

@Query(value = "SELECT * from users where age= ? 1", nativeQuery = true)
User findByName(int age);
Copy the code

(2) If you do not add ** @modifying and @Transactional** to add, update, or delete, the following exceptions will be raised, respectively.

java.sql.SQLException: Can not issue data manipulation statements with executeQuery().
Copy the code
javax.persistence.TransactionRequiredException: Executing an update/delete query
Copy the code

③ The return value of the update or delete operation method can only be void or int/Integer. Otherwise, the following exceptions will be thrown.

java.lang.IllegalArgumentException: Modifying queries can only use void or int/Integer as return type!
Copy the code

④ Only custom methods can sort by the LENGTH of the value. The default method and the convention method can sort by the LENGTH of the value.

org.springframework.data.mapping.PropertyReferenceException: No property LENGTH(description) found for type User!
Copy the code

⑤ Three incorrect HQL expressions

@Query("SELECT u from users u where u.name = ?1 and u.age = ?2")  // Users could not be identified. HQL operates on entity classes, not database tables (User class, not Users table)
User findByNameAndAge(String name, int age);

@Query("SELECT * from User where name = ? 1 and age = ? 2)"            // HQL does not support "*"
User findByNameAndAge(String name, int age);

@Query("SELECT User from User u where u.name = ?1 and u.age = ?2")   // Start a null pointer error (It confuses me)
User findByNameAndAge(String name, int age);
Copy the code

3.Service

The various methods defined in the Service layer can be used after being injected into Repository. Examples of use are provided in the code repository at the end of this article.

@Component
public class UsersService {

    @Resource                                     // @resource is recommended, @autowired is not recommended.
    private UsersRepository usersRepository;

    /** * Use the default method - add or update a data */
    public User saveUser(User user) {
        return usersRepository.save(user);
    }

    / /...
}
Copy the code

4.Controller

Routine use of

@RestController
@RequestMapping("/user")
public class UsersController {

    @Resource
    private UsersService usersService;

    @RequestMapping("/all")
    public List<User> getAllUsers(a) {
        return usersService.getAllByDefault();
    }

    // Call the UsersService method
    / /...
}
Copy the code