springboot结合mybatis使用多数据源的方式

  背景      

        最近有一个需求,有两个库需要做同步数据,一个Doris库,一个mysql库,两边的表结构一致,这里不能使用navicat等工具提供的数据传输之类的功能,只能使用代码做同步,springboot配置多数据源的方式在这里有示例:CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/132598605

 方式一:不同的库对应不同的mapper

项目结构示例

 数据库bank1配置

package com.example.springbootmybatisdiffdatasource.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;

/**
 * bank1配置
 * @Author wzw
 * @Date 2024/5/27 19:29
 * @Version 1.0
 * @Description todo
 */
@Configuration
@MapperScan(basePackages = "com.example.springbootmybatisdiffdatasource.mapper.bank1",
                sqlSessionFactoryRef ="bank1SqlSessionFactory" )
public class Bank1Config {
    /**
     * 本地mysql的bank1库的数据配置
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.bank1")
    public DataSourceProperties bank1SourceProperties() {
        return new DataSourceProperties();
    }
    /**
     * 初始化数据源
     * @return
     */
    @Bean("bank1DataSource")
    public DataSource bank1DataSource() {
        return bank1SourceProperties().initializeDataSourceBuilder().build();
    }

    /**
     * 创建session工厂
     * @param dataSource
     * @return org.apache.ibatis.session.SqlSessionFactory
     * @author: wzw
     * @date: 2024/5/27 19:37
     */
    @Bean("bank1SqlSessionFactory")
    public SqlSessionFactory bank1SqlSessionFactory(@Qualifier("bank1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        //设置数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        //设置mapper扫描路径
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:/mapper/bank1/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }
}

数据库bank2配置 

package com.example.springbootmybatisdiffdatasource.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * bank2配置
 * @Author wzw
 * @Date 2024/5/27 19:38
 * @Version 1.0
 * @Description todo
 */
@Configuration
@MapperScan(basePackages = "com.example.springbootmybatisdiffdatasource.mapper.bank2",
        sqlSessionFactoryRef ="bank2SqlSessionFactory" )
public class Bank2Config {
    /**
     * 本地mysql的bank1库的数据配置
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.bank2")
    public DataSourceProperties bank2SourceProperties() {
        return new DataSourceProperties();
    }
    /**
     * 初始化数据源
     * @return
     */
    @Bean("bank2DataSource")
    public DataSource bank2DataSource() {
        return bank2SourceProperties().initializeDataSourceBuilder().build();
    }

    /**
     * 创建session工厂
     * @param dataSource
     * @return org.apache.ibatis.session.SqlSessionFactory
     * @author: wzw
     * @date: 2024/5/27 19:37
     */
    @Bean("bank2SqlSessionFactory")
    public SqlSessionFactory bank2SqlSessionFactory(@Qualifier("bank2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        //设置数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        //设置mapper扫描路径
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:/mapper/bank2/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }
}

配置依赖数据库配置

spring.application.name=springboot-mybatis-diffdatasource
server.port=8888

spring.datasource.bank1.url=jdbc:mysql://localhost:3306/bank1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.bank1.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.bank1.username=root
spring.datasource.bank1.password=123456

spring.datasource.bank2.url=jdbc:mysql://localhost:3306/bank2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.bank2.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.bank2.username=root
spring.datasource.bank2.password=123456

实体类 

package com.example.springbootmybatisdiffdatasource.entity;

import lombok.Data;

import java.sql.Timestamp;

/**
 * 数据库实体映射
 * @Author wzw
 * @Date 2024/5/27 19:44
 * @Version 1.0
 * @Description todo
 */
@Data
public class DeDuplication {
    /**
     * 日志号
     */
    private String txNo;
    /**
     * 创建时间
     */
    private Timestamp createTime;

}

bank1查询接口

package com.example.springbootmybatisdiffdatasource.mapper.bank1;

import com.example.springbootmybatisdiffdatasource.entity.DeDuplication;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * @Author wzw
 * @Date 2024/5/27 19:43
 * @Version 1.0
 * @Description todo
 */
@Mapper
public interface DeDuplication1Mapper {
    /**
     * 查询所有数据
     * @param 
     * @return java.util.List<com.example.springbootmybatisdiffdatasource.entity.DeDuplication>
     * @author: wzw
     * @date: 2024/5/27 19:54
     */
    List<DeDuplication> selectAll();
}

bank2批量插入接口

package com.example.springbootmybatisdiffdatasource.mapper.bank2;

import com.example.springbootmybatisdiffdatasource.entity.DeDuplication;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * @Author wzw
 * @Date 2024/5/27 19:43
 * @Version 1.0
 * @Description todo
 */
@Mapper
public interface DeDuplication2Mapper {

