Spring Data JPA - 使用@Query注解创建数据库查询

x33g5p2x  于2022-10-07 转载在 Spring  
字(9.3k)|赞(0)|评价(0)|浏览(549)

本教程的上一部分描述了我们如何从查询方法的方法名中创建数据库查询。这篇博文描述了如何使用@Query注解来创建数据库查询。

那么,方法名的查询生成策略有以下弱点。

  1. 方法名解析器的特点决定了我们可以创建什么样的查询。如果方法名解析器不支持所需的关键词,我们就不能使用这个策略。
  2. 复杂查询方法的方法名又长又难看。
  3. 没有对动态查询的支持。
    在这篇文章中,我们可以通过使用@Query注解来避免这些弱点。

使用@Query注解创建查询方法

我们可以通过用@Query注解的查询方法来配置所调用的数据库查询。它同时支持JPQLSQL查询,并且通过使用@Query注解指定的查询优先于所有其他的查询生成策略。

让我们来看看如何用@Query注解创建JPQLSQL查询。

创建JPQL查询

我们可以通过以下步骤创建一个带有@Query注解的JPQL查询。

  1. 给我们的存储库接口添加一个查询方法。
  2. @Query注解对查询方法进行注解,并通过将其设置为@Query注解的值来指定调用的查询。
    让我们看看下面的例子,这些例子演示了使用@Query注释创建JPQL查询。

下面的例子显示了用@Query注解创建的查询。

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.emailAddress = ?1")
  User findByEmailAddress(String emailAddress);
}

使用高级LIKE表达式--用@Query创建的手动定义查询的查询执行机制允许在查询定义中定义高级LIKE表达式,如下面的例子中所示。

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.firstname like %?1")
  List<User> findByFirstnameEndsWith(String firstname);
}

在前面的例子中,LIKE分界符(%)被识别,查询被转化为有效的JPQL查询(去除%)。在查询执行时,传递给方法调用的参数被增加了先前识别的LIKE模式。

创建SQL查询

@Query注解允许通过设置nativeQuery标志为true来运行本地查询。

让我们按照下面的步骤来创建一个带有@Query注释的SQL查询。

  1. 在我们的存储库接口中添加一个查询方法。
  2. @Query注解对查询方法进行注解,并通过将其设置为@Query注解的值属性来指定调用的查询。
  3. @Query注解的nativeQuery属性的值设置为true
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import net.guides.springboot2.springboottestingexamples.model.User;

/**
* UserRepository demonstrates the method name query generation.
* 
* @author Ramesh Fadatare
*
*/
@Repository
public interface UserRepository extends JpaRepository<User, Long> {

 @Query(value = "select * from users where first_name like %?1", nativeQuery = true)
 List<User> findByFirstnameEndsWith(String firstname);

 @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
 User findByEmailAddress(String emailAddress);
}

完整的例子

让我们开发一个完整的例子来演示@Query注解的使用,它使用Spring Boot应用程序,通过自动配置快速启动。

使用的工具和技术

  • Spring Boot - 2.0.6.RELEASE
  • JDK - 1.8或更高版本
  • Spring Framework - 5.0.9 RELEASE
  • Spring Data JPA - 2.0.10 RELEASE
  • Maven - 3.2以上
  • IDE - Eclipse或Spring工具套件(STS)。

创建Spring Boot应用程序的方法有很多。最简单的方法是在http://start.spring.io/使用Spring Initializr,它是一个在线Spring Boot应用程序生成器。

pom.xml文件

<?xmlversion="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>net.guides.springboot2</groupId>
    <artifactId>springboot-testing-examples</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>springboot-testing-examples</name>
    <description>Demo project for Spring Boot</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/>
        <!-- lookup parent from repository -->
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

JPA实体 - User.java

在这个例子中,我们存储了User对象,被注释为JPA实体。

package net.guides.springboot2.springboottestingexamples.model;

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
@Table(name = "users")
public class User {
    private long id;
    private String firstname;
    private String lastname;
    private Date startDate;
    private String emailAddress;
    private int age;
    private int active;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getId() {
        return id;
    }

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

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getActive() {
        return active;
    }

    public void setActive(int active) {
        this.active = active;
    }

    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", firstname=" + firstname + ", lastname=" + lastname + ", startDate=" + startDate +
            ", emailAddress=" + emailAddress + ", age=" + age + ", active=" + active + "]";
    }
}
  • User类被注解为@Entity,表明它是一个JPA实体。
  • 用户的id属性被注解为@Id,这样JPA就能识别它是对象的ID。id属性也被注解为@GeneratedValue,以表明该ID应该自动生成。

Spring Data JPA Repository - UserRepository.java

package net.guides.springboot2.springboottestingexamples.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import net.guides.springboot2.springboottestingexamples.model.User;

/**
* UserRepository demonstrates the method name query generation.
* 
* @author Ramesh Fadatare
*
*/
@Repository
public interface UserRepository extends JpaRepository < User, Long > {
    @Query("select u from User u where u.emailAddress = ?1")
    User findByEmailAddress(String emailAddress);

    @Query("select u from User u where u.firstname like %?1")
    List < User > findByFirstnameEndsWith(String firstname);
}

让我们创建一个带有@Query注解的SQL查询。

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import net.guides.springboot2.springboottestingexamples.model.User;

/**
* UserRepository demonstrates the method name query generation.
* 
* @author Ramesh Fadatare
*
*/
@Repository
public interface UserRepository extends JpaRepository < User, Long > {

    @Query(value = "select * from users where first_name like %?1", nativeQuery = true)
    List < User > findByFirstnameEndsWith(String firstname);

    @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
    User findByEmailAddress(String emailAddress);
}

创建一个应用类

在这里,你创建一个包含所有组件的应用程序类。

package net.guides.springboot2.springboottestingexamples;

import java.util.Date;
import java.util.List;

import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import net.guides.springboot2.springboottestingexamples.model.User;
import net.guides.springboot2.springboottestingexamples.repository.UserRepository;

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private UserRepository userRepository;

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

    @Override
    public void run(String...args) throws Exception {
        User user = new User();
        user.setActive(1);
        user.setAge(28);
        user.setEmailAddress("ramesh24@gmail.com");
        user.setFirstname("Ramesh");
        user.setLastname("Fadatare");
        user.setStartDate(new Date());
        user = userRepository.save(user);

        System.out.println("-------------------------------------:: " + user.getId());

        System.out.println(" ---------------@Query ---------------------");
        System.out.println("--------------findByEmailAddress -----------------");

        User user2 = userRepository.findByEmailAddress("ramesh24@gmail.com");
        System.out.println(user2.toString());

        System.out.println(" ---------------@Query ---------------------");
        System.out.println("--------------findByLastname -----------------");

        List < User > user3 = userRepository.findByFirstnameEndsWith("Ramesh");
        System.out.println(user3.get(0).toString());
    }
}

注意,我们使用了UserRepository方法来演示@Query注解。

运行应用程序

我们使用的是Maven,所以我们可以使用**./mvnw spring-boot:run来运行该应用程序。或者你可以用./mvnw clean package**构建JAR文件。然后你可以运行JAR文件:

java -jar target/spring-data-jpa-example-0.1.0.jar

输出

这篇文章的源代码可以在我的GitHub仓库中找到 - https://github.com/RameshMF/spring-data-jpa-tutorial

相关文章