1:pom.xml引入相关依赖jar
<!--springboot整合mybatis的依赖 --> <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.22</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jta-atomikos --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
2、application.yml配置多数据源
spring: datasource: test1: url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowMultiQueries=true username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver sql-script-encoding: UTF-8 type: com.zaxxer.hikari.HikariDataSource initialization-mode: always continue-on-error: true hikari: minimum-idle: 5 connection-test-query: SELECT 1 FROM DUAL maximum-pool-size: 20 auto-commit: true idle-timeout: 30000 pool-name: SpringBootDemoHikariCP max-lifetime: 60000 connection-timeout: 30000 logging: level: com.qjc.dao.Test1: TARCE borrowConnectionTimeout: 30 loginTimeout: 30 maintenanceInterval: 60 maxIdleTime: 60 maxLifetime: 20000 maxPoolSize: 25 minPoolSize: 3 uniqueResourceName: test1 testQuery: SELECT 1 FROM DUAL test2: url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT&allowMultiQueries=true username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver sql-script-encoding: UTF-8 type: com.zaxxer.hikari.HikariDataSource initialization-mode: always continue-on-error: true hikari: minimum-idle: 5 connection-test-query: SELECT 1 FROM DUAL maximum-pool-size: 20 auto-commit: true idle-timeout: 30000 pool-name: SpringBootDemoHikariCP max-lifetime: 60000 connection-timeout: 30000 logging: level: com.qjc.dao.Test2: TARCE borrowConnectionTimeout: 30 loginTimeout: 30 maintenanceInterval: 60 maxIdleTime: 60 maxLifetime: 20000 maxPoolSize: 25 minPoolSize: 3 uniqueResourceName: test2 testQuery: SELECT 1 FROM DUAL
3、具体数据源的config和application.yml配置的数据源对应
package com.example.config; import org.springframework.boot.context.properties.ConfigurationProperties; import lombok.Data; @Data @ConfigurationProperties(prefix = "spring.datasource.test1") public class DBConfig1 { private String url; private String userName; private String passWord; private int minPoolSize; private int maxPoolSize; private int maxLifetime; private int borrowConnectionTimeout; private int loginTimeout; private int maintenanceInterval; private int maxIdleTime; private String testQuery; private String uniqueResourceName; }
package com.example.config; import org.springframework.boot.context.properties.ConfigurationProperties; import lombok.Data; @Data @ConfigurationProperties(prefix = "spring.datasource.test2") public class DBConfig2 { private String url; private String userName; private String passWord; private int minPoolSize; private int maxPoolSize; private int maxLifetime; private int borrowConnectionTimeout; private int loginTimeout; private int maintenanceInterval; private int maxIdleTime; private String testQuery; private String uniqueResourceName; }
4、启动类上加具体数据源的config
package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import com.example.config.DBConfig1; import com.example.config.DBConfig2; @SpringBootApplication @EnableConfigurationProperties({DBConfig1.class, DBConfig2.class}) public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
5、配置数据源加事务配置
package com.example.config; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import com.atomikos.jdbc.AtomikosDataSourceBean; import com.mysql.cj.jdbc.MysqlXADataSource; @Configuration //basePackages 最好分开配置,放在同一个文件夹可能会报错 @MapperScan(basePackages = {"com.example.mapper.test1"},sqlSessionTemplateRef = "test1SqlSessionTemplate") public class DataSourceConfig1 { /** * 配置数据源 * @return */ @Primary @Bean("test1DataSource") public DataSource e3shopDataSource(DBConfig1 eBConfig1) throws SQLException { //创建xa datasource MysqlXADataSource mysqlXADataSource=new MysqlXADataSource(); mysqlXADataSource.setUrl(eBConfig1.getUrl()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); mysqlXADataSource.setPassword(eBConfig1.getPassWord()); mysqlXADataSource.setUser(eBConfig1.getUserName()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); //2.注册到我们全局事务上 AtomikosDataSourceBean xaDataSource =new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(mysqlXADataSource); xaDataSource.setUniqueResourceName(eBConfig1.getUniqueResourceName()); xaDataSource.setMinPoolSize(eBConfig1.getMinPoolSize()); xaDataSource.setMaxPoolSize(eBConfig1.getMaxPoolSize()); xaDataSource.setBorrowConnectionTimeout(eBConfig1.getBorrowConnectionTimeout()); xaDataSource.setLoginTimeout(eBConfig1.getLoginTimeout()); xaDataSource.setMaintenanceInterval(eBConfig1.getMaintenanceInterval()); xaDataSource.setMaxIdleTime(eBConfig1.getMaxIdleTime()); xaDataSource.setTestQuery(eBConfig1.getTestQuery()); return xaDataSource; } /** * sqlSessionFactory * @param dataSource * @return * @throws Exception */ @Primary @Bean("test1SqlSessionFactory") public SqlSessionFactory e3shopSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean.getObject(); } /** * sqlsessionTemplate * @param sqlSessionFactory * @return */ @Primary @Bean(name = "test1SqlSessionTemplate") public SqlSessionTemplate e3shopSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }
package com.example.config; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.atomikos.jdbc.AtomikosDataSourceBean; import com.mysql.cj.jdbc.MysqlXADataSource; @Configuration //basePackages 最好分开配置,放在同一个文件夹可能会报错 @MapperScan(basePackages = {"com.example.mapper.test2"},sqlSessionTemplateRef = "test2SqlSessionTemplate") public class DataSourceConfig2 { /** * 配置数据源 * @return */ @Bean("test2DataSource") public DataSource e3shopDataSource(DBConfig2 eBConfig1) throws SQLException { //创建xa datasource MysqlXADataSource mysqlXADataSource=new MysqlXADataSource(); mysqlXADataSource.setUrl(eBConfig1.getUrl()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); mysqlXADataSource.setPassword(eBConfig1.getPassWord()); mysqlXADataSource.setUser(eBConfig1.getUserName()); mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true); //2.注册到我们全局事务上 AtomikosDataSourceBean xaDataSource =new AtomikosDataSourceBean(); xaDataSource.setXaDataSource(mysqlXADataSource); xaDataSource.setUniqueResourceName(eBConfig1.getUniqueResourceName()); xaDataSource.setMinPoolSize(eBConfig1.getMinPoolSize()); xaDataSource.setMaxPoolSize(eBConfig1.getMaxPoolSize()); xaDataSource.setBorrowConnectionTimeout(eBConfig1.getBorrowConnectionTimeout()); xaDataSource.setLoginTimeout(eBConfig1.getLoginTimeout()); xaDataSource.setMaintenanceInterval(eBConfig1.getMaintenanceInterval()); xaDataSource.setMaxIdleTime(eBConfig1.getMaxIdleTime()); xaDataSource.setTestQuery(eBConfig1.getTestQuery()); return xaDataSource; } /** * sqlSessionFactory * @param dataSource * @return * @throws Exception */ @Bean("test2SqlSessionFactory") public SqlSessionFactory e3shopSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean.getObject(); } /** * sqlsessionTemplate * @param sqlSessionFactory * @return */ @Bean(name = "test2SqlSessionTemplate") public SqlSessionTemplate e3shopSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }
6、添加mapper层操作数据库
package com.example.mapper.test1; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @Mapper public interface User1Mapper { @Insert("INSERT INTO user (username, sex, password) VALUES ( #{username}, #{sex}, #{password})") int insertUser(@Param("username")String username,@Param("sex")String sex,@Param("password")String password); }
package com.example.mapper.test2; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @Mapper public interface User2Mapper { @Insert("INSERT INTO user (username, sex, password) VALUES ( #{username}, #{sex}, #{password})") int insertUser(@Param("username")String username,@Param("sex")String sex,@Param("password")String password); }
7、service层添加事务@Transactional
package com.example.service.impl; import javax.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.example.mapper.test1.User1Mapper; import com.example.mapper.test2.User2Mapper; import com.example.service.UserService; @Service public class UserServiceImpl implements UserService { @Autowired private User1Mapper user1Mapper; @Autowired private User2Mapper user2Mapper; @Transactional @Override public int addUser(String username, String sex, String password) { int rtu1=user1Mapper.insertUser(username, sex, password); int rtu2=user2Mapper.insertUser(username, sex, password); return rtu1+rtu2; } }
完成,剩余的就是Controller层调用了