我正在开发一个暴露REST API的独立应用程序。
我用我能找到的最标准的库来制作它。基本上,我使用JPA2,Hibernate(和Guice进行依赖注入)。以下是我的主要依赖项:
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.10.Final</version>
</dependency>
EntityManagerFactory
和EntityManager
是通过自定义Guice Provider
注入的。
一切正常,但到目前为止,我必须手动处理交易,如:
@javax.inject.Inject
private EntityManager em;
public void foo() {
try {
em.getTransaction().begin();
doSomething();
em.getTransaction().commit();
} catch() {
em.getTransaction().rollback();
}
}
每次我需要交易时,我都不想使用try / catch。在另一个项目中,将Spring放在servlet容器中,我可以这样编写:
@Transactional
public void foo() {
doSomething();
}
是否有非弹簧解决方案? (我已经使用Guice进行依赖注入)。
编辑(回答Adam Siemion)。这是我如何通过自定义我的Guice的EntityManager提供程序来创建1个EntityManager / Thread。它对我来说似乎仍然很危险,因为可以在下一个事务中使用相同的EntityManager(可能处于脏状态):
public class EntityManagerProvider implements Provider<EntityManager> {
private static ThreadLocal<EntityManager> entityManagerThreadLocal
= new ThreadLocal<>();
@Inject
private EntityManagerFactory entityManagerFactory;
@Override
public EntityManager get() {
EntityManager entityManager = entityManagerThreadLocal.get();
if(entityManager == null) {
entityManager = entityManagerFactory.createEntityManager();
entityManagerThreadLocal.set(entityManager);
}
return entityManager;
}
}
答案 0 :(得分:2)
您可以绑定自定义拦截器
TransactionalMethodInterceptor interceptor = new TransactionalMethodInterceptor();
Guice中的:
bindInterceptor(annotatedWith(Transactional.class), any(), interceptor);
bindInterceptor(any(), annotatedWith(Transactional.class), interceptor);
但首先将EntityManager
注入您的TransactionalMethodInterceptor
:
requestInjection(interceptor);
将拦截对使用Transactional
注释注释的方法的所有调用。
你的拦截器可能是这些方面的东西:
class TransactionalMethodInterceptor implements MethodInterceptor {
@javax.inject.Inject
private EntityManager em;
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
Object result = invocation.proceed();
em.commit();
} catch (Exception e) {
em.rollback();
throw e;
}
}
}
MethodInterceptor
和MethodInvocation
来自aopalliance库。
答案 1 :(得分:1)
我认为您可以将AspectJ用于此类目的。 Kidnly检查这个例子
How to swallow a exception at AfterThrowing in AspectJ
在这种情况下,您应该只在方面声明一次try-catch块