    /**
     * 批量插入
     * @param list
     * @return java.lang.Integer
     * @author: wzw
     * @date: 2024/5/27 19:57
     */
    Integer batchInsert(@Param("list") List<DeDuplication> list);
}

bank1库示例表的xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootmybatisdiffdatasource.mapper.bank1.DeDuplication1Mapper">

	<resultMap id="base" type="com.example.springbootmybatisdiffdatasource.entity.DeDuplication">
		<result column="tx_no" property="txNo"/>
		<result column="create_time" property="createTime"/>
	</resultMap>

	<select id="selectAll" resultMap="base">
		select * from de_duplication
	</select>

</mapper>

bank2库示例表的xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootmybatisdiffdatasource.mapper.bank2.DeDuplication2Mapper">

	<insert id="batchInsert">
		insert into de_duplication(tx_no,create_time)
		values
		<foreach collection="list" item="a" separator=",">
			(
			 #{a.txNo},
			 #{a.createTime}
			)
		</foreach>
	</insert>

</mapper>

测试

package com.example.springbootmybatisdiffdatasource.test;

import com.example.springbootmybatisdiffdatasource.entity.DeDuplication;
import com.example.springbootmybatisdiffdatasource.mapper.bank1.DeDuplication1Mapper;
import com.example.springbootmybatisdiffdatasource.mapper.bank2.DeDuplication2Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 测试类
 * @Author wzw
 * @Date 2024/5/27 20:02
 * @Version 1.0
 * @Description todo
 */
@RestController
public class TestController {
    @Autowired
    private DeDuplication1Mapper deDuplication1Mapper;

    @Autowired
    private DeDuplication2Mapper deDuplication2Mapper;

    @GetMapping("test")
    public void test(){
        List<DeDuplication> deDuplications = deDuplication1Mapper.selectAll();
        System.out.printf("个数:%d%n",deDuplications.size());
        deDuplication2Mapper.batchInsert(deDuplications);
        System.out.println("批量插入成功");
    }
}

bank1中的数据

bank2中目前是空的

运行测试方法

刷新bank2

至此方式一解决了不同库数据同步问题,但是有个问题需要考虑 ,示例是写一张表,如果写入成百上千张表呢,mapper是不是要double,这里采用动态路由的方式切换数据源,如下

方式二:动态切换数据源(不同库使用同一个mapper)

项目结构示例

动态数据源配置

package com.example.springbootmybatisdiffdatasource.twoway.config;

import com.example.springbootmybatisdiffdatasource.twoway.constant.DataSourceEnum;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 同时配置bank1和bank2
 *
 * @Author wzw
 * @Date 2024/5/28 10:28
 * @Version 1.0
 * @Description todo
 */
@Configuration
//扫描mapper,两个库共用一个mapper,因为表结构是一致的
@MapperScan(basePackages = "com.example.springbootmybatisdiffdatasource.twoway.mapper")
public class DoubleDataSourceConfig {
    /**
     * 本地mysql的bank1库的数据配置
     *
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.bank1")
    public DataSourceProperties bank1SourceProperties() {
        return new DataSourceProperties();
    }

    /**
     * bank1初始化
     *
     * @return
     */
    @Bean("bank1DataSource")
    public DataSource bank1DataSource() {
        return bank1SourceProperties().initializeDataSourceBuilder().build();
    }

    /**
     * bank2库的数据配置
     *
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.bank2")
    public DataSourceProperties bank2SourceProperties() {
        return new DataSourceProperties();
    }

    /**
     * bank2初始化
     *
     * @return
     */
    @Bean("bank2DataSource")
    public DataSource bank2DataSource() {
        return bank2SourceProperties().initializeDataSourceBuilder().build();
    }

