Spring Data JPA @Query 注释示例

x33g5p2x  于2021-10-16 转载在 Spring  
字(5.9k)|赞(0)|评价(0)|浏览(386)

在此页面上,我们将学习使用 Spring Data JPA @Query 注释编写自定义查询。 @Query 注释支持 JPQLNative 查询。 @Query 注释的用途是执行复杂的 SQL 查询并从数据库中检索记录。

P.S 使用 Spring Boot 2.2.5.RELEASE 和 MySQL 数据库进行测试。

什么是 JPQL?

JPQL 代表Java 持久性查询语言。 JPQL 使用实体对象模型而不是数据库表来定义查询。它是一种独立于平台的面向对象查询语言,定义为 Java Persistence API (JPA) 规范的一部分。

JPQL 不是特定于数据库的查询。创建与数据库兼容的 SQL 是 ORM 引擎的责任。

请参阅以下方法,其中我们使用带有 @Query 注释的 JPQL。

/**
* It return the list of first name of customers
*/
@Query(value = "SELECT c.firstName FROM Customer c")
List<Customer> getCustomerFirstName();

这里,Customer 表示实体类的名称,firstName 是该实体的成员变量。

什么是本机查询?

简单来说,Native 查询特定于数据库(引擎)。所有列和表名称必须与数据库中的名称相同。我们还可以编写特定于数据库的函数或关键字。

/**
* It return the list of first name of all customers also.
*/
@Query(value = "SELECT c.first_name FROM customer c", nativeQuery = true)
List<String> getCustomerFirstNameNative();

这里,customer 代表表名,first_name 是该表的列名。

需要依赖

所需的依赖项是 spring-boot-starter-data-jpa 和其他与项目或应用程序相关的依赖项。

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

实体

创建实体类和成员变量。就我而言,Customer 是一个实体,如下所示:
客户.java

package org.websparrow.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Customer {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	private String firstName;
	private String lastName;
	private Long mobile;
	private String country;
	
	// Generate Getters and Setters...
}

1.JPQL

在本节中,我们将看到 @Query 注释的一些示例,我们将在其中使用 JPQL 从数据库中获取记录。所有这些方法都在 CustomerRepository 接口中声明。
CustomerRepository.java

package org.websparrow.repository;

import org.websparrow.entity.Customer;
@Repository
public interface CustomerRepository extends CrudRepository<Customer, Integer> {

}

1.1 获取/检索所有客户的列表:

@Query(value = "SELECT c FROM Customer c")
List<Customer> getCustomer();

1.2 它返回客户的名字列表:

@Query(value = "SELECT c.firstName FROM Customer c")
List<String> getCustomerFirstName();

记住:Customer 表示实体类的名称,firstName 是该实体的成员变量。

1.3 返回国家为美国的客户名字列表:

@Query(value = "SELECT c.firstName FROM Customer c WHERE c.country='USA'")
List<String> getCustomerFirstNameWhereCountry();

1.4 返回用户传递的国家名称的客户列表:

@Query(value = "SELECT c FROM Customer c WHERE c.country= ?1")
List<Customer> getCustomerWhereCountry(String country);

或者,我们也可以使用 @Param 注释来传递国家/地区值:

@Query(value = "SELECT c FROM Customer c WHERE c.country= :country")
List<Customer> getCustomerWhereCountry1(@Param("country") String country);

1.5 (OR 子句) 返回用户传递的国家或姓氏的客户列表:

@Query(value = "SELECT c FROM Customer c WHERE c.country= :country OR c.lastName= :lastName")
List<Customer> getCustomerWhereCountryOrLastName(
		@Param("country") String country,
		@Param("lastName") String lastName);

记住:Customer 表示实体类的名称,countrylastName 是该实体的成员变量。

替代方式;

@Query(value = "SELECT c FROM Customer c WHERE c.country= ?1 OR c.lastName= ?2")
List<Customer> getCustomerWhereCountryOrLastName1(String country,
		String lastName);

1.6****直接绑定到 DTO– 是的,我们也可以将值直接绑定到 JPQL 查询返回的 DTO。例如,实体(表)有5个成员变量(列),而我们要求只有2个成员变量(列),在这种情况下,创建新的DTO并绑定结果如下图:

@Query(value = "SELECT new org.websparrow.dto.CustomerCustomData(c.id, c.country)"
		+ " FROM Customer c")
