歡迎您光臨本站 註冊首頁

jSqlBox 3.0.0發布, 自帶分散式事務的 Java ORM 工具

←手機掃碼閱讀     admin @ 2019-09-06 , reply:0

jSqlBox3.0.0 發布

jSqlBox 是一個建立在 DbUtils 內核上的 Java 全功能資料庫持久層工具,具備跨資料庫(80 多種方言)、DD L生成、分頁、多種SQL寫法、分庫分表、聲明式事務、分散式事務、主從、實體 CURD、實體關聯查詢、ActiveRecord、Sql 模板等功能。

本次更新主要內容:支持分庫分表的分散式事務

Gtx 事務是 jSqlBox3.0.0 新增的分散式事務模塊,它的總體思路和 Seata 類似,也是通過生成反向記錄來自動回滾,減小對業務的侵入,但 jSqlBox 採用的思路是將分散式事務建立在 ORM 工具之上,不是分析SQL 內容,而是記錄實體的插入、刪除、修改操作,以生成回滾記錄。這樣一來,在實現難度上就降低了一個等級,以犧牲 SQL 支持來達到最好的跨資料庫兼容性,支持所有資料庫。在具體實現上,它通過採用最大保證完成模式結合全局記錄鎖的方案,架構請參見 Bag 分散式事務對 SAGA 分散式事務的改進一文。
image

以下為一個分散式事務的配置和演示:

public class GtxTest {
	SqlBoxContext[] ctx = new SqlBoxContext[3];

	private static DataSource newTestDataSource() {
		HikariDataSource ds = new HikariDataSource();
		ds.setDriverClassName("org.h2.Driver");
		ds.setJdbcUrl("jdbc:h2:mem:" + new Random().nextLong() // random h2 ds name
				+ ";MODE=MYSQL;DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT=0");
		ds.setUsername("sa");
		ds.setPassword("");
		return ds;
	}

	@Before
	public void init() {
		SqlBoxContext lock = new SqlBoxContext(newTestDataSource());
		lock.setName("lock");
		lock.executeDDL(lock.toCreateDDL(GtxId.class));
		lock.executeDDL(lock.toCreateDDL(GtxLock.class));
		lock.executeDDL(lock.toCreateGtxLogDDL(Usr.class));
		GtxConnectionManager lockCM = new GtxConnectionManager(lock);
		for (int i = 0; i < 3; i++) {
			ctx[i] = new SqlBoxContext(newTestDataSource());
			ctx[i].setName("db");
			ctx[i].setDbCode(i);
			ctx[i].setConnectionManager(lockCM);
			ctx[i].setMasters(ctx);
			ctx[i].executeDDL(ctx[i].toCreateDDL(GtxTag.class));
			ctx[i].executeDDL(ctx[i].toCreateDDL(Usr.class));
		}
	}

	public void Div0Test() {
		ctx[0].startTrans();
		try {
			new Usr().insert(ctx[0]);
			new Usr().insert(ctx[1]);
			new Usr().insert(ctx[1]);
			new Usr().insert(ctx[2]);
			System.out.println(1 / 0);//強制出錯
			ctx[0].commitTrans();
		} catch (Exception e) {
			TxResult result=ctx[0].rollbackTrans();
			GtxUnlockServ.forceUnlock(ctx[0], result);
		}
		Assert.assertEquals(0, ctx[0].eCountAll(Usr.class));
		Assert.assertEquals(0, ctx[1].eCountAll(Usr.class));
		Assert.assertEquals(0, ctx[2].eCountAll(Usr.class));
	}
}

上例是最簡單的一個分散式事務演示,包含了數據源配置和 DDL 建表。GTX 事務如果在事務提交中出錯,無論有無部分事務提交發生,只要資料庫沒有down機,在任意時刻網線中斷,數據的最終一致性都能保證,不象 XA 協議有可能會有數據不一致的情況發生。

上例 GtxUnlockServ.forceUnlock(ctx[0], result) 方法僅用於單元測試,實際項目中應該去掉這一行,而改成用GtxUnlockServ.start(ctx, loopInterval , maxLoopQty);方法開啟一個單獨的解鎖服務,第二個參數為解鎖間隔,單位為秒,必須設置成一個遠大於資料庫事務超時時間的值,第三個參數可以設為 0,表示沒有最大解鎖次數限制。

jSqlBox 的分散式事務支持分庫、分表,以及指定鎖伺服器的序號,這樣如果沒有一個高性能(雲)鎖伺服器,可以通過配置一個鎖伺服器群來提高事務處理性能,當然這種情況下,鎖伺服器序號的指定通常是與業務相關的,例如紅包轉賬分散式事務,可以紅包的 ID 取模作為鎖伺服器序號。具體示例請詳見 wiki 及單元測試目錄下的 GtxShardDbTbLockDbTest.java

jSqlBox 分散式事務的構想幾乎和 Seata 項目開源時同時提出,但從完成度來看差不多,這並不表示本人水平高,一個人干翻了 Seata,而是因為與 ORM 工具整合成一體的分散式事務,在編寫難度上要遠遠小於Seata 這種分析 SQl 語法、從底層代理數據源的第三方工具,而且 jSqlBox 的分散式事務只支持一組直連的 DataSource,不提供微服務的調用介面。

本次更新還包括以下內容: 
1.  在 demo 目錄下演示了使用 Beetl 作為 SQL 模板。例如以下是一個使用 Beetl 模板的調用,通過與 Text 類的結合使用,可以方便地利用 IDE 功能快速定位到模板文本: 
List<Map> usrs = ctx.tQueryForMapList(SelectUsers1.class, bind("age", 50, "name", null));

2.  JAVA8 類中引入 $,a$,c$ 靜態簡化寫法, 例如在 Dao-benchmark 項目中,以下這種 SQL 寫法是支持實體字體名重構的:
Listresult = gctx().eFindBySample(sample, " or ", $(u::getCode), "=?", param("efg"));
其中的$(u::getCode)靜態方法會返回"code"這個實體屬性名,也就是資料庫的列名(通常約定資料庫列名命名與實體屬性名一致)

3. JDBPRO 中新增 noNull 方法,用於 like 查詢時的非空判斷,使用示例:
ctx.iQueryForMapList("select * from a where 1=1",noNull("and name like ?","%",name,"%"));

4. 一些其它改進:
如 TinyTx 類不再使用,改名為 TinyTxAOP,jDialects 模塊中 ColumnModel 類中的 length 欄位被刪除,並修正了 precision 和 scale 在設定浮點數的錯誤。

5. 另外以下與 jSqlBox 相關的子項目也一併更新到 3.0.0 版,就不再另發更新資訊了,有以下子項目:
jDialects 支持80多種資料庫的分頁、類型變換、DDL 生成、實體源碼生成的資料庫方言工具 
jTransactions 一個單獨的事務工具,含分散式事務功能
jDbPro 這是 jSqlBox 的內核,建立在 DbUtils 基礎上,只有 SQL 功能,不包含 ORM 等功能
MyFat 這是一個 Mybatis 插件,它將 jSqlBox 和 MyBatis 捆綁在一起,利用 jSqlBox 來補足 Mybatis 缺少的實體 CRUD 等功能

期望 | Futures

歡迎發issue提出更好的意見或提交PR,幫助完善jSqlBox

版權 | License

Apache 2.0


[admin ]

來源:OsChina
連結:https://www.oschina.net/news/109632/jsqlbox-3-0-0-released
jSqlBox 3.0.0發布, 自帶分散式事務的 Java ORM 工具已經有222次圍觀

http://coctec.com/news/all/show-post-213851.html