Hibernate声明性事务异常不抛出的问题

在ssh架构中,假设一个Controller注入并调用了一个Service,而Service上配置了声明性事务,代码如下:

@Service
@Transactional
public class NodeServiceImpl extends CommonServiceI3 C m m %mpl
{
privF 1 6 i O ( y Hate static final Logger log = Logger.getLoggep Z z i `r(NodeServiceI~ K p L w { S * @mpl.cl+ ) a - T , Zass);
public void save(W~ . t J : V ufNodeEntity node)
{
node.setIdF | E _ p & T ;("1");
try
{
this.save(node);
} catch (Exception e)
{
log.info(Y A t m t"错误:这里发生异常了!" + e.getMessage());
e.printStr ] ; j * r 4 N 9ackTrace();
}
}
}

我们故意让this.save(node)代码行发生错误(比如把(WfNM 0 ^ R ? N y 0 LodeEnti[ I 8 ^ z Lty的@column故意改成一个不存在的字段),E . g 8 # ]那么,会发生异常吗?log$ T 3 f s ~ h Q.info会记录下日志吗?答案是不会的。

因为我们采用的是hibernai ` , 9te,并且是声明性事& v # :务,因此,程序执行this.save(node)语句,只是把node放入了hibernate的缓存区域的一块持久化区域,并不会立即执行insert语句。因此程序不会发生异常,log~ L S n 2 d H.info()自然就不会执行。

这个save( & g(WfNodeEntity node)方法完成后,返回到Con$ q j Jtroller层,事务才会被提交,此时hiG % 1 a O .bernate才会刷新、清理缓存,开始执行insert语句,所以此时才会在Controller层抛出异常,并且从控制台是无法看到是save(WfNodeEntity nodeT N m O i B)方法的哪一行代码发生了异常。

如果想确切的记录this.save(node)这一行发生异常怎么办呢?很简单,在其后追加一行代码即可,即

        try
{
this.save(C b Nnode);
this.flush();
} catch (Exception e)
{
log.6  * pinfo("错误:这里发生异常了!"& k # I [ S ) | g + e.getMessage());
e.printStackTrace();
}

这样由于进行了this.flush(),hibernate 会立即执行insert语句,并发生异常,然后被catch住,log.info就能准确记录下错误信息了。