此代码是否符合Java EE规范并可以使用?
@Stateless
public class SomeBean {
@Inject
protected TransactedRunner txRunner;
public void someFunc() {
txRuner.run(new Runnable(){
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
});
}
}
@Stateless
public class TransactedRunner {
@TransactionAttribute(REQUIRES_NEW)
public void run(Runnable r) {
r.run();
}
}
在这种情况下,应该启动一个新事务,并且将在runnable中完成的所有事务都将被处理。是对的吗?或者有一些技巧我应该受到EE的影响?
答案 0 :(得分:0)
JavaEE6中有一个名为@Asynchronous的注释,专门用于此目的。这是官方教程:http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html
@Stateless
public class SomeBean {
@Inject
private SomeBean self;
public void someFunc() {
self.doSomething();
}
@TransactionAttribute(REQUIRES_NEW)
@Asynchronous
private void doSomething() {
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
}
}
此外,不允许在EJB容器中创建或管理线程。查看:http://www.oracle.com/technetwork/java/restrictions-142267.html#threads
为什么不允许线程创建和管理?
EJB规范为EJB容器分配管理线程的责任。允许企业bean实例创建和管理线程会干扰容器控制其组件生命周期的能力。线程管理不是业务功能,它是一个实现细节,通常是复杂的和特定于平台的。让容器管理线程可以减轻企业bean开发人员处理线程问题的麻烦。多线程应用程序仍然可行,但多线程控制位于容器中,而不是企业bean中。
答案 1 :(得分:0)
方法"运行"将在交易中执行,这是真的。但它与线程或使用执行程序没有任何共同之处。在您的示例中,调用线程将执行您的"运行"方法。 Runnable接口本身不会为您创建单独的线程。
如果您需要通过单独的线程执行此调用,则可以使用异步调用,或者从EE7开始,可以使用ManagedExecutorService:
http://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html
答案 2 :(得分:0)
这应该按预期工作。但请注意,在一次服务调用期间多次调用txRunner.run可能会导致数据不一致,如果在这些调用之间或期间发生任何事情,例如连接超时,事务超时或节点死亡等。并且调用事务(如果有的话)可能看不到在调用期间完成的更改,直到它本身已经提交。