我有一个 batchEdit(List< E>实体),它调用编辑(E实体)函数一个循环,而每个edit()都拥有它自己的事务,因此失败的编辑不会回滚良好的编辑。我目前的实施方式如下:
I have a batchEdit(List<E> entity) that calls an edit(E entity) function in a loop, while each edit() has it's own transaction so that failed edits don't rollback the good edits. I currently have it implemented like so:
选项1
@Stateless @TransactionManagement( value = TransactionManagementType.CONTAINER ) public class Service<E> { @Resource private SessionContext context; @Override @TransactionAttribute( value = TransactionAttributeType.REQUIRES_NEW ) public E edit( E entity ) { //edit code } @Override public List<E> bulkEdit( List<E> entities ) { for(E entity : entities){ //case 1: Regular edit, Does not create a new transaction! //edit(entity); //case 2: Hacky edit, creates a new transaction context.getBusinessObject( Service.class ).editPersistNulls( entity ); } } }根据此stackoverflow讨论, @TransactionAttribute 在我的情况1中被忽略,因为它不跨越任何EJB边界,所以 batchEdit()调用 edit()好像它没有注释。在案例2中使用 context.getBusinessObject()函数来获取bean的引用会导致TransactionManagement批注工作,但是完成所有这些操作似乎很奇怪。
According to this stackoverflow discussion, The @TransactionAttribute is ignored in my case 1 because it doesn't cross any EJB boundaries, so batchEdit() calls edit() as if it wasn't annotated. Using the context.getBusinessObject() function in case 2 to grab a reference of the bean causes the TransactionManagement annotation to work, but it seems really weird to go through all of that.
选项2
我的另一个选择是更改为bean托管交易:
The other option I have is to change to bean managed transactions:
@TransactionManagement( value = TransactionManagementType.BEAN )然后我会失去JPA Magic并且必须管理各地的交易。我不认为我团队中的其他人会想要通过它,所以如果有更好或标准的方法来做到这一点,那么任何见解都会受到赞赏。
But then I would lose the "JPA Magic" and have to manage the transactions everywhere. I don't think other people on my team would want to go through that, so if there's a better or standard way to do this, any insight is appreciated.
我们正在使用OpenJPA和EJB,但我们正试图接近JPA标准。
We are using OpenJPA and EJBs, but we are trying to stay close to the JPA standard.
推荐答案我认为hacky在旁观者的眼中。 context.getBusinessObject 精确存在,这样你就可以做到这一点。
I guess that "hacky" is in the eye of the beholder. context.getBusinessObject exists precisely so that you can do this kind of thing.
另一种选择是使用秒class:
The alternative is to use a second class:
@Stateless public class BulkService<E> { @EJB private Service<E> service; public List<E> bulkEdit( List<E> entities ) { for(E entity : entities) { service.editPersistNulls( entity ); } } }谨防但是,大型实体列表,因为您的包含事务可以超时。
Beware of large entity lists though, as your encompassing transaction can time out.
如果您使用的是符合Java EE 7的服务器实现,那么请考虑使用 JSR-352批处理应用程序支持。
If you're using a Java EE 7 compliant server implementation then consider using the JSR-352 Batch Applications support.
更多推荐
在EJB中获取多个事务的干净,标准方法是什么?
发布评论