Spring Data JPA Reference Version 2.0.6 官方文档关键内容翻译

范培忠 2018-04-26

Spring Data JPA - Reference Documentation

Version 2.0.6.RELEASE,2018-04-04

一般步骤
1.定义接口
interface PersonRepository extends Repository<Person, Long> { … }
2.定义方法
interface PersonRepository extends Repository<Person, Long> {
  List<Person> findByLastname(String lastname);
}
3.设置代理
JavaConfig或XML。(按:实际在Spring Boot里并不需要。——范培忠)
①JavaConfig
Example 23. Sample annotation based repository configuration
@Configuration
@EnableJpaRepositories("com.acme.repositories")
class ApplicationConfiguration {
  @Bean
  EntityManagerFactory entityManagerFactory() {
    // …
  }
}
②XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jpa="http://www.springframework.org/schema/data/jpa"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/data/jpa
     http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
   <jpa:repositories base-package="com.acme.repositories"/>
</beans>
4.注入并使用
class SomeClient {
  private final PersonRepository repository;
  @AutoWired
  SomeClient(PersonRepository repository) {
    this.repository = repository;
  }
  void doSomething() {
    List<Person> persons = repository.findByLastname("Matthews");
  }
}

Defining repository interfaces
定义持久层接口
As a first step you define a domain class-specific repository interface. The interface must extend Repository and be typed to the domain class and an ID type. If you want to expose CRUD methods for that domain type, extend  CrudRepository  instead of  Repository .
首先需要实现一个指定了域模型的Repository 接口类,该类指定了域与ID类型。如果想扩展CRUD方法,可继承CrudRepository 类代替。

Repository与CrudRepository
一般继承 Repository 接口即可,也可以继承 CrudRepository 接口,它默认定义了一些方法。(其实并不是太好用)
Example 3. CrudRepository interface
public interface CrudRepository<T, ID extends Serializable>
  extends Repository<T, ID> {
  <S extends T> S save(S entity);      
  Optional<T> findById(ID primaryKey); 
  Iterable<T> findAll();               
  long count();                        
  void delete(T entity);               
  boolean existsById(ID primaryKey);   
  // … more functionality omitted.
}
Defining query methods
定义查询方法
The repository proxy has two ways to derive a store-specific query from the method name. It can derive the query from the method name directly, or by using a manually defined query.
repository 代理有两种方式获取针对特定数据库的查询方法。要么直接通过方法名获取,要么手工定义(废话)。

Query lookup strategies
查询策略
The following strategies are available for the repository infrastructure to resolve the query. 
获取查方法的的策略如下。

Keyword
Sample
JPQL snippet
And
findByLastnameAndFirstname
… where x.lastname = ?1 and x.firstname = ?2
Or
findByLastnameOrFirstname
… where x.lastname = ?1 or x.firstname = ?2
Is,Equals
findByFirstname , findByFirstnameIs , findByFirstnameEquals
… where x.firstname = ?1
Between
findByStartDateBetween
… where x.startDate between ?1 and ?2
LessThan
findByAgeLessThan
… where x.age < ?1
LessThanEqual
findByAgeLessThanEqual
… where x.age <= ?1
GreaterThan
findByAgeGreaterThan
… where x.age > ?1
GreaterThanEqual
findByAgeGreaterThanEqual
… where x.age >= ?1
After
findByStartDateAfter
… where x.startDate > ?1
Before
findByStartDateBefore
… where x.startDate < ?1
IsNull
findByAgeIsNull
… where x.age is null
IsNotNull,NotNull
findByAge(Is)NotNull
… where x.age not null
Like
findByFirstnameLike
… where x.firstname like ?1
NotLike
findByFirstnameNotLike
… where x.firstname not like ?1
StartingWith
findByFirstnameStartingWith
… where x.firstname like ?1 (parameter bound with appended  % )
EndingWith
findByFirstnameEndingWith
… where x.firstname like ?1 (parameter bound with prepended  % )
Containing
findByFirstnameContaining
… where x.firstname like ?1 (parameter bound wrapped in  % )
OrderBy
findByAgeOrderByLastnameDesc
… where x.age = ?1 order by x.lastname desc
Not
findByLastnameNot
… where x.lastname <> ?1
In
findByAgeIn(Collection<Age> ages)
… where x.age in ?1
NotIn
findByAgeNotIn(Collection<Age> ages)
… where x.age not in ?1
True
findByActiveTrue()
… where x.active = true
False
findByActiveFalse()
… where x.active = false
IgnoreCase
findByFirstnameIgnoreCase
… where UPPER(x.firstame) = UPPER(?1)
Query creation
The query builder mechanism built into Spring Data repository infrastructure is useful for building constraining queries over entities of the repository. The mechanism strips the prefixes  find…By read…By query…By count…By , and  get…By  from the method and starts parsing the rest of it. The introducing clause can contain further expressions such as a  Distinct   to set a distinct flag on the query to be created. However, the first  By   acts as delimiter to indicate the start of the actual criteria. At a very basic level you can define conditions on entity properties and concatenate them with  And  and  Or .
创建一般查询方法的关键字写法。不用看完,直接看红字就OK。

