[Spring Boot] Simple query in Spring Boot

The previous article introduced the integration of the JPA framework in the Spring Boot project to implement functions such as adding, deleting, modifying, and querying data. The use of Spring Data JPA is very simple. You only need to inherit JpaRepository to implement complete data operation methods without any data access layer and SQL statements. In addition to these functions and advantages, JPA also has very powerful data query functions. In the past, complex queries required splicing many query conditions, but JPA has a very convenient and elegant way to solve it. Next, let’s talk about the query function of JPA to experience the power of Spring Data JPA.

1. Pre-generation method

We introduced previously that the JpaRepository interface implements all key interfaces for accessing the database, such as exists(), save(), findAll(), delete() and other methods. Create a UserRepository class that inherits the JpaRepository class and has all the pre-generated methods in the parent class.

Calling these methods is also very simple. All the methods owned by the JpaRepository parent class above can be called directly without declaration. The sample code is as follows:

userRespository.existsByld((long) 1);
userRespository.save(user);
userRespository.findById((long) 1);
userRespository.findAll();
userRespository.delete(user);
userRespository.deleteById((long) 1);

2. Customize simple queries

In addition to directly using the basic functions provided by the JpaRepository interface, JPA also supports database operations based on a certain attribute of the entity. Spring Data JPA can automatically generate SQL based on its method name. Supported keywords include find, query, get, read, count, delete, etc., the main syntax is findByXX, queryByXX, getByXX, readByXX, countByXX, etc. To take advantage of this function, you only need to add the corresponding method name to the defined Repository. No specific implementation is required. When used, Spring Data JPA will automatically generate SQL statements based on the method name.

2.1 Attribute query

If you want to query User information based on the name attribute of the entity, just add an interface declaration directly to UserRepository:

User findByUserName(String userName);

As you can see from the above example, we can declare the findByUserName method in the UserRepository interface without implementing it. JPA will automatically generate the corresponding implementation method and its SQL statement.

2.2 Combined query

JPA not only supports single attribute query, but also supports multiple attribute query, and combined query based on And, Or and other keywords. The sample code is as follows:

User findByNameOrPassword (String name, String password);

In the above example, the query is based on the combination of two attributes: name and password. The name and number of the attributes must correspond to the position and number of the parameters one-to-one. It can be continuously added and spliced ​​according to the query conditions, and Spring Data JPA can be parsed and executed correctly.

2.3 JPA keywords

In addition to the And and Or keywords, JPA's custom query basically supports all keywords in SQL syntax, such as like, between, etc.

According to Spring Data's specifications, query methods start with find, read, and get. When query conditions are involved, the attributes of the conditions are connected using condition keywords. It should be noted that the first letter of conditional attributes is capitalized.

3. Custom SQL query

General data query functions can be implemented by defining method names. However, some special scenarios may require customized SQL to implement data query functions. Spring Data JPA can also be perfectly supported. Spring Data JPA provides @Query annotation, through which HQL or SQL can be customized to implement complex data query functions. The following uses a sample program to demonstrate the @Query annotation to implement a custom SQL query.

3.1 HQL query

Use the @Query annotation on the corresponding query method, and write HQL in the annotation to query the content:

@Query("select u from User u")
List<User> findALL();

In the above example, the @Query annotation is used to define a custom HQL statement to implement a custom HQL statement query. Using HQL is more readable than native SQL and enables data manipulation in an object-oriented manner. Things to note when using HQL:

1) From is followed by the entity class , not the data table name.

2) The query field uses the attributes in the entity class instead of the fields in the data table.

3) Select cannot be followed by "*" , it should be an attribute in the entity class.

3.2 SQL query

In addition to supporting HQL statement query, JPA can also directly use SQL statements, which is more intuitive. Just add another parameter "nativeQuery = true":

@Query(value="select * from user u where u.name = ?1",nativeQuery = true)
List<User> findByName(String name);

