Spring Data JPA 11.细节与增强

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/hgx_suiyuesusu/article/details/81228751

细节与增强

细节

关键字使用细节

Like 与 NotLike

  • 使用时,在传入查询参数时,需要用%%修饰才能够正确的查询到数据.
public void testMyDataJPA(){
        List<Person> people = personRepository.findByLastNameLike("%C%") ;
        // List<Person> people = personRepository.findByLastNameNotLike("%C%") ;
        System.out.println(people);
    }

StartingWith,EndingWith,Containing

  • 使用时不需要用%%修饰.
    • StartingWith:以xxx开头的数据.
    • EndingWith:以xxx结尾的数据.
    • Containing:包含xxx数据,同Like.
		List<Person> persons = personRepository.getByLastNameStartingWithAndIdLessThan("A", 5);
        System.out.println(persons);

        List<Person> persons2 = personRepository.getByLastNameEndingWithAndIdLessThan("C", 40);
        System.out.println(persons2);


方法解析器

  • 支持IgnoreCase为各个属性(例如findByLastnameIgnoreCase(…))或支持忽略大小写的类型(String例如,通常为实例)的所有属性设置标志findByLastnameAndFirstnameAllIgnoreCase(…)。是否支持忽略大小写可能因商店而异,因此请参阅参考文档中有关特定于商店的查询方法的相关章节。

SpEL表达式

  • 从Spring Data JPA 1.4版开始,我们支持在手动定义的查询中使用受限制的SpEL模板表达式@Query。在执行查询时,将根据预定义的变量集评估这些表达式。Spring Data JPA支持一个名为的变量entityName。它的用法是select x from #{#entityName} x。它插入entityName与给定存储库关联的域类型。该entityName解决如下:如果域类型已设置的name属性@Entity的注释,它被使用。否则,使用域类型的简单类名。

  • 当然,您可以User直接在查询声明中使用,但这也需要您更改查询。引用#entityName将User类的潜在未来重映射到不同的实体名称(例如,通过使用@Entity(name = “MyUser”)。

  @Query("select p from #{#entityName} p where p.lastName = ?1")
    List<Person> findByLastNameT(String lastName) ;

可空性注释

  • 您可以使用Spring Framework的可空性注释来表达存储库方法的可空性约束。它们null在运行时提供了一种工具友好的方法和选择性检查,如下所示:

  • @NonNullApi:在包级别上使用,以声明参数和返回值的默认行为是不接受或生成null值。

  • @NonNull:用于必须不是的参数或返回值null (参数上不需要,返回值@NonNullApi适用)。

  • @Nullable:用于可以的参数或返回值null。

  • Spring注释是使用JSR 305注释进行元注释的(一种休眠但广泛传播的JSR)。JSR 305元注释允许IDEA,Eclipse和Kotlin等工具供应商以通用方式提供空安全支持,而无需对Spring注释进行硬编码支持。要为查询方法启用运行时检查可空性约束,需要使用Spring的@NonNullApiin 来激活包级别的非可空性

  • 一旦存在非空默认,就会在运行时验证存储库查询方法调用的可空性约束。如果查询执行结果违反了定义的约束,则抛出异常。当方法返回null但声明为非可空时(默认情况下,存储库所在的包中定义了注释)会发生这种情况。如果您想再次选择可以为空的结果,请有选择地使用@Nullable单个方法。使用本节开头提到的结果包装器类型继续按预期工作:将空结果转换为表示缺席的值。

package com.acme;                                                       

import org.springframework.lang.Nullable;

interface UserRepository extends Repository<User, Long> {

//	在执行时不产生结果的查询时抛出一个EmptyResultDataAccessException。当emailAddress为null时抛出一个IllegalArgumentException。
  User getByEmailAddress(EmailAddress emailAddress);                    

//null执行查询时不返回结果。也接受null作为的值emailAddress
  @Nullable
  User findByEmailAddress(@Nullable EmailAddress emailAdress);    
        
//Optional.empty()执行查询时不返回结果。当emailAddress为null时抛出一个IllegalArgumentException
  Optional<User> findOptionalByEmailAddress(EmailAddress emailAddress); 
}

分页和排序


//方法名直接sql查询条件,参数中带有Pageable则会分页(同时可以带有排序)
Page<User> findByLastName(String lastName, Pageable pageable);

Slice<User> findByLastName(String lastName, Pageable pageable);

List<User> findByLastName(String lastName, Sort sort);

List<User> findByLastName(String lastName, Pageable pageable);

Page<Person> findByLastNameContaining(String lastName, Pageable pageable);

限制查询结果

  • 查询方法的结果可以通过使用first或top关键字来限制,这些关键字可以互换使用。可以附加一个可选的数值,top或者first指定要返回的最大结果大小。如果省略该数字,则假定结果大小为1。以下示例显示如何限制查询大小:
User findFirstByOrderByLastnameAsc();

