jSqlBox 2.0.6 发布,轻松解决分库分表事务

栏目: Java · 发布时间: 6年前

内容简介:jSqlBox是一个Java持久层工层,2.0.6版发布,主要有两个更新:1.添加了对以下三个JPA注解的支持:@Version 乐观锁注解

jSqlBox是一个 Java 持久层工层,2.0.6版发布,主要有两个更新:

1.添加了对以下三个JPA注解的支持:

@Version 乐观锁注解

@Enumerated 枚举字段注解

@Convert 自定义字段转换器

具体的用法可参考jSqlBox的[ 用户手册 ],对于以操纵 SQL 为基础的常见DAO工具来说,jSqlBox可能算是支持标准JPA注解比较多的了,目前它已支持的JPA注解达到以下15个,这些注解既可以使用JPA的,也可以使用jSqlBox自带的同名注解:

```

@GeneratedValue,@GenerationType,@Id,@Index,@SequenceGenerator,@Table,@TableGenerator,@Transient,@UniqueConstraint,@Version,@Column,@Convert,@Entity,@Enumerated,@EnumType

```

至于完整的JPA注解有上百个,不可能也没必要完全去支持,因为作者本人认为JPA从Hibernate演化而来,本身就存在着基于容器、过度复杂的问题。

2. 更正了多数据源及分库情况下不支持事务的bug:

在jSqlBox2.0.5及之前版本,存在一个bug:当SqlBoxContext实体被作为参数传递时,例如:

