我有一个非Spring应用程序。我想创建一个方面或类似的东西,它应该在之前和之后执行下面的代码,以使我的方法或类事务像Spring的@Transactional注释;
在
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("AdvancedMapping");
/* Create EntityManager */
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
后;
transaction.commit();
em.close();
我该怎么做?我在哪里可以找到类似的教程或示例?
编辑: 顺便说一句,需要在具有@Transactional的方法中使用em。
@Transactional
private int doSomething(String text) {
// Here I should have the "em" which was already taken in the aspect,
// so I can persist something in text
SomeEntityObject seo = new SomeEntityObject();
seo.setText(text);
em.persist(seo);
}
答案 0 :(得分:2)
只需使用AspectJ即可。您可以找到教程和其他文档here。如果使用Maven构建项目,则需要使用AspectJ Maven plugin以简化和自动化方面编译和编织。
一个小例子:
标记注释:
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Transactional {
String value();
}
驱动程序应用程序:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
Application application = new Application();
application.doSomething("foo");
application.doSomethingElse(11);
application.doSomething("bar");
application.doSomethingElse(22);
}
@Transactional("please wrap me")
public int doSomething(String text) {
System.out.println("Doing something with '" + text + "'");
return 42;
}
public void doSomethingElse(int number) {
System.out.println("Doing something else with number " + number);
}
}
交易包装方面:
package de.scrum_master.aspect;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import de.scrum_master.app.Transactional;
@Aspect
public class TransactionalAspect {
@Around("execution(* *(..)) && @annotation(transactional)")
public Object wrapWithTransaction(ProceedingJoinPoint thisJoinPoint, Transactional transactional) throws Throwable {
System.out.println(thisJoinPoint + " -> " + transactional);
// EntityManagerFactory emf = Persistence.createEntityManagerFactory("AdvancedMapping");
// EntityManager em = emf.createEntityManager();
// EntityTransaction transaction = em.getTransaction();
try {
Object result = thisJoinPoint.proceed();
// transaction.commit();
return result;
}
catch (Exception e) {
// transaction.rollback();
throw e;
}
finally {
// em.close();
}
}
}
带有JPA内容的控制台日志已注释掉:
execution(int de.scrum_master.app.Application.doSomething(String)) -> @de.scrum_master.app.Transactional(value=please wrap me)
Doing something with 'foo'
Doing something else with number 11
execution(int de.scrum_master.app.Application.doSomething(String)) -> @de.scrum_master.app.Transactional(value=please wrap me)
Doing something with 'bar'
Doing something else with number 22
答案 1 :(得分:1)
我在原始版本旁边添加了另一个答案,因为似乎可以通过AspectJ从头开始重建@Transactional
,以避免使用Spring容器:
实际上,Spring的声明式事务支持已经 是一个AspectJ方面。 Spring手册描述了how to use @Transactional
with AspectJ without the Spring container。您甚至不需要Spring XML配置,但可以将事务管理器直接注入方面(手册中引用的代码片段):
// construct an appropriate transaction manager
DataSourceTransactionManager txManager = new DataSourceTransactionManager(getDataSource());
// configure the AnnotationTransactionAspect to use it;
// this must be done before executing any transactional methods
AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager);