我创建了一个使用 Spring Data + Hibernate + JPA + Quartz 的 Web 应用程序。在我的 Quartz 工作之一中,我需要刷新一个实体,因为该实体可能已被用户通过用户界面更改。基本上,实体包含 Quartz 作业的配置,如果实体在作业之外更改,则实体内的数据已过时,所以我想在持久化实体之前刷新,以免它覆盖更新的信息。
由于 Spring Data 确实在存储库上提供了刷新方法,因此我为 Spring Data 中的所有存储库创建了一个自定义实现。
这是我设置自定义实现的方式:
CustomRepository.java(接口)
@NoRepositoryBean
public interface CustomRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
public void refresh(T entity);
}
CustomRepositoryImpl.java(实现)
@NoRepositoryBean
public class CustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements CustomRepository<T, ID> {
private EntityManager entityManager;
public CustomRepositoryImpl(Class<T> domainClass, EntityManager entityManager){
super(domainClass, entityManager);
this.entityManager = entityManager;
}
public void refresh(T entity) {
this.entityManager.refresh(entity);
}
}
CustomRepositoryFactoryBean.java(Spring 的工厂 Bean)
public class CustomRepositoryFactoryBean<T extends JpaRepository<S,ID>,S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> {
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager){
return new CustomRepositoryFactory(entityManager);
}
private static class CustomRepositoryFactory<T, ID extends Serializable> extends JpaRepositoryFactory{
private EntityManager entityManager;
public CustomRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
protected Object getTargetRepository(RepositoryMetadata metadata){
return new CustomRepositoryImpl<T, ID>((Class<T>) metadata.getDomainType(), entityManager);
}
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata){
return CustomRepository.class;
}
}
}
弹簧配置.xml
<jpa:repositories base-package="com.network.socially.data.repositories"
factory-class="com.network.socially.data.repositories.custom.CustomRepositoryFactoryBean">
</jpa:repositories>
当应用程序通过 Tomcat 初始化时,自定义实现的设置似乎有效,但是当我尝试调用刷新方法时,我收到异常。
下面是调用刷新方法的代码:
public void execute(JobExecutionContext context) throws JobExecutionException {
super.logExecution(context);
super.initialize(context);
this.extractObjects();
MyJob myJob = this.myJobRepository.findOne(super.applicationJob.getJobId());
this.myJobRepository.refresh(myJob);
this.myJobRepository.save(myJob);
}
这会引发异常:
Caused by: java.lang.IllegalArgumentException: Entity not managed
at org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:914)
at org.hibernate.ejb.AbstractEntityManagerImpl.refresh(AbstractEntityManagerImpl.java:895)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at $Proxy25.refresh(Unknown Source)
at com.network.socially.data.repositories.custom.CustomRepositoryImpl.refresh(CustomRepositoryImpl.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:333)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:318)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
... 10 more
我不明白为什么不管理实体,因为从数据库中检索实体会导致它在持久性上下文中进行管理。
谁能指出我哪里出错了?我是否需要使用 JTA 而不是 RESOURCE-LOCAL?当我通过 JPA 检索实体时,为什么不管理实体?