CDI交易管理:@Transactional如何工作? [英] CDI Transaction Management: How does @Transactional work?
问题描述
@Named(myBean)$ b在会话范围内拥有简单的CDI bean $ b @SessionScoped
public class MyBean实现Serializable {
private static final long serialVersionUID = 1L;
@Inject
EntityManager em;
...
@Transactional
private void testInsert(){
long t = System.currentTimeMillis(); (int i = 1; i <50000; i ++)
{
create(i);
}
System.out.println(Time:+ Long.toString(System.currentTimeMillis() - t));
}
private void create(int i){
Project p = new Project(Project+ i);
em.persist(p);
}
}
现在,通过EL#{myBean .testInsert}有两件事情似乎很奇怪:
1)将@ Transactional-annotation移到方法create(int)我得到:
javax.persistence.TransactionRequiredException:JBAS011469:
执行此操作需要执行事务(使用
事务或扩展持久性上下文)
2)用@Transactional装饰testInsert(),该函数立即返回,但JPA仍然在后台更新数据库线。该过程需要2分钟才能完成只有50000条记录的INSERT。在这个过程中关闭Java EE应用程序服务器时,后台进程停止,因此在我看来 - testInsert()不是事务性的。
这里误会?如何正确管理交易?
@ javax.transaction.Transactional
是在Java EE 7中引入的拦截器绑定。由CDI为您的bean注入的代理将拦截注释的方法调用以将其包装在事务中。
拦截器不适用于私有方法 - 我想这是你的例子的主要问题。
Having a simple CDI bean in session scope with an entity manager injected:
@Named("myBean")
@SessionScoped
public class MyBean implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
EntityManager em;
...
@Transactional
private void testInsert() {
long t = System.currentTimeMillis();
for (int i=1; i<50000; i++) {
create(i);
}
System.out.println("Time: " + Long.toString(System.currentTimeMillis()-t));
}
private void create(int i) {
Project p = new Project("Project " + i);
em.persist(p);
}
}
Now, when calling the function via EL #{myBean.testInsert} there are two things that seems to be very strange:
1) Moving the @Transactional-annotation to the method create(int) I get:
javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
2) Decorating testInsert() with @Transactional instead, the function returns instantly but JPA is still updating the database within a background thread. The process needs 2 minutes to finish INSERT of only 50000 records. When shutting down the Java EE-application server within the process, the background process stops and thus - in my opinion - testInsert() is not transactional.
What is my general misunderstanding here? How to manage transactions properly?
@javax.transaction.Transactional
is an interceptor binding introduced in Java EE 7. The proxy injected by CDI for your bean will intercept annotated method calls to wrap them in a transaction.
Interceptors do not work for private methods - I suppose that's the main problem with your example.
这篇关于CDI交易管理:@Transactional如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!