本架构已经注册代理的业务处理对象在运行时都可以对当前使用的数据库会话进行事物管理
本架构事物管理完全基于JDBC的事物特性
本架构支持多数据源事物,但仅仅是一起提交一起回滚,如果在一起提交之时发生程序中断,已经提交的数据源数据则不能回滚
本架构已经注册代理的业务处理对象都可以标注@Transactional注解来管理事物,事物所属的数据源需要指定相应的标识,实际例子如下
@Transactional(mark="erp")
@Override
public boolean changeName(String name, String
newName) throws SQLException {
boolean isChangeName = false;
if (login(name)) {
isChangeName = userDao.upUserInfo(name, newName);
}
return isChangeName;
}
通过指定之后该service方法changeName包含的全部对数据库操作的事物都基于指定标识的数据源
如果userDao的upUserInfo方法操作的数据源和changeName一致,则不需要做其他标注,否则也需要标注相应的数据源标识
@Transactional(mark="crm")
@Override
public boolean delUserInfo(String name) throws SQLException {
delete("user_info");
and("name = ?", name);
return executeUpdate(sql(), parameters()) > 0;
}
加上以上标注之后service方法changeName与dao方法delUserInfo为操纵“erp”与“crm”这两个数据源的事物
两个数据源事物会使用两个数据源会话,在方法调用结束之后会一起提交事物,如果其中某一个环节发生异常,则也会一起回滚事物
当然也可以在service方法changeName中如此标注
@Transactional(mark = { "erp", "crm" })
@Override
public boolean changeName(String name, String newName) throws SQLException {
boolean isChangeName = false;
if (login(name)) {
isChangeName = userDao.upUserInfo(name, newName);
}
return isChangeName;
}
但除非该当个方法同时操纵多个数据源,否则不推荐如此标注
如果方法不显式标注数据源标识,那么会使用默认数据源的事物。
在使用@Transactional注解标注数据源标识的时候可以指定该数据源的事物隔离级别(前提是该数据源支持事物隔离级别),实际例子如下
@Transactional(mark = "erp", level = TransactionalLevel.LEVEL3)
@Override
public boolean changeName(String name, String newName) throws SQLException {
boolean isChangeName = false;
if (login(name)) {
isChangeName = userDao.upUserInfo(name, newName);
}
return isChangeName;
}
事物隔离级别从LEVEL1~LEVEL5分别对应JDBC的定义
LEVEL1 Connection.TRANSACTION_SERIALIZABLE;
LEVEL2 Connection.TRANSACTION_REPEATABLE_READ;
LEVEL3 Connection.TRANSACTION_READ_COMMITTED;
LEVEL4 Connection.TRANSACTION_READ_UNCOMMITTED;
LEVEL5 Connection.TRANSACTION_NONE;
关于事物隔离级别的说明请参考JDBC官方文档,或者各个数据库JDBC驱动官方文档
多次指定不同事物隔离级别最终会以方法结束之前设置的最后一次@Transactional注解为准
在使用@Transactional注解标注数据源标识的时候可以指定该数据源的数据提交模式,实际例子如下
@Transactional(mark = "erp", autoCommit = true)
@Override
public boolean changeName(String name, String newName) throws SQLException {
boolean isChangeName = false;
if (login(name)) {
isChangeName = userDao.upUserInfo(name, newName);
}
return isChangeName;
}
如果进行该指定则该方法范围之内的全部对该数据源操作都将自动提交
其运行原理为运行到该方法体之时,使用另一个设置为自动提交的数据源会话给予该方法使用。
但此标注不会跨方法,如上所示dao方法delUserInfo如果没有加上此标识那么该方法依然使用事物提交。
在使用@Transactional注解标注数据源标识的时候可以指定一个还原点,实际例子如下
@Transactional(mark = "crm", insure = true)
@Override
public boolean delUserInfo(String name) throws SQLException {
delete("user_info");
and("name = ?", name);
return executeUpdate(sql(), parameters()) > 0;
}
如果该方法成功运行且后续方法运行抛出异常导致业务回滚之时,数据源只会回滚到该方法结束时对数据库操作的数据结果。
如果需要保证某一系列事物中某个环节不管整体事物成功与否都必须生效,那便可以如此指定
该功能依赖于指定数据源提供的JDBC驱动是非存在相关支持。