Spring数据访问:JDBC、事务管理与ORM集成实战

一、Spring JDBC:简化数据库操作

Spring JDBC模块通过模板模式消除了传统JDBC开发中的样板代码,提供了更简洁的数据访问方式。

1. JdbcTemplate

JdbcTemplate是Spring JDBC的核心类,处理了连接获取、异常转换等底层细节。

@Repository
public class UserRepository {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public User findById(Long id) {
        return jdbcTemplate.queryForObject(
            "SELECT * FROM users WHERE id = ?",
            (rs, rowNum) -> new User(
                rs.getLong("id"),
                rs.getString("username"),
                rs.getString("email")
            ),
            id
        );
    }
    
    public int updateEmail(Long id, String newEmail) {
        return jdbcTemplate.update(
            "UPDATE users SET email = ? WHERE id = ?",
            newEmail, id
        );
    }
}

最佳实践

  • 将JdbcTemplate注入到DAO层类中
  • 使用RowMapper或Lambda表达式处理结果集映射
  • 对于复杂查询,考虑使用BeanPropertyRowMapper

2. NamedParameterJdbcTemplate

相比JdbcTemplate的位置参数,NamedParameterJdbcTemplate支持命名参数,提高SQL可读性。

public List<User> findByStatus(String status) {
    String sql = "SELECT * FROM users WHERE status = :status";
    Map<String, Object> params = new HashMap<>();
    params.put("status", status);
    
    return namedParameterJdbcTemplate.query(
        sql,
        params,
        new BeanPropertyRowMapper<>(User.class)
    );
}

3. SimpleJdbcInsert

简化INSERT操作,自动处理主键生成等常见需求。

public Long addUser(User user) {
    SimpleJdbcInsert insert = new SimpleJdbcInsert(jdbcTemplate)
        .withTableName("users")
        .usingGeneratedKeyColumns("id");
    
    Map<String, Object> params = new HashMap<>();
    params.put("username", user.getUsername());
    params.put("email", user.getEmail());
    
    return insert.executeAndReturnKey(params).longValue();
}

二、Spring事务管理

Spring提供了统一的事务抽象,支持声明式和编程式事务管理。

1. 声明式事务(@Transactional)

@Service
public class OrderService {
    
    @Transactional
    public void placeOrder(Order order) {
        // 业务逻辑
        orderRepository.save(order);
        inventoryService.reduceStock(order.getItems());
        paymentService.processPayment(order);
    }
}

配置要点

@Configuration
@EnableTransactionManagement
public class AppConfig {
    
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

2. 编程式事务(TransactionTemplate)

public void batchProcess(List<Data> dataList) {
    transactionTemplate.execute(status -> {
        try {
            dataList.forEach(dataProcessor::process);
            return true;
        } catch (Exception e) {
            status.setRollbackOnly();
            throw e;
        }
    });
}

3. 传播行为与隔离级别

@Transactional(
    propagation = Propagation.REQUIRES_NEW,
    isolation = Isolation.READ_COMMITTED,
    timeout = 30
)
public void criticalOperation() {
    // 需要独立事务的关键操作
}

传播行为类型

  • REQUIRED(默认):当前有事务则加入,没有则新建
  • REQUIRES_NEW:总是新建事务
  • NESTED:嵌套事务
  • SUPPORTS/MANDATORY/NOT_SUPPORTED/NEVER

隔离级别

  • DEFAULT:使用数据库默认
  • READ_UNCOMMITTED:可能脏读
  • READ_COMMITTED:防止脏读
  • REPEATABLE_READ:防止不可重复读
  • SERIALIZABLE:最高隔离级别

三、ORM集成

1. Hibernate集成

@Configuration
@EnableTransactionManagement
public class HibernateConfig {
    
    @Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setPackagesToScan("com.example.domain");
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }
    
    private Properties hibernateProperties() {
        Properties props = new Properties();
        props.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
        props.put("hibernate.show_sql", true);
        props.put("hibernate.format_sql", true);
        return props;
    }
    
    @Bean
    public HibernateTransactionManager transactionManager(
            SessionFactory sessionFactory) {
        return new HibernateTransactionManager(sessionFactory);
    }
}

2. JPA集成

@Repository
public class UserRepositoryImpl implements UserRepositoryCustom {
    
    @PersistenceContext
    private EntityManager entityManager;
    
    @Override
    public List<User> findActiveUsers() {
        return entityManager.createQuery(
            "SELECT u FROM User u WHERE u.active = true", User.class)
            .getResultList();
    }
}

3. MyBatis集成

@Mapper
public interface UserMapper {
    
    @Select("SELECT * FROM users WHERE id = #{id}")
    User findById(@Param("id") Long id);
    
    @Insert("INSERT INTO users(username, email) VALUES(#{username}, #{email})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    void insert(User user);
}

集成配置

@Configuration
public class MyBatisConfig {
    
    @Bean
    public SqlSessionFactory sqlSessionFactory(
            DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage("com.example.domain");
        return sessionFactory.getObject();
    }
}

四、性能优化建议

  1. JDBC批量操作

    jdbcTemplate.batchUpdate(
     "INSERT INTO users(username, email) VALUES(?, ?)",
     users,
     100, // 批处理大小
     (ps, user) -> {
         ps.setString(1, user.getUsername());
         ps.setString(2, user.getEmail());
     }
    );
  2. 连接池配置

    # HikariCP配置示例
    spring.datasource.hikari.maximum-pool-size=20
    spring.datasource.hikari.connection-timeout=30000
    spring.datasource.hikari.idle-timeout=600000
  3. ORM缓存策略

    @Entity
    @Cacheable
    @org.hibernate.annotations.Cache(
     usage = CacheConcurrencyStrategy.READ_WRITE,
     region = "userCache"
    )
    public class User {
     // 实体定义
    }

五、总结对比

技术适用场景优点缺点
JdbcTemplate简单CRUD、需要精细控制SQL轻量、直接、性能好需要手动处理对象映射
Hibernate复杂领域模型、快速开发自动化程度高、缓存支持学习曲线陡峭、SQL优化难
JPA标准规范、需要切换实现标准化、可移植性好功能受限于标准
MyBatisSQL复杂度高、需要精细优化SQL控制灵活、学习成本低需要维护XML/注解

架构选择建议

  • 简单项目:JdbcTemplate + 事务管理
  • 中等复杂度:Spring Data JPA
  • 复杂查询需求:MyBatis + JPA混合模式
  • 高性能要求:JdbcTemplate + 存储过程

通过合理组合Spring的数据访问技术,可以在开发效率与系统性能之间取得良好平衡。

添加新评论