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

news2025/2/24 2:38:15

  背景      

        最近有一个需求,有两个库需要做同步数据,一个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("批量插入成功");
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

公众号爆文全攻略:最新推荐机制与实战干货分享

期待已久的公众号爆文直播来了&#xff01;老规矩&#xff0c;免费&#xff0c;只讲干货&#xff01;全程不废话&#xff01; 本次直播你将收获&#xff1a; 深度拆解公众号最新推荐机制&#xff1a;掌握公众号运营的核心规则&#xff0c;精准把握推荐逻辑&#xff0c;让你的内…

云动态摘要 2024-05-31

给您带来云厂商的最新动态&#xff0c;最新产品资讯和最新优惠更新。 最新优惠与活动 [1.5折起]年中盛惠--AI分会场 腾讯云 2024-05-30 人脸核身、语音识别、文字识别、数智人、腾讯混元等热门AI产品特惠&#xff0c;1.5折起 云服务器ECS试用产品续用 阿里云 2024-04-14 云…

手写HTML字符串解析成对应的 AST语法树

先看效果 展示如下&#xff1a; HTML模版 转成ast语法树后 在学习之前&#xff0c;我们需要了解这么一个问题&#xff0c;为什么要将HTML字符串解析成对应的 AST语法树。 为什么&#xff1f; 语法分析&#xff1a;HTML字符串是一种标记语言&#xff0c;其中包含了大量的标签…

掀桌子、降价、免费...之后,国内大模型应用进入高速时代

5月15日&#xff0c;字节跳动打响大模型市场价格战第一枪&#xff1b;5月21日阿里云更狠&#xff0c;价格降了97%&#xff0c;比字节还便宜37.5%同日&#xff0c;百度更为激进&#xff0c;直接宣布其两款主力模型ENIRE Speed和ENIRE Lite全面免费&#xff1b;5月22号&#xff0…

Windows10专业版系统安装Hyper-V虚拟机软件

Windows10专业版系统安装Hyper-V虚拟机软件 适用于在Windows10专业版系统安装Hyper-v虚拟机软件。 1. 安装准备 1.1 安装平台 Windows 10 1.2. 软件信息 软件名称软件版本安装路径windowswindows 10 专业版Hyper-vHyper-v 2. Hyper-v搭建 2.1打开cmd软件 2.2打开控制面…

【PostgreSQL17新特性之-explain命令新增选项】

EXPLAIN是一个用于显示语句执行计划的命令&#xff0c;可用于显示以下语句类型之一的执行计划&#xff1a; - SELECT - INSERT - UPDATE - DELETE - VALUES - EXECUTE - DECLARE - CREATE TABLE AS - CREATE MATERIALIZED VIEWPostgreSQL17-beta1版本近日发布了&#xff0c;新…

使用Prompt,轻松实现你的第一个全栈项目

前言 还有程序员没有应用过大模型技术吗&#xff1f;是工具也可以&#xff01;如果你还未使用过大模型技术&#xff0c;那么我劝你尽早行动&#xff0c;它会成为你开发的一大神器。如果你对大模型感兴趣&#xff0c;同时想使用大模型技术来开发产品&#xff0c;我接下来这个实…

Ubuntu24.04 LTS安装中文输入法

前言 最近&#xff0c;windows玩没了&#xff0c;一怒之下决定换一个操作系统&#xff0c;当然就是最新的Ubuntu24.04 LTS.&#xff0c;其中魔法和咒语&#xff08;汉语&#xff09;是inux遇到的第一大难关&#xff0c;我权限不够教不了魔法&#xff0c;但我可以教你咒语(๑•…

JVM优化之垃圾收集器

JVM优化之垃圾收集器 Serial收集器Parallel Scavenge收集器ParNew收集器 如果说垃圾收集算法是内存回收的方法论&#xff0c;那么垃圾收集器就是内存回收的具体实现。 没有最好的垃圾收集器&#xff0c;只有根据具体应用场景选择适合自己的垃圾收集器。 Serial收集器 #使用方…