"?1" in the above example represents the order in the method parameters, and "nativeQuery = true" represents executing the native SQL statement. In addition to passing parameters in this way, you can also use @Param to pass values:

@Query(value="select u from User u where u.password = :password")
List<User> findByPassword(@Param("password") String password);

3.3 Modification and deletion

In addition to custom query statements, the @Query annotation can also be used to define modification and deletion statements, but the @Modifying annotation needs to be added. The sample code is as follows:

@Modifying
@Query("update User set userName = ?1 where id = ?2")
int modifyById(String userName, Long id);

@Modifying
@Query("delete from User where id = ?1")
void deleteUserById(Long id);

In the above example, the @Modifying annotation needs to be added to the custom delete and update statements. It should be noted that when using it, you need to add the @Transactional annotation in the Repository or higher to ensure that the data can be successfully written to the database.

4. Named query

In addition to using the @Query annotation, you can also use annotations such as @NamedQuery and @NameQueries to define named queries. JPA's named query actually gives a name to the SQL query statement. When executing the query, the name is used directly to avoid repeatedly writing JPQL statements and enable the query method to be reused. The following uses a sample program to demonstrate JPA named query.

4.1 Define named queries

In the entity class, the @NamedQuery annotation defines a named query statement. The sample code is as follows:

@Entity
@Table(name="user")
@NamedQuery(name="findAllUser", query="SELECT U FROM User u")
public class User {
    
    

}

In the above example, the name attribute in @NamedQuery specifies the name of the named query, and the query attribute specifies the statement of the named query. If you want to define multiple named query methods, you need to use the @NamedQueries annotation:

@Entity
@Table(name="users")
@NamedQueries({
    
    
        @NamedQuery(name = "findAllUser", query = "SELECT U FROM User u"),
        @NamedQuery(name = "findUserWithId", query = "SELECT U FROM User u WHERE u.id = ?1"),
        @NamedQuery(name = "findUserWithName", query = "SELECT U FROM User u WHERE u.name = :name")
})
public class User {
    
    

}

In the above example, three methods findAllUser(), findUserWithId(), and findUserWithName() are defined in the User entity class.

4.2 Calling named queries

After defining a named query, you can create a query by passing in the name of the named query using the createNamedQuery() method in the EntityManager class:

    @Resource
    EntityManagerFactory emf;
    @Test
    public void testNamedQuery() {
    
    
        EntityManager em = emf.createEntityManager();
        // 根User实体中定义的命名查询
        Query query = em.createNamedQuery("findUserWithName");
        query.setParameter("name", "ysxq");
        List<User> users = query.getResultList();
        for (User u : users) {
    
    
            System.out.println("name:" + u.getName() + ",age:" + u.getAge());
        }
    }

In the above example, use createNamedQuery to create the corresponding query. JPA will first find the corresponding NamedQuery based on the incoming query name, and then execute the query and return the results by calling the getResultList() method.

In addition to using the @NamedQuery annotation, the Named query provided by Spring Data JPA can support writing SQL statements into XML files to achieve separation of SQL and Java code. Create the orm.xml file in the resources/META-INF directory and define the naming method. The reference configuration is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="2.0"
                 xmlns="http://java.sun.com/xml/ns/persistence/orm"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
                 http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/orm_2_2.xsd">
    <named-native-query name="findUserWithName2" result-class="com.example.ysxq.model.User">
        <description>通过name查询用户数据</description>
        <query>select u.id , u.name , u.password , u.age from users u where u.name = :name</query>
    </named-native-query>
</entity-mappings>

Use tags in the orm.xml file to define the named query of queryByName. The effect of using XML is the same as using the @NamedQuery annotation. Just write the SQL statement into the XML file to separate the SQL and Java code, making the defined Java entity class look less complicated and bloated.

Guess you like

Origin blog.csdn.net/weixin_45627039/article/details/132830831