设置网站的默认页面,昆明几大网站,东坑网站仿做,wordpress漂浮表单Spring Boot 配置多数据源并手动配置事务 一、为什么多数据源需要手动配置#xff1f;二、配置多数据源1. 数据源配置类 (DataSourceConfig)2. 主数据库 MyBatis 配置类 (PrimaryDbMyBatisConfig)3. 从数据库 MyBatis 配置类 (SecondaryDbMyBatisConfig)4. application.yml 配… Spring Boot 配置多数据源并手动配置事务 一、为什么多数据源需要手动配置二、配置多数据源1. 数据源配置类 (DataSourceConfig)2. 主数据库 MyBatis 配置类 (PrimaryDbMyBatisConfig)3. 从数据库 MyBatis 配置类 (SecondaryDbMyBatisConfig)4. application.yml 配置5. 使用 Transactional 指定事务管理器 三、问题说明will not be managed by Spring四、总结 在现代企业级应用中往往会涉及到多个数据库的使用。例如一个应用可能需要同时操作不同的业务数据库或分离读写操作。
Spring Boot 提供了对多数据源的支持但在某些情况下自动配置可能无法满足复杂的需求。特别是在事务管理方面当需要在多个数据源间进行操作时默认的事务管理方式可能不适用或者无法满足更高的灵活性需求。
因此手动配置多个数据源并支持事务管理是一个常见的解决方案。
一、为什么多数据源需要手动配置 多数据源隔离 在微服务架构或者不同模块之间可能会使用不同的数据库每个数据库有独立的数据源和事务管理。如果使用自动配置的方式Spring Boot会自动配置一个数据源和一个事务管理器这可能会导致不同数据源的事务冲突或共享问题。因此需要手动配置多个数据源和多个事务管理器。 跨数据源的事务管理 Spring 默认的事务管理仅适用于单一数据源如果在一个方法中涉及到多个数据源Spring并不会自动处理这些数据源之间的事务关系。这时我们需要显式地配置事务管理器以便手动控制事务的提交与回滚。 灵活的事务控制 有时我们可能需要在不同的数据源之间手动控制事务比如先操作主数据源再操作从数据源或者在同一个方法中对多个数据源进行操作。这时手动配置事务管理器可以为我们提供更高的灵活性和控制能力。
二、配置多数据源
1. 数据源配置类 (DataSourceConfig)
这个配置类主要负责配置 primary_db 和 secondary_db 两个数据源并为它们设置基本的连接属性。
Configuration
EnableTransactionManagement
public class DataSourceConfig {/*** 配置主数据库primary_db数据源* * 这个方法使用 ConfigurationProperties 注解从 application.yml 配置文件中读取 * spring.datasource.primary_db 下的配置自动配置数据源的连接信息如 URL、用户名、密码等。* * return 配置的主数据库数据源对象*/Bean(name primaryDataSource)ConfigurationProperties(prefix spring.datasource.primary_db)public DataSource primaryDataSource() {return DataSourceBuilder.create().build(); // 创建并返回数据源对象}/*** 配置从数据库secondary_db数据源* * 该方法使用 ConfigurationProperties 注解从 application.yml 配置文件中读取 * spring.datasource.secondary_db 下的配置自动配置数据源的连接信息。* * return 配置的从数据库数据源对象*/Bean(name secondaryDataSource)ConfigurationProperties(prefix spring.datasource.secondary_db)public DataSource secondaryDataSource() {return DataSourceBuilder.create().build(); // 创建并返回数据源对象}} primaryDataSource() 和 secondaryDataSource() 方法用于创建和配置两个数据源。通过 ConfigurationProperties 注解Spring 会自动读取配置文件中的数据源信息并将其与 DataSource 配置绑定。DataSourceBuilder.create().build() 是 Spring Boot 提供的便捷方式来创建数据源实例。 EnableTransactionManagement 启用了事务管理功能允许你在需要的地方使用 Transactional 注解来声明事务。
2. 主数据库 MyBatis 配置类 (PrimaryDbMyBatisConfig)
这个配置类负责配置与主数据库primary_db相关的 MyBatis 组件。它包含了 MyBatis 的 SqlSessionFactory 和事务管理器配置。
Configuration
EnableTransactionManagement
MapperScan(basePackages com.cx.mail.mapper.primary_db, sqlSessionFactoryRef primaryDbSqlSessionFactory)
public class PrimaryDbMyBatisConfig {AutowiredQualifier(primaryDataSource)private DataSource primaryDataSource;/*** 配置主数据库的 MyBatis SqlSessionFactory* * 创建并配置 MyBatis 的 SqlSessionFactory它是 MyBatis 用来与数据库交互的核心组件。* 在这个配置中我们指定了使用的 primaryDataSource 数据源。* * return 配置好的 SqlSessionFactory 对象* throws Exception 可能抛出异常例如创建 SqlSessionFactory 时出错*/Beanpublic SqlSessionFactory primaryDbSqlSessionFactory() throws Exception {MybatisSqlSessionFactoryBean factory new MybatisSqlSessionFactoryBean();factory.setDataSource(primaryDataSource); // 设置使用的主数据库数据源// 配置全局设置主要是 MetaObjectHandler用于自动填充字段GlobalConfig globalConfig GlobalConfigUtils.defaults();globalConfig.setMetaObjectHandler(new EntityAutoFillHandler()); // 自动填充创建时间和更新时间factory.setGlobalConfig(globalConfig);// 配置 MyBatis Plus 插件MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 添加分页插件factory.setPlugins(interceptor);// 配置 MyBatis 基本设置MybatisConfiguration configuration new MybatisConfiguration();configuration.setMapUnderscoreToCamelCase(true); // 将数据库字段下划线命名转换为 Java 类的驼峰命名法configuration.setLogImpl(StdOutImpl.class); // 配置 SQL 打印factory.setConfiguration(configuration);// 配置 MyBatis Mapper XML 文件的位置factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath*:mapper/primary_db/*.xml));return factory.getObject(); // 返回创建的 SqlSessionFactory}/*** 配置主数据库的事务管理器* * 该方法创建一个 DataSourceTransactionManager它是 Spring 提供的事务管理器用来处理主数据库的事务。* * param dataSource 主数据库的数据源* return 配置好的事务管理器*/PrimaryBean(name primaryDbTransactionManager)public DataSourceTransactionManager primaryDbTransactionManager(Qualifier(primaryDataSource) DataSource dataSource) {return new DataSourceTransactionManager(dataSource); // 返回主数据库的事务管理器}
} primaryDbSqlSessionFactory() 方法配置了主数据库的 SqlSessionFactory并指定了与该数据库交互时的 MyBatis 配置。 primaryDbTransactionManager() 方法创建了主数据库的事务管理器DataSourceTransactionManager使得我们可以通过 Transactional 注解来管理与主数据库相关的事务。
3. 从数据库 MyBatis 配置类 (SecondaryDbMyBatisConfig)
这个配置类与主数据库配置类似但是它专门配置与从数据库secondary_db相关的 MyBatis 组件。
Configuration
EnableTransactionManagement
MapperScan(basePackages com.cx.mail.mapper.secondary_db, sqlSessionFactoryRef secondaryDbSqlSessionFactory)
public class SecondaryDbMyBatisConfig {AutowiredQualifier(secondaryDataSource)private DataSource secondaryDataSource;/*** 配置从数据库的 MyBatis SqlSessionFactory* * 创建并配置从数据库的 SqlSessionFactory它将用于从数据库的 MyBatis 操作。* * return 配置好的 SqlSessionFactory 对象* throws Exception 可能抛出异常例如创建 SqlSessionFactory 时出错*/Bean(name secondaryDbSqlSessionFactory)public SqlSessionFactory secondaryDbSqlSessionFactory() throws Exception {MybatisSqlSessionFactoryBean factory new MybatisSqlSessionFactoryBean();factory.setDataSource(secondaryDataSource); // 设置使用的从数据库数据源// 配置全局设置主要是 MetaObjectHandler用于自动填充字段GlobalConfig globalConfig GlobalConfigUtils.defaults();globalConfig.setMetaObjectHandler(new EntityAutoFillHandler());factory.setGlobalConfig(globalConfig);// 配置 MyBatis Plus 插件MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 添加分页插件factory.setPlugins(interceptor);// 配置 MyBatis 基本设置MybatisConfiguration configuration new MybatisConfiguration();configuration.setMapUnderscoreToCamelCase(true); // 设置驼峰命名法configuration.setLogImpl(StdOutImpl.class); // 配置 SQL 打印factory.setConfiguration(configuration);// 设置 Mapper XML 文件的位置factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath*:mapper/secondary_db/*.xml));return factory.getObject(); // 返回创建的 SqlSessionFactory}/*** 配置从数据库的事务管理器* * 该方法创建一个 DataSourceTransactionManager它是 Spring 提供的事务管理器用来处理从数据库的事务。* * param dataSource 从数据库的数据源* return 配置好的事务管理器*/Bean(name secondaryDbTransactionManager)public DataSourceTransactionManager secondaryDbTransactionManager(Qualifier(secondaryDataSource) DataSource dataSource) {return new DataSourceTransactionManager(dataSource); // 返回从数据库的事务管理器}
}
secondaryDbSqlSessionFactory() 和 secondaryDbTransactionManager() 方法与主数据库的配置类类似但它们专门用于配置和管理从数据库的 MyBatis 和事务。
4. application.yml 配置
# 本地库
spring:# 数据源配置 mysqldatasource:primary_db:url: jdbc:mysql://localhost:3306/primary_dbusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driversecondary_db:url: jdbc:mysql://localhost:3306/secondary_dbusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver
配置了 primary_db 和 secondary_db 两个数据源的连接信息如 URL、用户名、密码等这些配置将被数据源配置类读取。
5. 使用 Transactional 指定事务管理器
在多个数据源配置好之后需要手动管理事务确保每个数据源的操作在不同的事务上下文中进行。
使用 Transactional 指定事务管理器应该加在需要使用该事务管理器进行事务管理的 服务层方法或类 上。通过 Transactional 注解来指定使用哪个事务管理器。这样Spring 会使用指定的事务管理器来管理该方法的事务。
Service
Transactional(transactionManager primaryDbTransactionManager) // 显式指定事务管理器
public class AdminServiceImpl implements AdminService {Autowiredprivate FakeDomainMapper fakeDomainMapper;Autowiredprivate FakeUserService fakeUserService;/*** 新增域名*/Overridepublic void addFakeDomain(String domain, String domainDescription) {String loginUsername FakeSecurityUtil.getUsername();if (!fakeUserService.isFakeUserAdmin(loginUsername)) {throw new FakeServiceException(FORBIDDEN);}FakeDomainEntity fakeDomainEntity new FakeDomainEntity();fakeDomainEntity.setFakeDomain(domain);if (domainDescription ! null) {fakeDomainEntity.setFakeDescription(domainDescription);}fakeDomainEntity.setFakeCreated(new Date());fakeDomainEntity.setFakeModified(new Date());// 设置默认的虚拟配额String fakeDefaultSettings default_user_quota:2048;;fakeDomainEntity.setFakeSettings(fakeDefaultSettings);fakeDomainMapper.insertFakeDomain(fakeDomainEntity);}
}
Transactional(transactionManager primaryDbTransactionManager) 使得 addFakeDomain 方法使用 primaryDbTransactionManager 来管理事务这样该方法的事务操作会应用到 primaryDataSource 数据源上。
三、问题说明will not be managed by Spring
在使用 Transactional 注解时如果有多个事务管理器例如多数据源配置需要特别注意 指定事务管理器。
否则Spring 无法自动决定使用哪个事务管理器来管理当前方法的事务可能导致事务 无法被 Spring 管理从而出现错误或者无法保证事务的一致性。
如果没有指定正确的事务管理器Spring 可能会抛出类似如下的错误 这个问题通常出现在以下两种情况下 多个数据源 应用程序配置了多个数据源每个数据源有自己的事务管理器。Spring 可能不知道应该使用哪个事务管理器来管理当前方法的事务。 未指定事务管理器 在有多个事务管理器的环境下Transactional 默认使用主数据源的事务管理器。如果你没有显式指定事务管理器可能会导致事务无法被正确管理或者使用错误的事务管理器。 四、总结
通过上述配置系统能够实现同时操作两个不同的数据源每个数据源有独立的事务管理、MyBatis 配置等确保了在进行跨库操作时能够稳定运行。每个模块的配置都进行了明确的注释方便维护和修改。 在有 多个数据源 或 多个事务管理器 的情况下必须显式指定 transactionManager否则事务将不会被 Spring 管理可能导致错误。 使用 Transactional(transactionManager primaryDbTransactionManager) 来明确指定事务管理器。 默认情况下如果没有显式指定事务管理器Spring 只会使用主数据源的事务管理器其他数据源的事务管理器将无法生效。 通过正确的事务管理器配置可以确保每个方法或服务层类的事务控制是正确的从而避免由于事务管理不当导致的数据库操作异常或数据不一致问题。