    /**
     * 配置动态数据源
     *
     * @param bank1
     * @param bank2
     * @return com.example.springbootmybatisdiffdatasource.twoway.config.DynamicToggleDataSource
     * @author: wzw
     * @date: 2024/5/28 10:56
     */
    @Bean("dynamicToggleDataSource")
    public DynamicToggleDataSource dynamicToggleDataSource(@Qualifier("bank1DataSource") DataSource bank1,
                                                           @Qualifier("bank2DataSource") DataSource bank2) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceEnum.BANK1, bank1);
        targetDataSources.put(DataSourceEnum.BANK2, bank2);
        DynamicToggleDataSource dynamicDataSource = new DynamicToggleDataSource();
        //数据源集合
        dynamicDataSource.setTargetDataSources(targetDataSources);
        //默认查询数据库bank1
        dynamicDataSource.setDefaultTargetDataSource(bank1);
        return dynamicDataSource;
    }

    /**
     * 创建session工厂
     * @param dataSource
     * @return org.apache.ibatis.session.SqlSessionFactory
     * @author: wzw
     * @date: 2024/5/27 19:37
     */
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicToggleDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        //设置数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        //设置mapper扫描路径
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:/twoway/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }
}

package com.example.springbootmybatisdiffdatasource.twoway.config;

import com.example.springbootmybatisdiffdatasource.twoway.constant.DataSourceEnum;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 动态切换数据源,使用
 * @Author wzw
 * @Date 2024/5/28 10:35
 * @Version 1.0
 * @Description todo
 */
public class DynamicToggleDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }

    public static class DataSourceContextHolder {

        private static final ThreadLocal<DataSourceEnum> contextHolder = new ThreadLocal<>();

        public static void setDataSourceType(DataSourceEnum type) {
            contextHolder.set(type);
        }

        public static DataSourceEnum getDataSourceType() {
            return contextHolder.get();
        }

        public static void clearDataSourceType() {
            contextHolder.remove();
        }
    }
}

数据源枚举

package com.example.springbootmybatisdiffdatasource.twoway.constant;

import lombok.AllArgsConstructor;

/**
 * 数据库枚举
 * @Author wzw
 * @Date 2024/5/28 10:39
 * @Version 1.0
 * @Description todo
 */
@AllArgsConstructor
public enum DataSourceEnum {
    BANK1("mysql_bank1"),
    BANK2("mysql_bank2");

    private String dataSourceName;


    public String getDataSourceName() {
        return dataSourceName;
    }

    public void setDataSourceName(String dataSourceName) {
        this.dataSourceName = dataSourceName;
    }
}

表mapper

package com.example.springbootmybatisdiffdatasource.twoway.mapper;

import com.example.springbootmybatisdiffdatasource.entity.DeDuplication;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * @Author wzw
 * @Date 2024/5/27 19:43
 * @Version 1.0
 * @Description todo
 */
@Mapper
public interface DeDuplicationMapper {
    /**
     * 查询所有数据
     * @param 
     * @return java.util.List<com.example.springbootmybatisdiffdatasource.entity.DeDuplication>
     * @author: wzw
     * @date: 2024/5/27 19:54
     */
    List<DeDuplication> selectAll();

    /**
     * 批量插入
     * @param list
     * @return java.lang.Integer
     * @author: wzw
     * @date: 2024/5/27 19:57
     */
    Integer batchInsert(@Param("list") List<DeDuplication> list);
}

xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootmybatisdiffdatasource.twoway.mapper.DeDuplicationMapper">

	<resultMap id="base" type="com.example.springbootmybatisdiffdatasource.entity.DeDuplication">
		<result column="tx_no" property="txNo"/>
		<result column="create_time" property="createTime"/>
	</resultMap>

	<select id="selectAll" resultMap="base">
		select * from de_duplication
	</select>

	<insert id="batchInsert">
		insert into de_duplication(tx_no,create_time)
		values
		<foreach collection="list" item="a" separator=",">
			(
			#{a.txNo},
			#{a.createTime}
			)
		</foreach>
	</insert>

</mapper>

测试

package com.example.springbootmybatisdiffdatasource.test;

import com.example.springbootmybatisdiffdatasource.entity.DeDuplication;
import com.example.springbootmybatisdiffdatasource.twoway.config.DynamicToggleDataSource;
import com.example.springbootmybatisdiffdatasource.twoway.constant.DataSourceEnum;
import com.example.springbootmybatisdiffdatasource.twoway.mapper.DeDuplicationMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

/**
 * 测试类
 * @Author wzw
 * @Date 2024/5/27 20:02
 * @Version 1.0
 * @Description todo
 */
@RestController
public class TestController {
    @Autowired
    private DeDuplicationMapper deDuplicationMapper;

