我创建了一个使用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 for Spring)
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;
}
}
}
弹簧-config.xml中
<jpa:repositories base-package="com.network.socially.data.repositories"
factory-class="com.network.socially.data.repositories.custom.CustomRepositoryFactoryBean">
</jpa:repositories>
当应用程序通过Tomcat初始化时,自定义实现的设置似乎有效,但是当我尝试调用refresh方法时,我收到异常。
以下是调用refresh方法的代码:
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检索实体时,为什么不管理实体?
答案 0 :(得分:2)
问题是您在调用refresh()
时需要一个事务。 Spring Data JPA中的所有存储库方法都会自动为您自动执行此操作。最简单的方法是使用Spring的@Transactional
,假设你enabled Spring transaction management。例如:
@Transactional
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);
}
以上假设定义此方法的对象实例是Spring管理的 - 即Spring bean。事务的边界扩展到整个方法。上述方法的缺点是,如果您在多个位置调用refresh()
,则需要确保在每个位置的事务内调用它。
答案 1 :(得分:0)
尝试在合并前使用合并。
library(gpuR)
A <- seq.int(from=0, to=999)
B <- seq.int(from=1000, to=1)
gpuA <- gpuVector(A)
gpuB <- gpuVector(B)
C <- A + B
gpuC <- gpuA + gpuB
all.equal(C, gpuC)
#> [1] "Modes: numeric, S4"
#> [2] "Attributes: < target is NULL, current is list >"
#> [3] "target is numeric, current is igpuVector"
all.equal(C, gpuC[])
#> [1] TRUE