我正在开发一个公开 REST API 的独立应用程序。
我使用了我能找到的最多的标准库。基本上,我使用 JPA2、Hibernate(和用于依赖注入(inject)的 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
注入(inject)。
一切正常,除了到现在为止,我必须像这样手动处理交易:
@javax.inject.Inject
private EntityManager em;
public void foo() {
try {
em.getTransaction().begin();
doSomething();
em.getTransaction().commit();
} catch() {
em.getTransaction().rollback();
}
}
而且我不想在每次需要交易时都使用 try/catch。在另一个项目中,在 servlet 容器中使用 Spring,我可以简单地这样写:
@Transactional
public void foo() {
doSomething();
}
有没有非spring的解决方案? (我已经使用 Guice 进行依赖注入(inject))。
编辑(对 Adam Siemion 的回答)。以下是我如何通过自定义 Guice 的 EntityManager Provider 创建 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;
}
}
最佳答案
可以绑定(bind)自定义拦截器
TransactionalMethodInterceptor interceptor = new TransactionalMethodInterceptor();
在 Guice 中:
bindInterceptor(annotatedWith(Transactional.class), any(), interceptor);
bindInterceptor(any(), annotatedWith(Transactional.class), interceptor);
但首先将 EntityManager
注入(inject)您的 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图书馆。
关于java - 在独立应用程序中使用@Transactional,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31192272/