Example 16. Query creation from method names
interface PersonRepository extends Repository<User, Long> {

  List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

  // Enables the distinct flag for the query
  List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
  List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);

  // Enabling ignoring case for an individual property
  List<Person> findByLastnameIgnoreCase(String lastname);
  // Enabling ignoring case for all suitable properties
  List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);

  // Enabling static ORDER BY for a query
  List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
  List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}

Special parameter handling
Example 17. Using Pageable , Slice and Sort in query methods
也就是分页和排序参数。(Page和Slice的区别就像List和Iterator,所以量大的时候用Slice).
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);
The first method allows you to pass an  org.springframework.data.domain.Pageable  instance to the query method to dynamically add paging to your statically defined query. A  Page  knows about the total number of elements and pages available.
第一个方法使用 Pageable  来分页。一个Page对象知道元素和页的总数。

It does so by the infrastructure triggering a count query to calculate the overall number. As this might be expensive depending on the store used,  Slice  can be used as return instead. A  Slice  only knows about whether there’s a next  Slice  available which might be just sufficient when walking through a larger result set.
分页可能会消耗较多资源,Slice类可以取代它。一个Slice对象仅仅知道是否有下一页(故资源消耗较低)。

Sorting options are handled through the  Pageable  instance too. If you only need sorting, simply add an  org.springframework.data.domain.Sort  parameter to your method. 
Pageable还可以设定排序参数。如果你只是需要排序,可以简单地使用Sort对象作为你方法的参数(很简单吗?)。

As you also can see, simply returning a  List  is possible as well. In this case the additional metadata required to build the actual  Page  instance will not be created (which in turn means that the additional count query that would have been necessary not being issued) but rather simply restricts the query to look up only the given range of entities.
你还能看到,还可以简单地定义仅返回List对象。此时元数据不会别创建,但结果集仍然是以分页后的数据子集返回。

Limiting query results
限制结果集
The results of query methods can be limited via the keywords  first   or  top
Example 18. Limiting the result size of a query with  Top  and  First
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
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);
Async query results
异步查询
Repository queries can be executed asynchronously using  Spring’s asynchronous method execution capability . This means the method will return immediately upon invocation and the actual query execution will occur in a task that has been submitted to a Spring TaskExecutor.
通过使用 Spring’s asynchronous method execution capability 可以实现 异步查询。方法被调用后会立即返回,实际的查询会被提交到Spring TaskExecutor执行。