ctx1.iExecute(ctx2,'insert into users (userid,name) value(...)'

它将会从ctx1切换到ctx2上工作,也就是数据源被切换了,但问题是,如果上述语句是在一个@TX之类的自定义声明式事务注解控制下,它的事务怎么处理? 2.0.5版及以前对这个问题考虑不周,这种情况下ctx2依然工作在自动提交模式,不受事务控制,显然这是一个严重的Bug。

从2.0.6版起,jSqlBox在jTransaction模块(子项目)增加了一个GroupTx类,这个类的作用是实现多数据源事务,解决了SqlBoxContext被作为参数传递时不受事务控制的问题。这个GroupTx事务不是分布式事务,只保证一致回滚,但不保证一致提交,也就是说,当有一组SqlBoxContext同时在GroupTx控制的方法里进行数据存取时,是不安全的,但是如果只有其中任意一个(具体那一个不知道)数据源进行提交,则是100%数据一致性安全的。 GroupTx最适用的场合是Sharding,因为在Sharding场景下,任一个SQL都会可能在一群SqlBoxContext中根据实体的Sharding键(jSqlBox要求是主键)切换,但是因为业务优化设计的原因,通常所有相关的业务数据都会保存在同一个数据库中,也就是说会收敛到单个数据源上进行操作,也就充分发挥了GroupTx的特点,实现了安全性。 Sharding和分布式事务都是用来解决大数据量的手段, 如果业务采用了Sharding方案,往往可以在支持大数据量的前题下,不制造出分布式事务问题,当然这对业务设计、持久层 工具 的要求比较高,所有业务、实体和SQL存取都要考虑分库分表情况,和开发单机应用不太一样。如果采用微服务架构,把所有订单放在一个库里,所有用户放在另一个库里,则编程虽然简单,但却制造出了微服务之间的分布式事务问题。

GroupTx的使用示例如下:(完整源码见jSqlBox/core/目录下的GroupTxTest.java)

public class GroupTxTest {
	GroupTxConnectionManager gm;
	HikariDataSource ds1;
	HikariDataSource ds2;
	SqlBoxContext ctx1;
	SqlBoxContext ctx2;

	@Before
	public void init() {
		ds1 = new HikariDataSource();
                (略去部分内容) 

		gm = new GroupTxConnectionManager(ds1, ds2); 
		ctx1 = new SqlBoxContext(ds1);
		ctx1.setConnectionManager(gm);//设定GroupTxConnectionManager

		ctx2 = new SqlBoxContext(ds2);
		ctx2.setConnectionManager(gm);//设定GroupTxConnectionManager
	} 

	@Test
	public void groupRollbackTest() { // test group roll back
		for (int i = 0; i < 100; i++) {
			gm.startGroupTransaction();
			try {
				Assert.assertEquals(100, ctx1.eCountAll(Usr.class));
				new Usr().putField("firstName", "Foo").insert(ctx1);
				Assert.assertEquals(101, ctx1.eCountAll(Tail.class, tail("users")));

				Assert.assertEquals(100, ctx2.eCountAll(Usr.class));
				new Usr().putField("firstName", "Foo").insert(ctx2);
				Assert.assertEquals(101, ctx2.eCountAll(Tail.class, tail("users")));
				System.out.println(1 / 0); // 除0,事务回滚!
				gm.commitGroupTx();
			} catch (Exception e) {
				gm.rollbackGroupTx();
			}
			Assert.assertEquals(100, ctx1.eCountAll(Tail.class, tail("users")));
			Assert.assertEquals(100, ctx2.eCountAll(Tail.class, tail("users")));
		}
	}

	@Test
	public void groupCommitTest() { // test group commit
		for (int i = 0; i < 100; i++) {
			gm.startGroupTransaction();
			try {
				new Usr().putField("firstName", "Foo").insert(ctx1);
				ctx1.eInsert(new Usr().setFirstName("Foo"), ctx2);
				new Usr().putField("firstName", "Bar").insert(ctx2);
				gm.commitGroupTx(); //两个都提交,但不可信任,因为。。。
			} catch (Exception e) {
				gm.rollbackGroupTx();
			}
		} 
	}

	@Test
	public void groupPartialCommitTest() { // simulate partial commit test
		Assert.assertEquals(100, ctx1.eCountAll(Tail.class, tail("users")));
		gm.startGroupTransaction();
		try {
			new Usr().putField("firstName", "Foo").insert(ctx1);
			new Usr().putField("firstName", "Foo").insert(ctx2);
			ds2.close();//看到没有,ds2关闭了,但是ctx1还是提交成功了
			gm.commitGroupTx();
		} catch (Exception e) {
			gm.rollbackGroupTx();
		}
		Assert.assertEquals(101, ctx1.eCountAll(Tail.class, tail("users")));
	}
}

以上示例演示了手工进行GroupTx事务的开启、提交和回滚,示例说明了如果有两个ctx同时进行提交,在调用commitGroupTx时,如果运行期异常发生,会回步回滚,这个没有问题,但是如果一个数据提交出错,另一个没有,就可能造成部分提交的情况,这就是GroupTx的局限,所以只能用在多打一的情况下,也就是说通常最适合它的场景是Sharding事务,最终生效的实际数据源会收敛到单个数据源上操作。

以上是手工进行GroupTx事务的配置和解说,关于声明式方式的配置使用和解说因篇幅问题请详见jSqlBox的wiki用户手册。

jSqlBox下一步计划是加入分布式TCC事务支持,补上这项一直缺少的功能,初步打算是加入Fescar的支持,这是阿里最近开源出来的项目,还没成熟,它的特点是对业务入侵小,通过分析SQL来自动创建回滚SQL。 不过个人感觉Fescar可能会存在性能问题和兼容性问题(非常类似于jdbc-sharding所面对的问题,它也是通过分析SQL语法来支持Sharding),如果由持久层工具来创建回滚SQL,虽然麻烦一点,但可能通用性和性能会更好一点。  

作者主要开源项目 | Other Projects

期望 | Futures

欢迎发issue提出更好的意见或提交PR,帮助完善jSqlBox

版权 | License

Apache 2.0

关注我 | About Me


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML Dog

HTML Dog

Patrick Griffiths / New Riders Press / 2006-11-22 / USD 49.99

For readers who want to design Web pages that load quickly, are easy to update, accessible to all, work on all browsers and can be quickly adapted to different media, this comprehensive guide represen......一起来看看 《HTML Dog》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

html转js在线工具
html转js在线工具

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具