回覆列表
  • 1 # 五星村小黃

    你好,我是小黃,一個java程式設計師,這個題目我來回答下。

    SpringBoot整合Mybatis,想要實現事務控制,需要在業務實現類上新增 @Transactional註解,以及在啟動類上增加@EnableAutoConfiguration註解,即可。

  • 2 # 居家程式設計師

    作為一名資深的CURD程式設計師,事務控制/事務管理是一項不可避免的工作,也是最常見的一項功能,簡單說,事務管理就是在執行業務操作時,由於資料操作在順序執行的過程中,任何一步操作都有可能發生異常,異常會導致後續操作無法完成,此時由於業務邏輯並未正確的完成,之前成功操作資料的並不可靠,需要在這種情況下進行回退。

    1、預設的事務管理配置方式:

    在引入相關的依賴之後(比如springboot的web元件依賴、父依賴、mysql驅動依賴以及mybatis依賴等)

    而@Transational註解也擁有許多的引數,比如:

    rollbackFor:可以指定需要進行回滾的異常,指定Class物件陣列,且該Class必須繼承自Throwable;value:用於在多資料來源的情況下,進行事務管理器的指定(下面描述下多資料來源事務這種情況);noRollbackFor:有rollbackFor自然有noRollbackFor,顧名思義,用於指定不需要進行回滾的異常;readOnly:是讀寫還是隻讀事務,預設是false,讀寫;

    還有許多,不一一描述了....

    例項:

    @Servicepublic class TestTransactionalService @Autowired private TestMapper testMapper; @Transactional //當丟擲Exception的時候,將進行回滾操作 public int insertTest(TestEntity testEntity) { testEntity.setName("get out! helloService") return testMapper.insertOne(testEntity); }}

    另外,在SpringBoot的啟動類中,需要增加@EnableTransactionManagement註解,用於啟動事務管理。

    例項:

    @EnableTransactionManagement@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}

    至此,SpringBoot整合Mybatis的單資料來源的事務管理便配置完成

    2、多資料來源的事務配置方式:

    第一種方式基本上滿足了普通專案的事務管理功能, 但當專案是比較大型的專案的時候(比如電商專案),可能會存在多個數據源,這時候會出現多個事務管理器,也就需要在宣告的時候為不同資料來源的資料操作指定不同的事務管理器。

    1)首先,需要引入資料來源依賴

    #主資料來源,多資料來源的情況下,需要指定主資料來源,在後續的config中進行,此時我們將#base資料來源作為主資料來源來看待~spring.datasource.base.jdbc-url=jdbc:mysql://localhost:3306/test1spring.datasource.base.username=rootspring.datasource.base.password=rootspring.datasource.base.driver-class-name=com.mysql.jdbc.Driver#從資料來源spring.datasource.second2.jdbc-url=jdbc:mysql://localhost:3306/test2spring.datasource.second2.username=rootspring.datasource.second2.password=rootspring.datasource.second2.driver-class-name=com.mysql.jdbc.Driver

    3)新增配置類,讀取配置檔案,進行資料來源的配置

    注意,配置類需要對DataSource、DataSourceTransactionManager、SqlSessionFactory 、SqlSessionTemplate四個資料項進行配置;

    其中DataSource型別需要引入javax.sql.DataSource;

    配置主資料來源:

    如上文所說,當系統中有多個數據源時,必須有一個數據源為主資料來源,在配置類中我們使用@Primary修飾。

    透過@MapperScan註解對指定dao包建立對映,確保在多個數據源下,自動選擇合適的資料來源,而在service層裡不需要做特殊說明,否則需要透過@Transactional的value屬性進行指定

    @Configuration @MapperScan(basePackages = "com.livinghome.base", sqlSessionTemplateRef = "baseSqlSessionTemplate",sqlSessionFactoryRef = "baseSqlSessionFactory") public class BaseDataSourceConfig { /**讀取base資料來源**/ @Bean(name = "baseDataSource") @ConfigurationProperties(prefix = "spring.datasource.base") @Primary public DataSource setDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "baseTransactionManager") @Primary public DataSourceTransactionManager setTransactionManager(@Qualifier("baseDataSource") DataSource dataSource) { return new DruidDataSource(); } @Bean(name = "baseSqlSessionFactory") @Primary public SqlSessionFactory setSqlSessionFactory(@Qualifier("baseDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/base/*.xml")); return bean.getObject(); } @Bean(name = "baseSqlSessionTemplate") @Primary public SqlSessionTemplate setSqlSessionTemplate(@Qualifier("baseSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }

    配置從資料來源:

    @Configuration@MapperScan(basePackages = "com.livinghome.second2", sqlSessionTemplateRef = "zentaoSqlSessionTemplate",sqlSessionFactoryRef = "zentaoSqlSessionFactory")public class Second2DataSourceConfig { @Bean(name = "second2DataSource") @ConfigurationProperties(prefix = "spring.datasource.second2") public DataSource setDataSource() { return new DruidDataSource(); } @Bean(name = "second2TransactionManager") public DataSourceTransactionManager setTransactionManager(@Qualifier("second2DataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "second2SqlSessionFactory") public SqlSessionFactory setSqlSessionFactory(@Qualifier("second2DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/second2/*.xml")); return bean.getObject(); } @Bean(name = "second2SqlSessionTemplate") public SqlSessionTemplate setSqlSessionTemplate(@Qualifier("second2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); }}

    4)到了這裡,我們基本的多資料來源事務管理便已經完成了(真的)....

    對於service層,不需要進行事務管理器的指定,因為我們上面使用了@MapperScan進行了包指定,當然也可以手動指定,方式便是 @Transactional(transactionManager="baseTransactionManager")

    便可手動指定為base資料來源。

    另外,還有分散式事務管理,也就是在一次操作中,操作了不同的資料來源的情況,對於service而言,便是在一次service裡呼叫了兩個資料來源的方法,這種情況常見於微服務架構中,例如電商系統(第二次使用電商系統舉例..)。

    從百度上copy了一個簡單的下單流程:

    在微服務中,2、3、4步驟是涉及了3個系統以及3個數據庫的,當某個操作出現問題時,會出現多資料來源的事務管理問題,傳統的方式是透過將不同資料來源的事務都註冊到一個全域性事務中(可以透過jpa+atomikos來進行),但有大神告訴我這種方式效能差,具體還未有實踐,不是很清楚。

    我說完了... 因為對微服務架構學習還在進行中,所以對於分散式事務問題我還沒有太多的理解和實踐,等我回來....

  • 中秋節和大豐收的關聯?
  • 北約為何升級與俄羅斯的對抗?