为使JDBC更加易于使用,Spring在JDBC API上定义了抽象层,以此建立一个JDBC存取框架。作为Spring JDBC框架的核心,JDBC模板的设计目的是为不同类型的JDBC操作提供模板方法,每个模板方法都能控制整个过程,并允许覆盖过程中的特定任务;该方式可以在尽可能保留灵活性的情况下, 将数据库存取的工作量降到最低。
Spring对JDBC的支持的核心测试代码下载地址:http://download.csdn.net/download/bingbeichen/9783606。
Spring的JdbcTemplate可以实现更新、批量更新、查询单行、查询多行和查询单值等功能,具体实现步骤如下说明。
第一步:额外导入C3P0数据源、MySQL数据库和JdbcTemplate所依赖的jar包,具体如下图所示:
第二步:在src目录下创建db.properties文件,用于存放连接数据库所需要的基本信息,文件内容如下所示:
jdbc.user=root
jdbc.password=root
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///spring4
jdbc.initPoolSize=5
jdbc.maxPoolSize=10
第三步:在src目录下创建Spring bean的配置文件applicationContext.xml,用于配置C3P0数据源和Spring的JdbcTemplate,核心配置代码如下:
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}">property>
<property name="password" value="${jdbc.password}">property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}">property>
<property name="driverClass" value="${jdbc.driverClass}">property>
<property name="initialPoolSize" value="${jdbc.initPoolSize}">property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}">property>
bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
第四步:创建JUnit测试类,开始使用JdbcTemplate操作数据库,测试类的核心代码如下:
package com.qiaobc.spring.jdbc;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class JDBCTest {
private ApplicationContext ctx = null;
private JdbcTemplate jdbcTemplate = null;
{
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
}
/**
* 1. 测试C3P0数据源是否配置成功
* @throws Exception
*/
@Test
public void testDataSource() throws Exception {
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println(dataSource.getConnection());
}
/**
* 2.1 更新:执行INSERT、UPDATE 或 DELETE操作
*/
@Test
public void testUpdate() {
String sql = "UPDATE employees SET last_name = ? WHERE id = ?";
jdbcTemplate.update(sql, "bb", 1);
}
/**
* 2.2 批量更新:执行批量的INSERT、UPDATE 或 DELETE操作
* 异常:Field 'id' doesn't have a default value,原因是创建表时未设置主键为自增模式
*/
@Test
public void testBatchUpdate() {
String sql = "INSERT INTO employees(first_name, last_name, email) VALUES(?, ?, ?)";
List
JdbcTemplate利用了Java 1.5的特性(自动装箱、泛型、可变长度等)来简化开发,其实现DAO类的方式主要有两种,具体说明如下:
package com.qiaobc.spring.jdbc.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.qiaobc.spring.jdbc.Employee;
/**
* 推荐使用:在使用时仅创建一个JdbcTemplate的实例即可使用
* 需要在配置文件中设置自动扫描该类:
*
* @author qiaobc
*
*/
@Repository
public class EmployeeDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public Employee get(Integer id) {
String sql = "SELECT id, first_name firstName, last_name lastName, email FROM employees WHERE id = ?";
RowMapper rowMapper = new BeanPropertyRowMapper<>(Employee.class);
return jdbcTemplate.queryForObject(sql, rowMapper , id);
}
}
package com.qiaobc.spring.jdbc.dao;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;
import com.qiaobc.spring.jdbc.Employee;
/**
* 不推荐使用,推荐直接使用JdbcTemplate作为DAO类的成员变量
* @author qiaobc
* Caused by: java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
*/
@Repository
public class EmployeeKzDao extends JdbcDaoSupport {
@Autowired
public void setDataSource1(DataSource dataSource) { // 其父类的setDataSource()方法是final的
setDataSource(dataSource);
}
public Employee get(Integer id) {
String sql = "SELECT id, first_name firstName, last_name lastName, email FROM employees WHERE id = ?";
RowMapper rowMapper = new BeanPropertyRowMapper<>(Employee.class);
return getJdbcTemplate().queryForObject(sql, rowMapper , id);
}
}
Spring的NamedParameterJdbcTemplate类支持具名参数,即SQL语句按名称(以冒号开头)而不是按位置(以?号表示)进行参数绑定,其更易于维护且可读性较强。
@Test
public void testNamedParameterJdbcTemplate() {
String sql = "INSERT INTO employees(first_name, last_name, email) VALUES(:firstName, :lastName, :email)";
// 可以使用具名参数,即按名称进行参数绑定,但较为麻烦
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("firstName", "qiao");
paramMap.put("lastName", "bei");
paramMap.put("email", "[email protected]");
namedParameterJdbcTemplate.update(sql, paramMap);
// 使用update(String sql, SqlParameterSource paramSource)方法实现更新操作较为简单,要求具名参数名和类的属性名相同
Employee employee = new Employee(null, "qiao", "dabei", "[email protected]");
SqlParameterSource paramSource = new BeanPropertySqlParameterSource(employee);
namedParameterJdbcTemplate.update(sql, paramSource);
}