List<CustomerCustomData> getCustomerIdAndCountry();

DTO 看起来像:

确保 DTO 必须有一个 constructor 接受所有内部变量作为参数。

客户自定义数据.java

package org.websparrow.dto;

public class CustomerCustomData {

	private Integer id;
	private String country;

	public CustomerCustomData(Integer id, String country) {
		super();
		this.id = id;
		this.country = country;
	}
}

new org.websparrow.dto.CustomerCustomData(c.*id*, c.*country*)– 这就是魔法发生的地方。 JPQL 查询通过使用完整的包名称和之前创建的参数化构造函数来创建一个新的 CustomerCustomData。唯一剩下的就是将必要的 Customer 变量(c.id, c.country) 映射到 DTO

1.7(JOINs) 在 JPQL 中,我们可以从两个或多个实体(表)中获取数据。总之,JPQL 也支持 JOIN 子句。例如,我们只需要订购某些东西的那些客户的记录。

@Query(value = "SELECT c FROM Customer c INNER JOIN CustomerOrder co ON c.id=co.customerId")
List<Customer> getCustomerWhoOrdered();

这里的 CutomerOrder 是一个维护订单的实体,每个订单都属于一个特定的客户。

CustomerOrder.java

package org.websparrow.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class CustomerOrder {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	private String name;
	private String description;
	private String orderStatus;
	private Integer customerId;

	// Generate Getters and Setters...
}

记住:CustomerCustomerOrder 都是实体类的名称。

1.8(JOIN with WHERE 子句) 同样,我们也可以在 JPQL 中添加带有“JOIN”的“WHERE”子句。

@Query(value = "SELECT c FROM Customer c INNER JOIN CustomerOrder co "
		+ " ON c.id=co.customerId WHERE co.orderStatus='Rejected'")
List<Customer> getCustomerWhoOrderedRejected();

1.9JPQL 还支持 UPDATEDELETE 除了检索对象(SELECT 查询)和 [ [$28$]] 注释。

/**
* Update customer country where id is something(e.g 9)
 */
@Transactional
@Modifying
@Query(value = "UPDATE Customer c SET c.country='Spain' WHERE c.id= 9")
int updateCustomerCountry();


/**
* Delete customer records whose id is something(e.g 6)
*/
@Transactional
@Modifying
@Query(value = "DELETE FROM Customer c WHERE c.id= 6")
void deleteCustomer();

为什么是 @Transactional@Modifying

每当您尝试修改数据库中的记录时,都必须将其标记为 @Transactional@Modifying,这指示 Spring 可以修改现有记录。

2. 原生查询

@Query 注释还支持本机(特定于数据库的)查询。要使其在 @Query 注释中启用,我们必须设置属性 nativeQuery = *true*,默认情况下它是 false。它将指示 Spring Data JPA 查询特定于/适用于应用程序中使用的数据库。

在这种情况下,ORM 引擎不会转换查询,而是直接执行查询。使用 Native 查询的另一个优点是我们可以在查询中使用特定于数据库的 函数、关键字等

例如,我们的数据库是 MySQL,我只想从一个表中提取 1000 条记录中的 10 条,那么 SQL 查询将是:

SELECT * FROM customer LIMIT 10;

如果数据库是 Oracle 那么,查询将是我猜:

SELECT * FROM customer ROWNUM <= 3;

让我们看看它的实际外观。

1.1 获取/检索所有客户的列表:

@Query(value = "SELECT * FROM customer", nativeQuery = true)
List<Customer> getCustomerNative();

1.2 它返回客户名字的列表:

@Query(value = "SELECT c.first_name FROM customer c", nativeQuery = true)
List<String> getCustomerFirstNameNative();

记住:customer 代表表名,first_name 是表的列名。

1.3 返回国家为美国的客户名字列表:

@Query(value = "SELECT c.first_name FROM customer c WHERE c.country='USA'", nativeQuery = true)
List<String> getCustomerFirstNameWhereCountryNative();

1.4 返回客户仅有的 10 条记录:

@Query(value = "SELECT * FROM customer c LIMIT 10", nativeQuery = true)
List<Customer> getCustomerWhereCountryNative();

同样,您可以使用本机查询尝试其他查询。

相关文章

微信公众号

最新文章

更多