Skip to content

JdbcTemplate

概述

JdbcTemplate 是 Spring Framework 中的一个核心类,它提供了一种简单而有效的方式来处理 Java 应用程序中的 JDBC 操作。JdbcTemplate 封装了 JDBC 操作的细节,使得开发人员可以专注于业务逻辑的实现,而不必过多地关心底层的 JDBC API。

JdbcTemplate 主要提供以下几个方面的功能:

  1. 数据源配置和管理:JdbcTemplate 可以轻松地配置和管理数据源,可以使用内置的连接池或者自定义的连接池。

  2. SQL 语句的执行和结果集的处理:JdbcTemplate 封装了 SQL 语句的执行过程,可以使用预编译的 SQL 语句或者命名参数的 SQL 语句。在执行 SQL 语句之后,JdbcTemplate 可以将结果集转换为 Java 对象或者基本类型。

  3. 事务管理:JdbcTemplate 可以轻松地实现事务管理,可以使用编程式事务或者声明式事务。

JdbcTemplate入门

核心API

快速入门

  1. 准备连接池

c3p0与druid任选其一即可,本文使用druid

  1. 导入 spring-jdbc
  • spring-beans.jar
  • spring-core.jar
  • spring-jdbc.jar
  • spring-tx.jar
  • commons-logging.jar
  1. 创建 JdbcTemplate 对象

调用JdbcTemplate构造器,传入连接池对象

  1. 调用 update、query、queryForObject 等方法
java
@Test
public void testQuery() throws Exception {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource());

    List<Product> list = jdbcTemplate.query(
        "SELECT * FROM product", 
        new BeanPropertyRowMapper<>(Product.class)
    );

    System.out.println(list);
}

JdbcTemplate深入

实现聚合查询

JdbcTemplatequeryForObject方法,与query方法大致相同,不同点在于query用于处理多条结果,而queryForObject用于处理单条结果。

java
@Test
public void testCount() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource());

    int count = jdbcTemplate.queryForObject(
        "SELECT COUNT(*) FROM product", 
        Integer.class
    );

    System.out.println(count);
}

实现增删改

JdbcTemplateupdate方法用于执行DML语句。同时还可以在 SQL 语句中使用?占位,在update方法的Object... args可变参数中传入对应的参数。

新增数据

java
@Test
public void testInsert() throws Exception {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource());

    String sql = "INSERT INTO product VALUES (NULL, ?, ?)";

    jdbcTemplate.update(sql, "iPhone3GS", 3333);
    jdbcTemplate.update(sql, "iPhone4", 5000);
    jdbcTemplate.update(sql, "iPhone4S", 5001);
    jdbcTemplate.update(sql, "iPhone5", 5555);
    jdbcTemplate.update(sql, "iPhone5C", 3888);
    jdbcTemplate.update(sql, "iPhone5S", 5666);
    jdbcTemplate.update(sql, "iPhone6", 6666);
    jdbcTemplate.update(sql, "iPhone6S", 7000);
    jdbcTemplate.update(sql, "iPhone6SP", 7777);
    jdbcTemplate.update(sql, "iPhoneX", 8888);
}

修改数据

java
@Test
public void testUpdate() throws Exception {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource());

    String sql = "UPDATE product SET pname=?, price=? WHERE pid=?";

    int i = jdbcTemplate.update(sql, "XVIII", 18888, 10);

    System.out.println("受影响的行数: " + i);
}

删除数据

java
@Test
public void testDelete() throws Exception {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(DataSourceUtils.getDataSource());

    String sql = "DELETE FROM product WHERE pid=?";

    int i = jdbcTemplate.update(sql, 7);

    System.out.println("受影响的行数: " + i);
}

事务控制

借助TransactionSynchronizationManager

java
@Test
public void testTx() {
    DataSource dataSource = DataSourceUtils.getDataSource();
    
    //实例jdbcTemplate
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    
    //启动事务管理器(获取datasource操作数据库连接对象并绑定到当前线程中)
    TransactionSynchronizationManager.initSynchronization();
    
    //从数据源中获取jdbcTemplate操作的当前连接对象
    Connection connection = DataSourceUtils.getConnection(dataSource);
    
    try {
        connection.setAutoCommit(false);
    
        //添加收藏数: uid rid date
        int addFlag = favoriteDao.addFavorite(jdbcTemplate,uid, rid, new Date());
    
        //更新收藏数量
        int updateFlag = routeDao.updateRouteCountByRid(jdbcTemplate,rid);
    
        connection.commit();
    
        return  true;
    } catch (Exception e) {
        //出现异常则回滚
        try {
            connection.rollback();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
        System.out.println("回滚了!");
        return  false;
    } finally {
        try {
            //释放资源
            //释放当前线程与连接对象的绑定
            TransactionSynchronizationManager.clearSynchronization();
            //重置当前连接为自动提交事务
            connection.setAutoCommit(true);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

借助TransactionTemplate

java
@Bean(name="transactionManager")
public DataSourceTransactionManager transactionManager(@Autowired DruidDataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

@Bean(name = "txTemplate")
public TransactionTemplate transactionTemplate (@Autowired DataSourceTransactionManager transactionManager){
    return new TransactionTemplate(transactionManager);
}

@Test
public void testTx() {
    String sql1 = "INSERT INTO user_tmp(`id`, `username`) VALUES(?, ?)";
    Object[] args1 = new Object[] {22, 222};

    String sql2 = "INSERT INTO user_tmp(`id`, `username`) VALUES(?, ?)";
    Object[] args2 = new Object[] {1, 111};

    txTemplate.execute(new TransactionCallback<Object>() {
        @Override
        public Object doInTransaction(TransactionStatus transactionStatus) {
            Object savepoint = transactionStatus.createSavepoint();
            // DML执行
            try {
                int rs1 = jdbcTemplate.update(sql1, args1);
                int rs2 = jdbcTemplate.update(sql2, args2);
            } catch (Throwable e) {
                LOG.error("Error occured, cause by: {}", e.getMessage());
                transactionStatus.setRollbackOnly();
                // transactionStatus.rollbackToSavepoint(savepoint);
            }
            return null;
        }
    });
}

学习目标总结

  • 能够使用 JdbcTemplate 执行 SQL 语句
  • 能够理解 JdbcTemplate 的原理