@Async
Future<User> findByFirstname(String firstname);               ①
@Async
CompletableFuture<User> findOneByFirstname(String firstname); ②
@Async
ListenableFuture<User> findOneByLastname(String lastname);    ③
(按:我只能想到异步调用在大批量插入或更新数据时有实用价值。——范培忠

Using @Query
Example 57. Advanced like-expressions in @Query
public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.firstname like %?1")
  List<User> findByFirstnameEndsWith(String firstname);
}
还可以使用本地查询,即以与数据库产品耦合的方式的SQL语句(所谓本地查询,就是使用原生的sql语句(根据数据库的不同,在sql的语法或结构方面可能有所区别)进行查询数据库的操作)(如果想使用select * 这样的写法,就必须用 nativeQuery
Example 59. Declare native count queries for pagination at the query method using @Query
public interface UserRepository extends JpaRepository<User, Long> {

  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByAndSort(String lastname, Pageable pageable);
}
Using named parameters
使用命名的参数
Example 61. Using named parameters
public interface UserRepository extends JpaRepository<User, Long> {
  @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
  User findByLastnameOrFirstname(@Param("lastname") String lastname,
                                 @Param("firstname") String firstname);
}


@Modifying
Of course you can add custom modifying behaviour by using facilities described in  Custom implementations for Spring Data repositories
你可以添加自定义的修改方法,详见链接。@Modifying注解还是要和@Query注解搭配使用。
Example 64. Declaring manipulating queries
@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
Derived delete queries
扩展删除方法
Spring Data JPA also supports derived delete queries that allow you to avoid having to declare the JPQL query explicitly.
Example 65. Using a derived delete query
interface UserRepository extends Repository<User, Long> {
  void deleteByRoleId(long roleId);

  @Modifying
  @Query("delete from User u where user.role.id = ?1")
  void deleteInBulkByRoleId(long roleId);
}
Transactionality
自定义事务控制
CRUD methods on repository instances are transactional by default. For reading operations the transaction configuration  readOnly  flag is set to  true , all others are configured with a plain  @Transactional  so that default transaction configuration applies. For details see JavaDoc of  SimpleJpaRepository . If you need to tweak transaction configuration for one of the methods declared in a repository simply redeclare the method in your repository interface as follows:
CRUD方法已经默认使用了简单的事务。比如在查询时已经将readOnly设为true。其它会设置为普通的 @Transactional。你如果想扩展事务控制,则进行自定义。

Example 98. Custom transaction configuration for CRUD
@Transactional(readOnly = true)
public interface UserRepository extends CrudRepository<User, Long> {
  @Override
  @Transactional(timeout = 10)
  public List<User> findAll();

  @Modifying
  @Transactional
  @Query("delete from User u where u.active = false")
  void deleteInactiveUsers();
}
Another possibility to alter transactional behaviour is using a facade or service implementation that typically covers more than one repository. Its purpose is to define transactional boundaries for non-CRUD operations:
还有种可能就是你希望在facade或者service里去修改事务行为。此时通常你会使用多个或多次持久类。

Example 99. Using a facade to define transactions for multiple repository calls
@Service
class UserManagementImpl implements UserManagement {
  //...
  @Transactional
  public void addRoleToAllUsers(String roleName) {
    Role role = roleRepository.findByName(roleName);
    for (User user : userRepository.findAll()) {
      user.addRole(role);
      userRepository.save(user);
    }
  }
  //...
}
Note that you will have to activate  <tx:annotation-driven />  or use  @EnableTransactionManagement  explicitly to get annotation based configuration at facades working. 
注意你得在框架配置里激活事务。

Locking
加锁
To specify the lock mode to be used the  @Lock  annotation can be used on query methods:
Example 101. Defining lock metadata on query methods
interface UserRepository extends Repository<User, Long> {
  // Plain query method
  @Lock(LockModeType.READ)
  List<User> findByLastname(String lastname);
}
Creating repository instances
创建持久层实例
In this section you create instances and bean definitions for the repository interfaces defined. One way to do so is using the Spring namespace that is shipped with each Spring Data module that supports the repository mechanism although we generally recommend to use the Java-Config style configuration.
可以用XML创建,现在推荐使用Java Config来创建。

XML configuration
Example 21. Enabling Spring Data repositories via XML
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.springframework.org/schema/data/jpa"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

  <repositories base-package="com.acme.repositories" />

</beans:beans>
JavaConfig
The repository infrastructure can also be triggered using a store-specific  @Enable${store}Repositories  annotation on a JavaConfig class. For an introduction into Java-based configuration of the Spring container, see the r eference documentation. [ 1 ]
A sample configuration to enable Spring Data repositories looks something like this.
Example 23. Sample annotation based repository configuration
@Configuration
@EnableJpaRepositories("com.acme.repositories")
class ApplicationConfiguration {

  @Bean
  EntityManagerFactory entityManagerFactory() {
    // …
  }
}

附注:
1.Repository→CrudRepository→JpaRepository 继承关系如是。JpaRepository 实现了一系列常用方法,继承它可免常用方法定义。
2.若entity某字段不想被映射,则使用@Transient 注解

范培忠 2018-04-26

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值