5.1.8. 锁定
若要指定要使用的锁定模式,可以在查询方法上使用注释,如以下示例所示:@Lock
例 120。在查询方法上定义锁定元数据
interface UserRepository extends Repository<User, Long> {
// Plain query method
@Lock(LockModeType.READ)
List<User> findByLastname(String lastname);
}
此方法声明会导致触发的查询配备 aof。您还可以通过在存储库界面中重新声明 CRUD 方法并添加注释来定义 CRUD 方法的锁定,如以下示例所示:LockModeType
READ
@Lock
例 121.在 CRUD 方法上定义锁元数据
interface UserRepository extends Repository<User, Long> {
// Redeclaration of a CRUD method
@Lock(LockModeType.READ)
List<User> findAll();
}
5.1.9. 审计
基本
Spring Data提供了复杂的支持,可以透明地跟踪谁创建或更改了实体以及更改发生的时间。若要从该功能中受益,必须为实体类配备可以使用批注或通过实现接口来定义的审核元数据。 此外,必须通过注释配置或 XML 配置启用审核,以注册所需的基础结构组件。 有关配置示例,请参阅特定于商店的部分。
不需要仅跟踪创建和修改日期的应用程序会使其实体实现AuditorAware。
|
基于注释的审核元数据
我们提供捕获创建或修改实体的用户以及何时发生更改的捕获。@CreatedBy
@LastModifiedBy
@CreatedDate
@LastModifiedDate
例 122。被审计的实体
class Customer {
@CreatedBy
private User user;
@CreatedDate
private Instant createdDate;
// … further properties omitted
}
如您所见,注释可以有选择地应用,具体取决于要捕获的信息。 指示在进行更改时捕获的注释可用于 JDK8 日期和时间类型,,,以及旧版 Javaand 的属性。long
Long
Date
Calendar
审核元数据不一定需要位于根级实体中,但可以添加到嵌入的实体中(取决于使用的实际存储),如下面的代码片段所示。
例 123.审核嵌入实体中的元数据
class Customer {
private AuditMetadata auditingMetadata;
// … further properties omitted
}
class AuditMetadata {
@CreatedBy
private User user;
@CreatedDate
private Instant createdDate;
}
基于接口的审核元数据
如果您不想使用注释来定义审核元数据,则可以让您的域类实现接口。它公开所有审核属性的 setter 方法。Auditable
AuditorAware
如果使用任一 or,则审计基础结构需要以某种方式了解当前主体。为此,我们提供了 anSPI 接口,您必须实现该接口来告诉基础架构当前与应用程序交互的用户或系统是谁。泛型类型定义批注属性的类型。@CreatedBy
@LastModifiedBy
AuditorAware<T>
T
@CreatedBy
@LastModifiedBy
以下示例显示了使用 Spring 安全性对象的接口的实现:Authentication
例 124.基于弹簧安全性的实现AuditorAware
class SpringSecurityAuditorAware implements AuditorAware<User> {
@Override
public Optional<User> getCurrentAuditor() {
return Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(User.class::cast);
}
}
该实现访问 Spring 安全性提供的对象,并查找您在实现中创建的自定义实例。我们在这里假设您通过实现公开域用户,但基于发现,您也可以从任何地方查找它。Authentication
UserDetails
UserDetailsService
UserDetails
Authentication
ReactiveAuditorAware
使用响应式基础结构时,您可能希望利用上下文信息来提供信息。 我们提供 anSPI 接口,您必须实现该接口来告诉基础架构当前与应用程序交互的用户或系统是谁。泛型类型定义批注属性的类型。@CreatedBy
@LastModifiedBy
ReactiveAuditorAware<T>
T
@CreatedBy
@LastModifiedBy
以下示例显示了使用反应式 Spring 安全性对象的接口的实现:Authentication
例 125.基于弹簧安全性的实现ReactiveAuditorAware
class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {
@Override
public Mono<User> getCurrentAuditor() {
return ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(User.class::cast);
}
}
该实现访问 Spring 安全性提供的对象,并查找您在实现中创建的自定义实例。我们在这里假设您通过实现公开域用户,但基于发现,您也可以从任何地方查找它。Authentication
UserDetails
UserDetailsService
UserDetails
Authentication
还有一个方便的基类,您可以扩展它以避免手动实现接口方法的需要。这样做会增加域类与 Spring 数据的耦合,这可能是您想要避免的事情。通常,首选基于注释的审核元数据定义方式,因为它侵入性较小且更灵活。AbstractAuditable
5.1.10. JPA 审计
常规审核配置
Spring Data JPA 附带了一个实体侦听器,可用于触发审计信息的捕获。首先,您必须在 arfile 中注册用于持久性上下文中所有实体的 the,如以下示例所示:AuditingEntityListener
orm.xml
例 126.审核配置或.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>
您还可以使用注释按实体启用 the,如下所示:AuditingEntityListener
@EntityListeners
@Entity
@EntityListeners(AuditingEntityListener.class)
public class MyEntity {
}
审计功能要求位于类路径上。spring-aspects.jar |
在类路径上适当修改后,激活审计功能只需将 Spring Data JPAnamespace 元素添加到您的配置中,如下所示:orm.xml
spring-aspects.jar
auditing
例 127.使用 XML 配置激活审核
<jpa:auditing auditor-aware-ref="yourAuditorAwareBean" />
从 Spring Data JPA 1.5 开始,您可以通过使用注释注释配置类来启用审计。您仍然必须修改文件并具有类路径。以下示例演示如何使用注释:@EnableJpaAuditing
orm.xml
spring-aspects.jar
@EnableJpaAuditing
例 128.使用 Java 配置激活审计
@Configuration
@EnableJpaAuditing
class Config {
@Bean
public AuditorAware<AuditableUser> auditorProvider() {
return new AuditorAwareImpl();
}
}
If you expose a bean of type to the , the auditing infrastructure automatically picks it up and uses it to determine the current user to be set on domain types. If you have multiple implementations registered in the , you can select the one to be used by explicitly setting the attribute of .AuditorAware
ApplicationContext
ApplicationContext
auditorAwareRef
@EnableJpaAuditing
5.2. 其他注意事项
5.2.1. 在自定义实现中使用JpaContext
使用多个实例和自定义存储库实现时,需要将 correct连接到存储库实现类中。您可以通过显式命名thein注释来做到这一点,或者,如果是the,则通过使用。EntityManager
EntityManager
EntityManager
@PersistenceContext
EntityManager
@Autowired
@Qualifier
从 Spring Data JPA 1.9 开始,Spring Data JPA 包含一个名为的类,该类允许您获取托管域类,假设它仅由应用程序中的一个实例管理。以下示例演示如何在自定义存储库中使用:JpaContext
EntityManager
EntityManager
JpaContext
例 129.在自定义存储库实现中使用JpaContext
class UserRepositoryImpl implements UserRepositoryCustom {
private final EntityManager em;
@Autowired
public UserRepositoryImpl(JpaContext context) {
this.em = context.getEntityManagerByManagedType(User.class);
}
…
}
此方法的优点是,如果将域类型分配给不同的持久性单元,则不必触摸存储库即可更改对持久性单元的引用。
5.2.2. 合并持久性单元
Spring 支持具有多个持久性单元。但是,有时您可能希望模块化应用程序,但仍要确保所有这些模块在单个持久性单元中运行。为了实现这种行为,Spring Data JPA提供了一个实现,可以根据它们的名称自动合并持久性单元,如以下示例所示:PersistenceUnitManager
例 130.使用 mergegingPersistenceUnitmanager
<bean class="….LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager">
<bean class="….MergingPersistenceUnitManager" />
</property>
</bean>
@Entity类和 JPA 映射文件的类路径扫描
普通 JPA 设置要求在其中列出所有注释映射的实体类。这同样适用于 XML 映射文件。Spring Data JPA 提供了一个配置基本包并选择性地采用映射文件名模式的方法。然后,它会扫描给定包以查找带有注释的类,加载与文件名模式匹配的配置文件,并将它们交给 JPA 配置。后处理器必须按如下方式配置:orm.xml
ClasspathScanningPersistenceUnitPostProcessor
@Entity
@MappedSuperclass
例 131.使用 ClasspathScanningPersistenceUnitPostProcessor
<bean class="….LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitPostProcessors">
<list>
<bean class="org.springframework.data.jpa.support.ClasspathScanningPersistenceUnitPostProcessor">
<constructor-arg value="com.acme.domain" />
<property name="mappingFileNamePattern" value="**/*Mapping.xml" />
</bean>
</list>
</property>
</bean>
从 Spring 3.1 开始,可以直接在 上配置要扫描的包,以启用实体类的类路径扫描。有关详细信息,请参阅JavaDoc。LocalContainerEntityManagerFactoryBean |
5.2.3. CDI 集成
存储库接口的实例通常由容器创建,在使用 Spring 数据时,Spring 是最自然的选择。Spring 为创建 Bean 实例提供了复杂的支持,如创建存储库实例中所述。从版本1.1.0开始,Spring Data JPA附带了一个自定义CDI扩展,允许在CDI环境中使用存储库抽象。扩展是 JAR 的一部分。要激活它,请在类路径中包含 Spring Data JPA JAR。
现在,您可以通过为 and 实现 CDI 创建器来设置基础结构,如以下示例所示:EntityManagerFactory
EntityManager
class EntityManagerFactoryProducer {
@Produces
@ApplicationScoped
public EntityManagerFactory createEntityManagerFactory() {
return Persistence.createEntityManagerFactory("my-persistence-unit");
}
public void close(@Disposes EntityManagerFactory entityManagerFactory) {
entityManagerFactory.close();
}
@Produces
@RequestScoped
public EntityManager createEntityManager(EntityManagerFactory entityManagerFactory) {
return entityManagerFactory.createEntityManager();
}
public void close(@Disposes EntityManager entityManager) {
entityManager.close();
}
}
必要的设置可能因 JavaEE 环境而异。您可能只需要重新声明 aas 为 CDI Bean,如下所示:EntityManager
class CdiConfig {
@Produces
@RequestScoped
@PersistenceContext
public EntityManager entityManager;
}
在前面的示例中,容器必须能够创建 JPA 本身。所有配置所做的只是将 JPA 重新导出为 CDI Bean。EntityManagers
EntityManager
Spring Data JPA CDI 扩展将所有可用实例作为 CDI bean 选取,并在容器请求存储库类型的 Bean 时为 Spring 数据存储库创建代理。因此,获取 Spring 数据存储库的实例是声明属性的问题,如以下示例所示:EntityManager
@Injected
class RepositoryClient {
@Inject
PersonRepository repository;
public void businessMethod() {
List<Person> people = repository.findAll();
}
}
5.3. 弹簧数据转换器
5.3.1. 什么是 Spring 数据转换器?
Spring Data Envers 在 Spring Data JPA 的存储库中提供了典型的 Envers 查询。 它与其他 Spring 数据模块的不同之处在于,它总是与另一个 Spring 数据模块结合使用:Spring Data JPA。
5.3.2. 什么是Envers?
Envers 是一个Hibernate 模块,它为 JPA 实体添加了审计功能。 本文档假设您熟悉Envers,就像Spring Data Envers依赖于正确配置Envers一样。
5.3.3. 配置
作为使用 Spring Data Envers 的起点,您需要一个在类路径上具有 Spring Data JPA 的项目和一个额外的依赖项:spring-data-envers
<dependencies>
<!-- other dependency elements omitted -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-envers</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
这也将项目作为暂时性依赖项引入。hibernate-envers
要启用 Spring Data Envers 和 Spring Data JPA,我们需要配置两个 bean 和一个特殊的:repositoryFactoryBeanClass
@Configuration
@EnableEnversRepositories
@EnableTransactionManagement
public class EnversDemoConfiguration {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("example.springdata.jpa.envers");
factory.setDataSource(dataSource());
return factory;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
}
要实际使用 Spring Data Envers,请将一个或多个存储库添加到 {spring-data-commons-javadoc-base}/org/springframework/data/repository/history/RevisionRepository.html[] 中,方法是将其添加为扩展接口:RevisionRepository
interface PersonRepository
extends CrudRepository<Person, Long>,
RevisionRepository<Person, Long, Long>
{}
第一个类型参数 () 表示实体类型,第二个 () 表示 id 属性的类型,最后一个参数 () 是修订号的类型。 对于默认配置中的 Envers,修订号参数应为 OR。Person Long Long Integer Long |
该存储库的实体必须是启用了 Envers 审核的实体(即,它必须具有注释):@Audited
@Entity
@Audited
class Person {
@Id @GeneratedValue
Long id;
String name;
@Version Long version;
}
5.3.4. 用法
现在,您可以使用 from 方法查询实体的修订,如以下测试用例所示:RevisionRepository
@ExtendWith(SpringExtension.class)
@Import(EnversDemoConfiguration.class)
class EnversIntegrationTests {
final PersonRepository repository;
final TransactionTemplate tx;
EnversIntegrationTests(@Autowired PersonRepository repository, @Autowired PlatformTransactionManager tm) {
this.repository = repository;
this.tx = new TransactionTemplate(tm);
}
@Test
void testRepository() {
Person updated = preparePersonHistory();
Revisions<Long, Person> revisions = repository.findRevisions(updated.id);
Iterator<Revision<Long, Person>> revisionIterator = revisions.iterator();
checkNextRevision(revisionIterator, "John", RevisionType.INSERT);
checkNextRevision(revisionIterator, "Jonny", RevisionType.UPDATE);
checkNextRevision(revisionIterator, null, RevisionType.DELETE);
assertThat(revisionIterator.hasNext()).isFalse();
}
/**
* Checks that the next element in the iterator is a Revision entry referencing a Person
* with the given name after whatever change brought that Revision into existence.
* <p>
* As a side effect the Iterator gets advanced by one element.
*
* @param revisionIterator the iterator to be tested.
* @param name the expected name of the Person referenced by the Revision.
* @param revisionType the type of the revision denoting if it represents an insert, update or delete.
*/
private void checkNextRevision(Iterator<Revision<Long, Person>> revisionIterator, String name,
RevisionType revisionType) {
assertThat(revisionIterator.hasNext()).isTrue();
Revision<Long, Person> revision = revisionIterator.next();
assertThat(revision.getEntity().name).isEqualTo(name);
assertThat(revision.getMetadata().getRevisionType()).isEqualTo(revisionType);
}
/**
* Creates a Person with a couple of changes so it has a non-trivial revision history.
* @return the created Person.
*/
private Person preparePersonHistory() {
Person john = new Person();
john.setName("John");
// create
Person saved = tx.execute(__ -> repository.save(john));
assertThat(saved).isNotNull();
saved.setName("Jonny");
// update
Person updated = tx.execute(__ -> repository.save(saved));
assertThat(updated).isNotNull();
// delete
tx.executeWithoutResult(__ -> repository.delete(updated));
return updated;
}
}
这引用了前面介绍的应用程序上下文配置(在“配置”部分中)。 |
5.3.5. 更多资源
您可以在 Spring数据示例存储库中下载 Spring 数据示例示例,并尝试一下库的工作原理。
您还应该查看 {spring-data-commons-javadoc-base}/org/springframework/data/repository/history/RevisionRepository.html[Javadoc for] 和相关类。RevisionRepository
您可以在* 上使用spring-data-envers标签提问。
Spring Data Envers的源代码和问题跟踪器托管在GitHub上。
6. 附录
附录 A:命名空间引用
元素<repositories />
该元素触发了 Spring 数据存储库基础结构的设置。最重要的属性是,它定义了要扫描 Spring 数据存储库接口的包。请参阅“XML 配置”。下表描述了元素的属性:<repositories />
base-package
<repositories />
表 6.属性
名字
|
描述
|
base-package |
定义要扫描的包,以查找在自动检测模式下扩展的存储库接口(实际接口由特定的 Spring 数据模块确定)。还会扫描已配置软件包下的所有软件包。允许使用通配符。*Repository |
repository-impl-postfix |
定义用于自动检测自定义存储库实现的后缀。名称以配置的后缀结尾的类被视为候选类。默认为。Impl |
query-lookup-strategy |
确定用于创建查找器查询的策略。有关详细信息,请参阅“查询查找策略”。默认为。create-if-not-found |
named-queries-location |
定义搜索包含外部定义查询的属性文件的位置。 |
consider-nested-repositories |
是否应考虑嵌套存储库接口定义。默认为。false |
附录 B:填充器命名空间参考
<填充器 /> 元素
该元素允许通过 Spring 数据存储库基础架构填充数据存储。[1]<populator />
表 7.属性
名字
|
描述
|
locations |
应填充从存储库中查找要读取对象的文件的位置。 |
附录 C:存储库查询关键字
支持的查询方法主题关键字
下表列出了 Spring 数据存储库查询派生机制通常支持的主题关键字,以表达谓词。 有关支持的关键字的确切列表,请参阅特定于商店的文档,因为此处列出的某些关键字可能在特定商店中不受支持。
表 8.查询主题关键字
关键词
|
描述
|
find…By , , , , , read…By get…By query…By search…By stream…By |
常规查询方法通常返回存储库类型、主子类型或结果包装器(如),或任何其他特定于存储的结果包装器。可以用作,或与其他关键字结合使用。Collection Streamable Page GeoResults findBy… findMyDomainTypeBy… |
exists…By |
存在投影,返回通常为结果。boolean |
count…By |
计数投影返回数值结果。 |
delete…By , remove…By |
Delete query method returning either no result () or the delete count.void |
…First<number>… , …Top<number>… |
Limit the query results to the first of results. This keyword can occur in any place of the subject between (and the other keywords) and .<number> find by |
…Distinct… |
使用非重复查询仅返回唯一结果。请参阅特定于商店的文档是否支持该功能。此关键字可以出现在主题(和其他关键字)之间的任何位置。find by |
支持的查询方法谓词关键字和修饰符
下表列出了 Spring 数据存储库查询派生机制通常支持的谓词关键字。 但是,请参阅特定于商店的文档,了解支持的关键字的确切列表,因为此处列出的某些关键字可能在特定商店中不受支持。
表 9.查询谓词关键字
逻辑关键字
|
关键字表达式
|
AND |
And |
OR |
Or |
AFTER |
After , IsAfter |
BEFORE |
Before , IsBefore |
CONTAINING |
Containing , , IsContaining Contains |
BETWEEN |
Between , IsBetween |
ENDING_WITH |
EndingWith , , IsEndingWith EndsWith |
EXISTS |
Exists |
FALSE |
False , IsFalse |
GREATER_THAN |
GreaterThan , IsGreaterThan |
GREATER_THAN_EQUALS |
GreaterThanEqual , IsGreaterThanEqual |
IN |
In , IsIn |
IS |
Is ,,(或无关键字)Equals |
IS_EMPTY |
IsEmpty , Empty |
IS_NOT_EMPTY |
IsNotEmpty , NotEmpty |
IS_NOT_NULL |
NotNull , IsNotNull |
IS_NULL |
Null , IsNull |
LESS_THAN |
LessThan , IsLessThan |
LESS_THAN_EQUAL |
LessThanEqual , IsLessThanEqual |
LIKE |
Like , IsLike |
NEAR |
Near , IsNear |
NOT |
Not , IsNot |
NOT_IN |
NotIn , IsNotIn |
NOT_LIKE |
NotLike , IsNotLike |
REGEX |
Regex , , MatchesRegex Matches |
STARTING_WITH |
StartingWith , , IsStartingWith StartsWith |
TRUE |
True , IsTrue |
WITHIN |
Within , IsWithin |
除了筛选器谓词之外,还支持以下修饰符列表:
表 10.查询谓词修饰符关键字
关键词
|
描述
|
IgnoreCase , IgnoringCase |
与谓词关键字一起使用,用于不区分大小写的比较。 |
AllIgnoreCase , AllIgnoringCase |
忽略所有合适属性的大小写。在查询方法谓词中的某处使用。 |
OrderBy… |
指定静态排序顺序,后跟属性路径和方向(例如)。OrderByFirstnameAscLastnameDesc |
附录 D:存储库查询返回类型
支持的查询返回类型
下表列出了 Spring 数据存储库通常支持的返回类型。 但是,请参阅特定于商店的文档以获取支持的返回类型的确切列表,因为此处列出的某些类型可能在特定商店中不受支持。
地理空间类型(如、和)仅适用于支持地理空间查询的数据存储。 某些存储模块可能会定义自己的结果包装器类型。GeoResult GeoResults GeoPage |
表 11.查询返回类型
返回类型
|
描述
|
void |
表示无返回值。 |
原 |
Java 原语。 |
包装器类型 |
Java 包装器类型。 |
T |
一个独特的实体。期望查询方法最多返回一个结果。如果未找到结果,则返回。多个结果触发 an.null IncorrectResultSizeDataAccessException |
Iterator<T> |
一。Iterator |
Collection<T> |
一个。Collection |
List<T> |
一个。List |
Optional<T> |
爪哇8或番石榴。期望查询方法最多返回一个结果。如果未找到结果,则返回 oris 。多个结果触发 an.Optional Optional.empty() Optional.absent() IncorrectResultSizeDataAccessException |
Option<T> |
要么是斯卡拉,要么是vavrtype。在语义上与前面描述的Java 8的行为相同。Option Optional |
Stream<T> |
A Java 8 .Stream |
Streamable<T> |
该直接的便利扩展公开了流式传输,映射和过滤结果,连接它们等的方法。Iterable |
实现和采用构造函数或工厂方法参数的类型Streamable Streamable |
公开采用 aas 参数的构造函数或/工厂方法的类型。有关详细信息,请参阅返回自定义可流式传输包装器类型。….of(…) ….valueOf(…) Streamable |
瓦夫尔,,,Seq List Map Set |
Vavr 集合类型。有关详细信息,请参阅对 Vavr 集合的支持。 |
Future<T> |
A. 期望对方法进行注释,并且需要启用 Spring 的异步方法执行功能。Future @Async |
CompletableFuture<T> |
A Java 8.期望对方法进行注释,并且需要启用 Spring 的异步方法执行功能。CompletableFuture @Async |
Slice<T> |
一个大小的数据块,指示是否有更多可用数据。需要方法参数。Pageable |
Page<T> |
A 包含其他信息,例如结果总数。需要方法参数。Slice Pageable |
GeoResult<T> |
包含附加信息(如到参考位置的距离)的结果条目。 |
GeoResults<T> |
包含附加信息的列表,例如到参考位置的平均距离。GeoResult<T> |
GeoPage<T> |
Awith,例如到参考位置的平均距离。Page GeoResult<T> |
Mono<T> |
使用反应式存储库发射零个或一个元素的项目反应器。期望查询方法最多返回一个结果。如果未找到结果,则返回。多个结果触发 an.Mono Mono.empty() IncorrectResultSizeDataAccessException |
Flux<T> |
使用反应式存储库发射零个、一个或多个元素的项目反应器。返回的查询还可以发出无限数量的元素。Flux Flux |
Single<T> |
一个 RxJava使用反应式存储库发出单个元素。期望查询方法最多返回一个结果。如果未找到结果,则返回。多个结果触发 an.Single Mono.empty() IncorrectResultSizeDataAccessException |
Maybe<T> |
使用反应式存储库的 RxJavaemitting 零个或一个元素。期望查询方法最多返回一个结果。如果未找到结果,则返回。多个结果触发 an.Maybe Mono.empty() IncorrectResultSizeDataAccessException |
Flowable<T> |
使用反应式存储库的 RxJavaemitting 零个、一个或多个元素。返回的查询还可以发出无限数量的元素。Flowable Flowable |
附录E:常见问题
常见
-
例如,我想获得有关
在 JpaRepository
中调用哪些方法的更详细的日志记录信息。我怎样才能获得它们?
你可以利用 Spring 提供的,如以下示例所示:CustomizableTraceInterceptor
<bean class="
org.springframework.aop.interceptor.CustomizableTraceInterceptor">
<property name="enterMessage" value="Entering $[methodName]($[arguments])"/>
<property name="exitMessage" value="Leaving $[methodName](): $[returnValue]"/>
</bean>
<aop:config>
<aop:advisor advice-ref="customizableTraceInterceptor"
pointcut="execution(public * org.springframework.data.jpa.repository.JpaRepository+.*(..))"/>
</aop:config>
审计
-
我想使用 Spring Data JPA 审计功能,但已将我的数据库配置为在实体上设置修改和创建日期。如何防止 Spring 数据以编程方式设置日期?
将命名空间元素的属性设置为。set-dates
auditing
false