    @GetMapping("test")
    public void test(){
        List<DeDuplication> deDuplications = deDuplicationMapper.selectAll();
        System.out.printf("个数:%d%n",deDuplications.size());
        //  切换数据源
        DynamicToggleDataSource.DataSourceContextHolder.setDataSourceType(DataSourceEnum.BANK2);
        deDuplicationMapper.batchInsert(deDuplications);
        System.out.println("批量插入成功");
    }
}

测试结果跟上面一致,但是还会有一个问题:动态切换数据源在表很多的前提下还是会增大系统开销,浪费系统资源

方式三:使用SqlSessionTemplate指向不同的数据源(也是使用同一个mapper)

项目结构示例

动态数据源配置

package com.example.springbootmybatisdiffdatasource.threeway.config;
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.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/**
 * bank1配置
 * @Author wzw
 * @Date 2024/5/27 19:29
 * @Version 1.0
 * @Description todo
 */
@Configuration
@MapperScan(basePackages = "com.example.springbootmybatisdiffdatasource.threeway.mapper",
                sqlSessionTemplateRef ="bank1SqlSessionTemplate" )
public class Bank1Config {
    /**
     * 本地mysql的bank1库的数据配置
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.bank1")
    public DataSourceProperties bank1SourceProperties() {
        return new DataSourceProperties();
    }
    /**
     * 初始化数据源
     * @return
     */
    @Bean("bank1DataSource")
    public DataSource bank1DataSource() {
        return bank1SourceProperties().initializeDataSourceBuilder().build();
    }