User findTopByOrderByAgeDesc();

//方法名直接sql查询条件,参数中带有Pageable则会分页(同时可以带有排序)
Page<User> queryFirst10ByLastName(String lastName, Pageable pageable);

Slice<User> findTop3ByLastName(String lastName, Pageable pageable);

List<User> findFirst10ByLastName(String lastname, Sort sort);

List<User> findTop10ByLastName(String lastname, Pageable pageable);

预测

  • Spring Data查询方法通常返回由存储库管理的聚合根的一个或多个实例。但是,有时可能需要根据这些类型的某些属性创建投影。Spring Data允许建模专用返回类型,以更有选择地检索托管聚合的部分视图。

  • Entity实体:

public class Person {
    private Integer id ;
    private String lastName ;
    private String email ;
    private Date birth ;
    private Integer age ;
//...

现在假设我们只想检索人的姓名和邮箱。

(1)基于接口的预测:将查询结果限制为仅名称属性的最简单方法是声明一个接口,该接口公开要读取的属性的访问器方法
  • 投影接口

//用于检索属性子集的投影接口
public interface LastNameAndEmailOnly {

    String getLastName() ;
    String getEmail() ;
}
//这里重要的一点是,此处定义的属性与聚合根中的属性完全匹配。这样做可以添加查询方法
  • dao使用:
List<LastNameAndEmailOnly> findByLastName(String lastName) ;

  • 可以递归使用预测。如果您还想包含一些Address信息,请为其创建一个投影接口,并从声明中返回该接口getAddress(),如以下示例所示:
interface PersonSummary {

 String getLastName() ;
 String getEmail() ; 

 AddressSummary getAddress();

 interface AddressSummary {
    String getCity();
  }
}
(2)基于类别的预测(DTO)
  • 定义投影的另一种方法是使用值类型DTO(数据传输对象),它包含应该检索的字段的属性。这些DTO类型可以与投影界面完全相同的方式使用,除了不发生代理并且不能应用嵌套投影。

如果存储通过限制要加载的字段来优化查询执行,则要加载的字段将根据公开的构造函数的参数名称确定。

以下示例显示了投影DTO:

public class PersonDTO {

    private final  String lastName;

    private final  String email;

	public PersonDTO(String lastName, String email) {
        this.lastName = lastName;
        this.email = email;
    }

    public String getLastName() {
        return lastName;
    }

    public String getEmail() {
        return email;
    }
}
//避免投影DTO的样板代码您可以使用Project Lombok大大简化DTO的代码,
//它提供了一个@Value注释(不要与@Value之前的接口示例中显示的Spring的注释混淆)

按示例查询(QBE)

  • 按示例查询非常适合几种用例:

  • 使用一组静态或动态约束查询数据存储。

  • 频繁重构域对象,而不必担心破坏现有查询。

  • 独立于底层数据存储API工作。

  • 按示例查询也有几个限制:

  • 不支持嵌套或分组的属性约束,例如firstname = ?0 or (firstname = ?1 and lastname = ?2)。

  • 仅支持字符串的开始/包含/结束/正则表达式匹配以及其他属性类型的精确匹配。

  • 例子:

erson person = new Person();                         
person.setLastName("Dave");                          

Example<Person> example = Example.of(person);    
  • 示例不限于默认设置。您可以使用,为字符串匹配,空值处理和特定于属性的设置指定自己的默认值ExampleMatcher:具体参考文档

锁定

  • 要指定要使用的锁定模式,可以@Lock在查询方法上使用注释,如以下示例所示:
    @Lock(LockModeType.READ)
    PersonDTO findByLastName(String lastName) ;
//这个方法声明将导致触发查询中配备了LockModeType的READ

审计

基本

  • Spring Data提供了复杂的支持,可以透明地跟踪创建或更改实体的人员以及更改发生的时间。要从该功能中受益,您必须为您的实体类配备审计元数据,该元数据可以使用注释或通过实现接口来定义。

  • 基于注释的审计元数据
    我们提供@CreatedBy和@LastModifiedBy捕捉谁创建或修改的实体以及用户@CreatedDate和@LastModifiedDate捕捉时的变化发生了。

JPA审计

  • 配置:Spring Data JPA附带了一个实体监听器,可用于触发审计信息的捕获。首先,您必须注册AuditingEntityListener要用于orm.xml文件中持久性上下文中的所有实体.
<persistence-unit-metadata>
  <persistence-unit-defaults>
    <entity-listeners>
      <entity-listener class="….data.jpa.domain.support.AuditingEntityListener" />
    </entity-listeners>
  </persistence-unit-defaults>
</persistence-unit-metadata>
  • 您还可以AuditingEntityListener使用@EntityListeners注释在每个实体的基础上启用,如下所示:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class MyEntity {

}

猜你喜欢

转载自blog.csdn.net/hgx_suiyuesusu/article/details/81228751