JdbcTemplate 的使用步骤

    技术2022-07-10  187

    概述

    它是 spring 提供的一个对象,对原始的 JDBC 的 API 操作进行简单的封装。它更像是一个工具,和 DButils 很像,只是 Spring 不叫 util,叫 Template(模板)。

    除此之外,Spring 还提供了很多的模板,例如操作关系型数据库的 HibernateTemplate,操作 NoSql 数据库的 RedisTemplate,操作消息队列的 JmsTemplate等等

    下面采用的是 Maven 创建的工程

    使用步骤

    导入 Spring-jdbc 和 spring-tx 的依赖创建数据库表和实体创建 JdbcTemplate 对象执行数据库操作。

    导入依赖

    <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> <scope>test</scope> </dependency> </dependencys>

    其中 spring-jdbc 是 jdbcTemplate 基本支持,spring-tx 用于控制事务,spring-context 是 spring 的基本,mysql 是驱动,c3p0 是连接池,junit 使用了测试方便,这样无需写 main 函数。

    创建数据库和实体

    有一张 acc 表,里面有两个字段,分别为 account( varchar ) 和 age( varchar ),实体类 account 如下

    public class Account { private String account; private String age; @Override public String toString() { return "Account{" + "account='" + account + '\'' + ", age='" + age + '\'' + '}'; } public void setAccount(String account) { this.account = account; } public void setAge(String age) { this.age = age; } public String getAccount() { return account; } public String getAge() { return age; } }

    创建 JdbcTemplate 对象

    配置数据源

    因为是用在数据库上的,所以需要在 spring 的配置文件配置数据源,这里使用的 c3p0 连接池技术。

    <!--配置数据源对象--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.drivar}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> </bean>

    配置 JdbcTemplate 对象

    这里配置对象,并且交给 Spring 容器管理。

    <!--配置 jdbc 模板对象--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>

    执行数据库的操作

    插入操作

    // 把 junit 的测试加给 spring,这样在每次运行测试之前,他都可以帮我们生成 spring 容器。 @RunWith(SpringJUnit4ClassRunner.class) //指定上下文配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class MainTestCRUD { @Autowired private JdbcTemplate jdbcTemplate; @Test public void test1() throws PropertyVetoException { int row = jdbcTemplate.update("insert into acc values(?,?)","t","18"); System.out.println(row); } }

    修改操作

    // 把 junit 的测试加给 spring,这样在每次运行测试之前,他都可以帮我们生成 spring 容器。 @RunWith(SpringJUnit4ClassRunner.class) //指定上下文配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class MainTestCRUD { @Autowired private JdbcTemplate jdbcTemplate; @Test public void test2() throws PropertyVetoException { int row = jdbcTemplate.update("update acc set age=? where account= ? ","20","tom"); System.out.println(row); } }

    删除操作

    // 把 junit 的测试加给 spring,这样在每次运行测试之前,他都可以帮我们生成 spring 容器。 @RunWith(SpringJUnit4ClassRunner.class) //指定上下文配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class MainTestCRUD { @Autowired private JdbcTemplate jdbcTemplate; @Test public void test3() throws PropertyVetoException { int row = jdbcTemplate.update("delete from acc where account=?","tom"); System.out.println(row); } }

    查询操作

    查询多个对象

    // 把 junit 的测试加给 spring,这样在每次运行测试之前,他都可以帮我们生成 spring 容器。 @RunWith(SpringJUnit4ClassRunner.class) //指定上下文配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class MainTestCRUD { @Autowired private JdbcTemplate jdbcTemplate; @Test public void test4() throws PropertyVetoException { List<Account> query = jdbcTemplate.query("select * from acc", new BeanPropertyRowMapper<>(Account.class)); for (Account temp: query ) { System.out.println(query); } } }

    查询单个对象

    // 把 junit 的测试加给 spring,这样在每次运行测试之前,他都可以帮我们生成 spring 容器。 @RunWith(SpringJUnit4ClassRunner.class) //指定上下文配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class MainTestCRUD { @Autowired private JdbcTemplate jdbcTemplate; @Test public void test4() throws PropertyVetoException { Account query = jdbcTemplate.queryForObject("select * from acc where account=? ", new BeanPropertyRowMapper<>(Account.class),"tom"); System.out.println(query); } }

    查询聚合函数的结果

    // 把 junit 的测试加给 spring,这样在每次运行测试之前,他都可以帮我们生成 spring 容器。 @RunWith(SpringJUnit4ClassRunner.class) //指定上下文配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class MainTestCRUD { @Autowired private JdbcTemplate jdbcTemplate; @Test public void test4() throws PropertyVetoException { int i = jdbcTemplate.queryForObject("select count(*) from acc",Integer.class); System.out.println(i); } }

    扩展

    在 JdbcTemplate 中,都是对 sql 使用占位符 ?来占位,并且在 update 或者 query 参数传参时候,都有顺序要求,如果占位符很多,顺序记不清怎么办?

    Spring 还提供了一个 JdbcTemplate 的子类 NamedParameterJdbcTemplate 来解决这个问题。那么如何用?

    把 JdbcTemplate 的 bean 配置改成如下

    <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"> <constructor-arg ref="dataSource"></constructor-arg> </bean>

    对数据库的操作,如插入改成如下,其他的操作类似

    修改 Sql 语句

    String sql = "insert into acc values(:account,:age)";

    添加 Map 关系

    Map<String,Object> map = new HashMap<>(); map.put("account", "haha"); map.put("age", "18");

    执行

    namedParameterJdbcTemplate.update(sql, map);

    整个代码如下

    // 把 junit 的测试加给 spring,这样在每次运行测试之前,他都可以帮我们生成 spring 容器。 @RunWith(SpringJUnit4ClassRunner.class) //指定上下文配置文件 @ContextConfiguration("classpath:applicationContext.xml") public class MainTestCRUD { @Autowired private NamedParameterJdbcTemplate namedParameterJdbcTemplate; @Test public void test4() throws PropertyVetoException { String sql = "insert into acc values(:account,:age)"; Map<String,Object> map = new HashMap<>(); map.put("account", "haha"); map.put("age", "18"); namedParameterJdbcTemplate.update(sql, map); } }
    Processed: 0.018, SQL: 9