Solon 在編碼上,是強調註解與手寫並重的一個風格。它有個 @Tran
註解,用於事務管理(可以參考:《事務的全域性控制及應用》)。這裡,主要是講講它的手動處理工具類 TranUtils
。
1、看看它的介面:
public final class TranUtils {
//執行事務
public static void execute(Tran tran, RunnableEx runnable) throws Throwable;
//是否在事務中
public static boolean inTrans();
//是否在事務中且只讀
public static boolean inTransAndReadOnly();
//監聽事務
public static void listen(TranListener listener) throws IllegalStateException;
//獲取連結
public static Connection getConnection(DataSource ds) throws SQLException;
//獲取連結代理(方便,用於第三方框架事務對接)
public static Connection getConnectionProxy(DataSource ds) throws SQLException;
}
2、那怎麼用它呢?
- 用它判斷當前是否在事務中?
if(TranUtils.inTrans()){
//正在事務中嘍...
}
- 做一個手動的事務控制(與
@Tran
註解等同效果)
@Component
public class UserService{
//@Tran(policy=TranPolicy.requires_new)
public void addUser(UserModel user) throws Throwable{
TranUtils.execute(new TranAnno().policy(TranPolicy.requires_new), ()->{
//...
});
}
}
@Controller
public class DemoController{
@Inject
UserService userService;
//父回滾,子不回滾
//
//@Tran
@Mapping("/user/add2")
pubblic void addUser2(UserModel user){
TranUtils.execute(new TranAnno(), ()->{
userService.addUser(user);
throw new RuntimeException("不讓你加;但還是加了:(");
});
}
}
- 用它與 dbvisitor (或者別的第三方框架)做事務託管對接
public class SolonManagedDynamicConnection implements DynamicConnection {
private DataSource ds;
public SolonManagedDynamicConnection(DataSource ds) {
this.ds = ds;
}
@Override
public Connection getConnection() throws SQLException {
return TranUtils.getConnectionProxy(ds);
}
@Override
public void releaseConnection(Connection conn) throws SQLException {
conn.close();
}
}
3、TranUtils 是個麻雀工具
麻雀雖然,五臟具全。還可以在執行時,動態新增事務監聽哦。先看看事務監聽器介面:
public interface TranListener {
//順序位
default int getIndex();
//提交之前(可以出異常觸發回滾)
default void beforeCommit(boolean readOnly) throws Throwable;
//完成之前
default void beforeCompletion();
//提交之後
default void afterCommit();
//完成之後
default void afterCompletion(int status);
}
然後,我們試著做一個事務監聽:
@Component
public class UserService {
@Inject
UserDao userDao;
//新增並使用事務
@Tran
public void addUserAndTran(User user){
userDao.add(user);
onUserAdd();
//這裡明確知道有事務
TranUtils.listen(new TranListener() {
@Override
public void afterCompletion(int status) {
System.err.println("---afterCompletion: " + status);
}
});
}
//新增(不使用事務)
public vod addUser(User user){
userDao.add(user);
onUserAdd();
}
private void onUserAdd(){
//這裡不確定是否有事務,先判斷下
if(TranUtils.inTrans()){
TranUtils.listen(new TranListener() {
@Override
public void afterCompletion(int status) {
System.err.println("---afterCompletion: " + status);
}
});
}
}
}