bal*_*ker 18 java hibernate jpa transactions
我正在使用无状态EJB类来更新位于数据库中的持久性实体.EJB中的方法调用完成工作的实现类.我认为造成这个问题的原因是一个被称为Foo实体的实体与一个实体有一个关系Bar.事情已经完成,会话将更新为Foo"级联" Bar.StaleObjectStateException发生a 时,事务未完全回滚,这导致错误,原因很明显.
EJB:
private Session getSession() throws BusinessException {
if( this.sess == null ) {
ServiceLocator locator = new ServiceLocator();
SessionFactory sf = locator.getHibernateSessionFactory();
this.sess = sf.openSession();
}
return this.sess;
}
private ProductionOrderImpl getImpl() throws BusinessException {
if( this.impl == null ) {
this.impl = new ProductionOrderImpl( getSession() );
}
return this.impl;
}
public void cutoffOrders( ) throws Exception {
Transaction tx = null;
try {
tx = getSession().beginTransaction();
getImpl().cutOffFoos(fooTime);
tx.commit();
} catch (StaleObjectStateException e1){
if (tx != null) tx.rollback();
logger.error( "Failed to cutoff order : " + e1 );
throw new Exception( LocaleMgr.getMessage());
}
finally {
// reset implementation object, close session,
// and reset session object
impl = null;
sess.close();
sess = null;
}
}
Run Code Online (Sandbox Code Playgroud)
实施:
public ProductionOrderImpl(Session sess) {
this.sess = sess;
}
public void cutoffFoos( Timestamp fooTime) throws Exception {
... Code that gets fooList ...
if( fooList != null ) {
for( Foo foo: fooList ) {
for( Bar bar : foo.getBarList() ) {
... Code that does things with existing Barlist ...
if( ... ) {
... Code that makes new Bar object ...
foo.getBarList().add(bar2);
}
}
sess.update( foo );
}
}
}
Run Code Online (Sandbox Code Playgroud)
相关的Foo代码:
@OneToMany(cascade=CascadeType.ALL, mappedBy="foo")
@OrderBy("startTime DESC")
Set<Bar> barList;
Run Code Online (Sandbox Code Playgroud)
所以基本上,当事务尝试回滚时,已更改的Bar部分将被回滚,但新的Bar(代码中的bar2)记录仍然存在.
任何指导将不胜感激.就像我说的,我相信这里的错误与sess.update(foo); 可能与某些事情有关autocommit,但默认情况下它应该关闭.
我相信正在发生的事情是,Session.Update(foo)反过来又创建了两个独立的事务.具体来说,Foo更新(SQL UPDATE),但Bar保存(SQL INSERT).由于事务上下文只会真正看到SQL UPDATE,所以它就会反转.将不得不考虑更多..
我试过更改Session.FlushMode到COMMIT但仍然似乎没有解决问题.但它确实可以部分修复问题.除了导致StaleObjectStateException的特定条目外,它将正确回滚条目.该特定条目实际上已从数据库中删除...
好吧,我设法解决了我的问题..我会等待接受它,以防其他人发布更好的东西,更多的东西......值得赏金。
基本上,通过将 更改FlushMode为手动,并手动刷新整个过程,我可以赶上StaleObjectException较早的内容,从而更快地支持代码。我仍然有部分回滚记录的工件。但是,此方法按计划每 2 分钟运行一次,因此在第二遍期间它修复了所有问题。
我将 EJB 更改为具有以下内容:
public void cutoffOrders( ) throws Exception {
Transaction tx = null;
try {
tx = getSession().beginTransaction();
getSession().setFlushMode(FlushMode.MANUAL);
getImpl().cutOffFoos(fooTime);
getSession().flush();
tx.commit();
} catch (StaleObjectStateException e1){
if (tx != null) tx.rollback();
logger.error( "Failed to cutoff order : " + e1 );
throw new Exception( LocaleMgr.getMessage());
}
finally {
// reset implementation object, close session,
// and reset session object
impl = null;
sess.close();
sess = null;
}
}
Run Code Online (Sandbox Code Playgroud)
那么实现代码如下:
public void cutoffFoos( Timestamp fooTime) throws Exception {
... Code that gets fooList ...
if( fooList != null ) {
for( Foo foo: fooList ) {
for( Bar bar : foo.getBarList() ) {
... Code that does things with existing Barlist ...
sess.flush();
if( ... ) {
... Code that makes new Bar object ...
foo.getBarList().add(bar2);
}
}
sess.flush();
sess.update( foo );
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2266 次 |
| 最近记录: |