You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用spring-jdbc template和spring-transaction实现两模块共享DAO类

最优解决方案

不要在共享module2中定义数据源、事务管理器这类和业务运行环境强绑定的配置,最优方案是共享module2只提供DAO、实体类的公共实现,由两个业务模块(module1、module3)各自编写自己的数据源、JDBC模板、事务相关配置。


方案核心原因

  • 公共模块职责单一原则:module2作为公共依赖,核心作用是提供可复用的数据库访问能力,不应该绑定上层业务的数据源地址、事务策略等环境配置,否则会大幅提高耦合度,后续新增业务模块需要适配不同数据库时完全无法扩展。
  • 避免配置冲突:如果在module2中硬编码两个数据源配置,上层模块引入依赖时会默认加载所有配置,很容易和业务模块自己的配置产生冲突,也会引入不必要的冗余Bean。
  • 灵活适配不同业务需求:两个业务模块的事务需求完全不同,各自配置可以独立控制开关,不需要事务能力的module3不用引入额外的事务相关组件,减少不必要的性能开销。

具体实现步骤

第一步:改造module2的DAO实现,完全解耦配置

module2中的DAO不要硬编码JdbcTemplate实例,通过构造方法注入JdbcTemplate即可,不需要加任何Spring相关的配置类:

// module2中的DAO示例
public class OrderDao {
    private final JdbcTemplate jdbcTemplate;
    // 构造方法注入JdbcTemplate,完全不关心JdbcTemplate的来源和配置策略
    public OrderDao(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    // 下方编写你的增删改查方法即可
    public Order getById(Long id) {
        return jdbcTemplate.queryForObject("select * from order where id = ?", 
            (rs, rowNum) -> new Order(rs.getLong("id"), rs.getString("order_no")), 
            id);
    }
}

第二步:编写module3的配置(无事务、自动提交)

module3所有操作都是自动提交,不需要配置事务管理器,只需要配置数据源和JdbcTemplate,注入到共享DAO中即可,Spring JdbcTemplate默认就是自动提交模式,完全符合需求:

@Configuration
@ComponentScan(basePackages = "com.yourdomain.module3.service")
public class Module3Config {
    // 配置当前模块的数据源
    @Bean
    public DataSource module3DataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://你的数据库地址/库名");
        dataSource.setUsername("账号");
        dataSource.setPassword("密码");
        return dataSource;
    }
    // 配置JdbcTemplate
    @Bean
    public JdbcTemplate module3JdbcTemplate() {
        return new JdbcTemplate(module3DataSource());
    }
    // 实例化共享DAO,传入当前模块的JdbcTemplate
    @Bean
    public OrderDao orderDao() {
        return new OrderDao(module3JdbcTemplate());
    }
}

第三步:编写module1的配置(支持事务)

module1需要事务支持,除了基础的数据源、JdbcTemplate配置外,额外添加事务管理器、开启事务注解支持即可,共享DAO完全不用修改:

@Configuration
@ComponentScan(basePackages = "com.yourdomain.module1.service")
@EnableTransactionManagement // 开启Spring声明式事务支持
public class Module1Config {
    // 配置当前模块的数据源,也可以和module3用同一个数据库,自行修改配置即可
    @Bean
    public DataSource module1DataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://你的数据库地址/库名");
        dataSource.setUsername("账号");
        dataSource.setPassword("密码");
        return dataSource;
    }
    // 配置JdbcTemplate
    @Bean
    public JdbcTemplate module1JdbcTemplate() {
        return new JdbcTemplate(module1DataSource());
    }
    // 配置事务管理器
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(module1DataSource());
    }
    // 实例化共享DAO,传入当前模块的JdbcTemplate
    @Bean
    public OrderDao orderDao() {
        return new OrderDao(module1JdbcTemplate());
    }
}

需要事务的业务方法直接添加@Transactional注解即可,方法内所有调用共享DAO的操作都会自动纳入同一个事务:

@Service
public class TransactionService {
    private final OrderDao orderDao;
    // 构造注入共享DAO
    public TransactionService(OrderDao orderDao) {
        this.orderDao = orderDao;
    }
    // 该方法内所有DAO操作在同一个事务中,异常会自动回滚
    @Transactional(rollbackFor = Exception.class)
    public void batchOperate() {
        orderDao.insert(new Order(1, "xxx1"));
        orderDao.updateStatus(2, "已支付");
        orderDao.deleteById(3);
    }
}

额外优化建议

如果两个业务模块使用同一个数据库,数据源配置完全一致,可以把数据源配置抽成一个单独的公共配置模块,避免重复代码,事务相关配置仍然由各业务模块自己控制即可。

内容的提问来源于stack exchange,提问作者jimmayhem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 04:18:05