阅读下面实验之前:请先阅读官方的分布式事务支持内容:https://shardingsphere.apache.org/document/current/cn/features/transaction/
经过试验,单服务跨数据源,使用shardingJdbc的事务,同普通jdbc时的做法一样。实验版本 shrading-jdbc-spring-boot-starter ver.3.1.0
1)启动类 (前提:pom引入spring-boot-starter-jdbc或者引入spring-boot-starter-data-jpa依赖,启动类使用注解开启事务管理器@EnableTransactionManagement):
package com.chong.mcspcshardingdbtable; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class}) @EnableDiscoveryClient @EnableTransactionManagement @ComponentScan(basePackages = {"com.chong.common","com.chong.mcspcshardingdbtable"}) public class McSpcShardingDbTableApplication { public static void main(String[] args) { SpringApplication.run(McSpcShardingDbTableApplication.class, args); } }
2)service方法引入事务注解
@Transactional public List<BizMember> saveMembersToMutliDbs(String name,String name2) { BizMember member1 = newMember(); member1.setFullName(name); member1.setGender(1); // 存放到mcspcsharding1库 BizMember member2 = newMember(); member2.setFullName(name2); member2.setGender(2);// 存放到mcspcsharding0库 List<BizMember> memberList = new ArrayList<>(); memberList.add(memberRepository.save(member1)); memberList.add(member2 = memberRepository.save(member2)); return memberList; }
3)实验之数据库构成:mcspcsharding0放置gender=2的数据;mcspcsharding1放置gender=1的数据;
4)实验步骤:通过postman,投放数据,name1符合要求,name2不符合要求(数据超长)。Rest格式为 POST: url/{name1}/{name2}
5)实验结果:
A.可以看出第一条语句插入name1的会员执行通过,第二条语句插入name2的语句执行失败,失败原因为name2的参数内容长度超出数据库列长的限制。
B.数据库中确认实际入库记录,name1和name2的数据都没有插入到数据库中。证明通过简单的两个事物注解,实现了跨数据源的事务控制。
todo:两个库的事务commit和rollback机制在shardingjdbc里如何实现的,需要抽空研究。
console内容:
2020-02-29 19:10:47.962 INFO 24132 --- [io-9060-exec-10] ShardingSphere-SQL : Rule Type: sharding 2020-02-29 19:10:47.966 INFO 24132 --- [io-9060-exec-10] ShardingSphere-SQL : Logic SQL: insert into mc_member (age, create_time, create_user, full_name, gender, is_delete, update_time, update_user, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?) 2020-02-29 19:10:47.971 INFO 24132 --- [io-9060-exec-10] ShardingSphere-SQL : SQLStatement: InsertStatement(super=DMLStatement(super=io.shardingsphere.core.parsing.parser.sql.dml.insert.InsertStatement@68a542c3), columns=[Column(name=age, tableName=mc_member), Column(name=create_time, tableName=mc_member), Column(name=create_user, tableName=mc_member), Column(name=full_name, tableName=mc_member), Column(name=gender, tableName=mc_member), Column(name=is_delete, tableName=mc_member), Column(name=update_time, tableName=mc_member), Column(name=update_user, tableName=mc_member), Column(name=id, tableName=mc_member)], generatedKeyConditions=[], insertValues=InsertValues(insertValues=[InsertValue(type=VALUES, expression=(?, ?, ?, ?, ?, ?, ?, ?, ?), parametersCount=9)]), columnsListLastPosition=112, generateKeyColumnIndex=-1, insertValuesListLastPosition=148) 2020-02-29 19:10:47.976 INFO 24132 --- [io-9060-exec-10] ShardingSphere-SQL : Actual SQL: ms1 ::: insert into mc_member0 (age, create_time, create_user, full_name, gender, is_delete, update_time, update_user, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?) ::: [[45, 2020-02-29 19:09:41.749, 245, name12, 1, 0, null, null, 4041594688888832]] Hibernate: insert into mc_member (age, create_time, create_user, full_name, gender, is_delete, update_time, update_user, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?) 2020-02-29 19:10:47.999 INFO 24132 --- [io-9060-exec-10] ShardingSphere-SQL : Rule Type: sharding 2020-02-29 19:10:48.001 INFO 24132 --- [io-9060-exec-10] ShardingSphere-SQL : Logic SQL: insert into mc_member (age, create_time, create_user, full_name, gender, is_delete, update_time, update_user, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?) 2020-02-29 19:10:48.002 INFO 24132 --- [io-9060-exec-10] ShardingSphere-SQL : SQLStatement: InsertStatement(super=DMLStatement(super=io.shardingsphere.core.parsing.parser.sql.dml.insert.InsertStatement@68a542c3), columns=[Column(name=age, tableName=mc_member), Column(name=create_time, tableName=mc_member), Column(name=create_user, tableName=mc_member), Column(name=full_name, tableName=mc_member), Column(name=gender, tableName=mc_member), Column(name=is_delete, tableName=mc_member), Column(name=update_time, tableName=mc_member), Column(name=update_user, tableName=mc_member), Column(name=id, tableName=mc_member)], generatedKeyConditions=[], insertValues=InsertValues(insertValues=[InsertValue(type=VALUES, expression=(?, ?, ?, ?, ?, ?, ?, ?, ?), parametersCount=9)]), columnsListLastPosition=112, generateKeyColumnIndex=-1, insertValuesListLastPosition=148) 2020-02-29 19:10:48.002 INFO 24132 --- [io-9060-exec-10] ShardingSphere-SQL : Actual SQL: ms0 ::: insert into mc_member0 (age, create_time, create_user, full_name, gender, is_delete, update_time, update_user, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?) ::: [[73, 2020-02-29 19:09:41.75, 873, name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1name1, 2, 0, null, null, 4041594693083136]] 2020-02-29 19:10:48.020 WARN 24132 --- [io-9060-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1406, SQLState: 22001 2020-02-29 19:10:48.020 ERROR 24132 --- [io-9060-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : Data truncation: Data too long for column 'full_name' at row 1 2020-02-29 19:10:48.043 ERROR 24132 --- [io-9060-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.DataException: could not execute statement] with root cause com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Data too long for column 'full_name' at row 1 at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:104) ~[mysql-connector-java-8.0.19.jar:8.0.19] at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) ~[mysql-connector-java-8.0.19.jar:8.0.19] at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092) ~[mysql-connector-java-8.0.19.jar:8.0.19] at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040) ~[mysql-connector-java-8.0.19.jar:8.0.19]