    /**
     * 创建session工厂
     * @param dataSource
     * @return org.apache.ibatis.session.SqlSessionFactory
     * @author: wzw
     * @date: 2024/5/27 19:37
     */
    @Bean("bank1SqlSessionFactory")
    public SqlSessionFactory bank1SqlSessionFactory(@Qualifier("bank1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        //设置数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        //设置mapper扫描路径
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:/threeway/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * bank1的事务管理器
     * @param dataSource
     * @return org.springframework.transaction.PlatformTransactionManager
     * @author: wzw
     * @date: 2024/5/28 11:55
     */
    @Bean(name = "bank1TransactionManager")
    public PlatformTransactionManager bank1TransactionManager(@Qualifier("bank1DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * bank1的sql模板
     * @param sqlSessionFactory
     * @return org.mybatis.spring.SqlSessionTemplate
     * @author: wzw
     * @date: 2024/5/28 11:55
     */
    @Bean(name = "bank1SqlSessionTemplate")
    public SqlSessionTemplate bank1SqlSessionTemplate(@Qualifier("bank1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
package com.example.springbootmybatisdiffdatasource.threeway.config;
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.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/**
 * bank2配置
 * @Author wzw
 * @Date 2024/5/27 19:38
 * @Version 1.0
 * @Description todo
 */
@Configuration
@MapperScan(basePackages = "com.example.springbootmybatisdiffdatasource.threeway.mapper",
        sqlSessionTemplateRef ="bank2SqlSessionTemplate" )
public class Bank2Config {
    /**
     * 本地mysql的bank2库的数据配置
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.bank2")
    public DataSourceProperties bank2SourceProperties() {
        return new DataSourceProperties();
    }
    /**
     * 初始化数据源
     * @return
     */
    @Bean("bank2DataSource")
    public DataSource bank2DataSource() {
        return bank2SourceProperties().initializeDataSourceBuilder().build();
    }

    /**
     * 创建session工厂
     * @param dataSource
     * @return org.apache.ibatis.session.SqlSessionFactory
     * @author: wzw
     * @date: 2024/5/27 19:37
     */
    @Bean("bank2SqlSessionFactory")
    public SqlSessionFactory bank2SqlSessionFactory(@Qualifier("bank2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        //设置数据源
        sqlSessionFactoryBean.setDataSource(dataSource);
        //设置mapper扫描路径
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:/threeway/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * bank2的事务管理器
     * @param dataSource
     * @return org.springframework.transaction.PlatformTransactionManager
     * @author: wzw
     * @date: 2024/5/28 11:55
     */
    @Bean(name = "bank2TransactionManager")
    public PlatformTransactionManager bank2TransactionManager(@Qualifier("bank2DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * bank1的sql模板
     * @param sqlSessionFactory
     * @return org.mybatis.spring.SqlSessionTemplate
     * @author: wzw
     * @date: 2024/5/28 11:55
     */
    @Bean(name = "bank2SqlSessionTemplate")
    public SqlSessionTemplate bank2SqlSessionTemplate(@Qualifier("bank2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

 

表mapper、xml和上面一样

测试

package com.example.springbootmybatisdiffdatasource.test;

import com.example.springbootmybatisdiffdatasource.entity.DeDuplication;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

/**
 * 测试类
 * @Author wzw
 * @Date 2024/5/27 20:02
 * @Version 1.0
 * @Description todo
 */
@RestController
public class TestController {
    @Autowired
    @Qualifier("bank1SqlSessionTemplate")
    private SqlSessionTemplate bank1Template;

    @Autowired
    @Qualifier("bank2SqlSessionTemplate")
    private SqlSessionTemplate bank2Template;

    @GetMapping("test")
    public void test(){
        List<DeDuplication> deDuplications =
                bank1Template.selectList("com.example.springbootmybatisdiffdatasource.threeway.mapper.DeDuplicationMapper.selectAll");
        System.out.printf("个数:%d%n",deDuplications.size());
        bank2Template.insert("com.example.springbootmybatisdiffdatasource.threeway.mapper.DeDuplicationMapper.batchInsert",deDuplications);
        System.out.println("批量插入成功");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/667437.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

乐高小人分类项目

数据来源 LEGO Minifigures | Kaggle 建立文件目录 BASE_DIR lego/star-wars-images/ names [YODA, LUKE SKYWALKER, R2-D2, MACE WINDU, GENERAL GRIEVOUS ] tf.random.set_seed(1)# Read information about dataset if not os.path.isdir(BASE_DIR train/):for name in …

GPT-4o:新一代人工智能技术的全方位解析引言

目录 &#x1f40b;引言 &#x1f40b;梳理 GPT 各版本之间的内容 &#x1f988;GPT-1&#xff1a;开创性的起点 &#x1f988; GPT-2&#xff1a;参数规模的大幅提升 &#x1f988; GPT-3&#xff1a;参数爆炸与多任务学习 &#x1f988;GPT-4&#xff1a;进一步提升的智…

嵌入式模块学习小记(未分类)

L298N电机驱动板模块 Output A&#xff1a;接DC 电机 1 或步进电机的 A和 A-&#xff1b; Output B&#xff1a;接DC 电机 2 或步进电机的 B和 B-&#xff1b; 5V Enable&#xff1a;如果使用输入电源大于12V的电源&#xff0c;请将跳线帽移除。输入电源小于12V时短接可以提…

【Python面试50题】

1. **基础概念** 1. Python 是解释型还是编译型语言&#xff1f; 2. 什么是 Python 的 GIL&#xff08;全局解释器锁&#xff09;&#xff1f; 3. 如何理解 Python 中的可变与不可变数据类型&#xff1f; 4. 解释一下 Python 中的 pass 语句。 5. Python 中的列…

让低代码平台插上AI的翅膀 - 记开源驰骋AI平台升级

让低代码系统插上AI的翅膀——驰骋低代码开发平台引领新时代 在当今日新月异的科技世界中&#xff0c;人工智能&#xff08;AI&#xff09;已经成为各个行业不可或缺的一部分。从制造业的自动化生产到金融行业的智能风控&#xff0c;再到医疗领域的精准诊断&#xff0c;AI技术…

FPGA-ARM架构与分类

ARM架构&#xff0c;曾称进阶精简指令集机器&#xff08;Advanced RISC Machine&#xff09;更早称作Acorn RISC Machine&#xff0c;是一个32位精简指令集&#xff08;RISC&#xff09;处理器架构。 主要是根据FPGA zynq-7000的芯片编写的知识思维导图总结,废话不多说自取吧 …

GPT LoRA 大模型微调,生成猫耳娘

往期热门专栏回顾 专栏描述Java项目实战介绍Java组件安装、使用&#xff1b;手写框架等Aws服务器实战Aws Linux服务器上操作nginx、git、JDK、VueJava微服务实战Java 微服务实战&#xff0c;Spring Cloud Netflix套件、Spring Cloud Alibaba套件、Seata、gateway、shadingjdbc…

Windows环境安装redis

1、下载redis https://github.com/tporadowski/redis/releases 2、解压 .zip 3、更改文件名 更改文件名称为&#xff1a;redis 4、将本地解压后的redis&#xff0c;作为本地服务器下的应用服务 从redis文件路径下&#xff0c;执行cmd .\redis-server --service-install re…

使用wireshark分析tcp握手过程

开启抓包 tcpdump -i any host 127.0.0.1 and port 123 -w tcp_capture.pcap 使用telnet模拟tcp连接 telnet 127.0.0.1 123 如果地址无法连接&#xff0c;则会一直重试SYN包&#xff0c;各个平台SYN重试间隔并不一致&#xff0c;如下&#xff1a; 异常站点抓包展示&#xff…

word中设置页眉,首页不设置

在设计文档时&#xff0c;有时候会给文档设置页眉&#xff0c;但是一设置&#xff0c;就是每页都会同时设置&#xff0c;大部分都不需要首页设置&#xff0c;那咋么解决呢&#xff0c;请看以下的解说&#xff0c;Come On&#xff01;&#xff01;&#xff01; 1、首先点击头部…

基于SSM的“基于Apriori算法的网络书城”的设计与实现(源码+数据库+文档)

基于SSM的“基于Apriori算法的网络书城”的设计与实现&#xff08;源码数据库文档) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 网站功能展示图 首页 商品分类 热销 新品 我的订单 个…

组装电脑(使用老机箱)

昨天同事拿来一台联想 ThinkCentre M6210t的台式机&#xff0c;说计算机实在是太慢了&#xff0c;在只保留主机箱想升级一下。   她拿来了配件&#xff0c;有电源、主板、CPU、CPU风扇、内存条、机箱风扇、硬盘&#xff1a;   主板&#xff1a;华硕 Prime H610M-K D4&#…

FPGA高端项目:FPGA解码MIPI视频+图像缩放+视频拼接,基于MIPI CSI-2 RX Subsystem架构实现,提供4套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我这里已有的 MIPI 编解码方案本方案在Xilinx Artix7-35T上解码MIPI视频的应用本方案在Xilinx Artix7-100T上解码MIPI视频的应用本方案在Xilinx Kintex7上解码MIPI视频的应用本方案在Xilinx Zynq7000上解码MIPI视频的应用本方案在…

【云原生 | 60】Docker中通过docker-compose部署kafka集群

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

基于WIN2016搭建MS2016 ALWAYS ON域控故障转移群集

基于WIN2016搭建MS2016 ALWAYS ON域控故障转移群集 一、前言1、Always On简介2、AD DC域控简介 二、部署实施1、部署环境简介2、搭建流程简介3、域控服务器安装及群集节点加域3.1、安装域控&#xff0c;安装同时会安装DNS系统3.2、执行安装&#xff0c;完成后重启服务器3.3、将…

哇塞!数字营销竟是企业增长的魔法棒!

​嘿&#xff0c;朋友们&#xff01;你们有没有发现“蚓链数字营销”就像一根神奇的魔法棒&#xff0c;为企业带来了超乎想象的市场影响力&#xff01; 首先&#xff0c;蚓链数字营销能够利用互联网和数字技术&#xff0c;精准地定位目标用户群体。比如&#xff0c;通过搜索引擎…

Java整合EasyExcel实战——3(上下列相同合并单元格策略)

参考&#xff1a;https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06 准备条件 依赖 <dependency><groupId>com.alibaba</gr…

数据分析案例一使用Python进行红酒与白酒数据数据分析

源码和数据集链接 以红葡萄酒为例 有两个样本: winequality-red.csv:红葡萄酒样本 winequality-white.csv:白葡萄酒样本 每个样本都有得分从1到10的质量评分&#xff0c;以及若干理化检验的结果 #理化性质字段名称1固定酸度fixed acidity2挥发性酸度volatile acidity3柠檬酸…

【SpringBoot】SpringBoot整合JWT

目录 先说token单点登录&#xff08;SSO&#xff09;简介原理单点登录的优势单点登录流程分布式单点登录方式方式一&#xff1a;session广播机制实现方式二&#xff1a;使用cookieredis实现。方式三&#xff1a;token认证 JWT数字签名JWT的作用JWT和传统Session1、无状态&#…

【Linux 网络】网络基础(三)(其他重要协议或技术:DNS、ICMP、NAT)

一、DNS&#xff08;Domain Name System&#xff09; DNS 是一整套从域名映射到 IP 的系统。 1、DNS 背景 TCP/IP 中使用 IP 地址和端口号来确定网络上的一台主机的一个程序&#xff0c;但是 IP 地址不方便记忆。于是人们发明了一种叫主机名的东西&#xff0c;是一个字符串&…