GPU学习(1)

一、为什么要GPU 我们先看一个基本的神经网络计算 YF(x)AxB 这就是一次乘法一次加法 &#xff0c;也叫FMA&#xff0c;(fused multiply-add) 如果矩阵乘&#xff0c;就是上面的那个式子扩展一下&#xff0c;所以又用了这张老图 比如你要多执行好几个yAxB&#xff0c;可能比较简…

C++11中的新特性(2)

C11 1 可变参数模板2 emplace_back函数3 lambda表达式3.1 捕捉列表的作用3.2 lambda表达式底层原理 4 包装器5 bind函数的使用 1 可变参数模板 在C11之前&#xff0c;模板利用class关键字定义了几个参数&#xff0c;那么我们在编译推演中&#xff0c;我们就必须传入对应的参数…

在鲲鹏服务器上安装nginx

华为鲲鹏服务器采用华为自研cpu ARMv8架构,提供 Windows 和多个Linux 系统 常使用 CentOS 7.6 64bit with ARM Nginx 和 Apache 一样都是一种 Web 服务器。是基于 REST 架构风格&#xff0c;以统一资源描述符URI 或者统一资源定位符URL 作为沟通依据&#xff0c;通过 HTTP 协议…

【算法】模拟算法——Z字形变换(medium)

题解&#xff1a;模拟算法——Z字形变换(medium) 目录 1.题目2.题解3.参考代码4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 利用模拟&#xff0c;来解决问题。 首先创建出一个O(numRows*n)的数组来&#xff0c;并按照题目要求把每个字符按顺序填进去。 这里以numRows…

操作系统6_输入输出系统

操作系统6_输入输出系统 文章目录 操作系统6_输入输出系统1. I/O功能、模型接口2. I/O设备及控制器2.1 I/O设备2.2 设备与控制器接口2.3 设备控制器2.4 通道3. 中断及处理4. 设备驱动程序4.1 驱动程序的功能和特点4.2 驱动程序的处理过程4.3 设备控制方式4.3.1 程序I/O方式4.3.…

微信小程序-页面配置

一、页面配置文件的作用 小程序中&#xff0c;每个页面都有自己的.json配置文件&#xff0c;用来对当前页面的窗口外观、页面效果等进行配置 二、页面配置和全局配置的关系 小程序中&#xff0c;app.json中的window节点&#xff0c;可以全局配置小程序中每个页面的窗口表现 …

MySQL(十一) 用户管理

1.用户 1.1 用户信息 MySQL中的用户&#xff0c;都存储在系统数据库mysql的user表中 mysql> select host,user,authentication_string from user; --------------------------------------------------------------------- | host | user | authentication…

浏览器提示413 Request Entity Too Large

1 问题 2 解决 2.1 后端java配置 2.2 Nginx配置

7个卖出信号出现,昂首资本立即盈利收场

在上篇文章中&#xff0c;我们和各位投资者讨论了如果使用匕首交易策略进行交易&#xff0c;但是如果只买进不卖出&#xff0c;是不是还是盈利不了&#xff1f;Anzo Capital昂首资本认为只有低买高卖才能盈利赚钱&#xff0c;只要发现盈利信号就要立即卖出盈利收场&#xff01;…

【解决】Tree prefab at index 8 is missing.

开发平台&#xff1a;Unity 2020 版本以上   问题描述 翻译&#xff1a;树预制体集合中第8位预制体丢失。   解决方法&#xff1a;修复丢失树资产 关联 Unity Terrier 组件使用&#xff0c;前往 树绘制工作区&#xff0c;检查 “树资产” 引用是否丢失&#xff1f;删除或重…

力扣257. 二叉树的所有路径

思路&#xff1a;题目需要记录从根节点开始走的路径&#xff0c;无疑选用前序遍历&#xff0c;用一个数组paths 记录走过的节点信息&#xff0c;遇到叶子节点就用另一个list记录下路径&#xff0c;回溯时删掉paths尾节点即可 class Solution {public List<String> binar…