天天看点

Spring与JDBC模板

Spring 所使用的操作数据库的技术: JDBC 模板的使用和 Spring 对于事务的管理。

  • JDBC 模板的使用,是 IoC 的应用,将 JDBC 模板对象注入给了 Dao 层的实现类。
  • Spring 的事务管理, 是 AOP 的应用,将事务作为切面织入到了 Service 层的业务方法中。

为了避免直接使用 JDBC 而带来的复杂且冗长的代码, Spring 提供了一个强有力的模板类——JdbcTemplate 来简化 JDBC 操作。并且,数据源 DataSource 对象与模板 JdbcTemplate 对象均可通过 Bean 的形式定义在配置文件中,充分发挥了依赖注入的威力。

数据源的配置

使用 JDBC 模板,首先需要配置好数据源,数据源直接以 Bean 的形式配置在 Spring 配置文件中。根据数据源的不同,其配置方式不同。常用数据源的配置方式有三种:

  1. Spring 默认的数据源
  2. DBCP 数据源
  3. C3P0 数据源

Spring 默认的数据源

Spring 默认的数据源为 DriverManagerDataSource,其有一个属性 DriverClassName,用于接收 DB 驱动。DriverManagerDataSource 类继承自 AbstractDriverBasedDataSource。其有三个属性用于接收连接数据库的 URL、用户名与密码。

<!-- 注册数据源:Spring内置连接池 -->
	<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://localhost:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="123456"/>
	</bean>
           

DBCP 数据源

DBCP(DataBase Connection Pool),是 Apache 下的项目,DBCP 数据源是 BasicDataSource,其有 driverClassName、 url、 username、 password 四个 DB 连接属性。

<!-- 注册数据源:DBCP -->
	<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://localhost:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="123456"/>
	</bean>
           

C3P0 数据源

C3P0 数据源是 ComboPooledDataSource ,其有 DriverClass、JdbcUrl、 User、 Password 四个 DB 连接属性。

<!-- 注册数据源:C3P0 -->
	<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driver}"/>
		<property name="jdbcUrl" value="${jdbc.url}"/>
		<property name="user" value="${jdbc.user}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
           

从属性文件读取数据库连接信息

为了便于维护,可以将数据库连接信息写入到属性文件中,使 Spring 配置文件从中读取数据。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.user=root
jdbc.password=123456
           

Spring 配置文件从属性文件中读取数据时,需要在<property/>的 value 属性中使用${ },将在属性文件中定义的 key 括起来,以引用指定属性的值。

Spring与JDBC模板

该属性文件若要被 Spring 配置文件读取,其必须在配置文件中进行注册。注册方式有两种:

  1. <bean/>方式
  2. <context/>方式

<bean/>方式

以 PropertyPlaceholderConfigurer 类的 bean 实例的方式进行注册。该类有一个属性 location,用于指定属性文件的位置。

<!-- 注册属性文件:方式一 -->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location" value="classpath:jdbc.properties"/>
	</bean>
           

<context:property-placeholder/>方式

<!-- 注册属性文件:方式二 -->
	<context:property-placeholder location="classpath:jdbc.properties"/>
           

注意:

该方式要求在 Spring 配置文件头部加入 context 的约束,<context:property-placeholder/>标签中有一个属性 location,用于指定属性文件的位置。

配置JDBC模板

JDBC 模板类 JdbcTemplate 从其父类 JdbcAccessor 继承了一个属性 dataSource,用于接收数据源。

<!-- 注册JdbcTemplate -->
	
	<bean id="myJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="myDataSource"/>
	</bean>
           

Dao实现类继承JdbcDaoSupport

JdbcDaoSupport 类中有一个属性 JdbcTemplate,用于接收 JDBC 模板。所以 Dao 实现类继承了 JdbcDaoSupport 类后,也就具有了 JDBC 模板属性。在配置文件中,只要将模板对象注入即可。

Spring与JDBC模板

对DB的增、删、改操作

JdbcTemplate 类中提供了对 DB 进行修改、查询的方法。 Dao 实现类使用继承自 JdbcDaoSupport 的 getTemplate()方法,可以获取到 JDBC 模板对象。

public interface IStudentDao {
	void insertStudent(Student student);
	void deleteById(int id);
	void updateStudent(Student student);
	
	List<String> selectAllStudentsNames();
	String selectStudentNameById(int id);
	
	List<Student> selectAllStudents();
	Student selectStudnetById(int id);

}
           

对 DB 的增、删、改都是通过 update()方法实现的。该方法常用的重载方法有两个:

第 1 个参数为要执行的 sql 语句,第 2 个参数为要执行的 sql 语句中所包含的动态参数。其返回值为所影响记录的条数。一般不用。

Spring与JDBC模板

对DB的查询操作

JDBC 模板的查询结果均是以对象的形式返回。根据返回对象类型的不同,可以将查询分为两类:

  • 简单对象查询:查询结果为 String、 Integer 等简单对象类型,或该类型做为元素的集合类型,如 List<String>等。
  • 自定义对象查询:查询结果为自定义类型,如 User 等,或该类型做为元素的集合类型,如 List<User>等。

简单对象查询

常用的简单对象查询方法有:查询结果为单个对象的 queryForObject()与查询结果为 List 的 queryForList()。

@Override
	public List<String> selectAllStudentsNames() {
		String sql = "select name from student";
		return this.getJdbcTemplate().queryForList(sql, String.class);
	}

	@Override
	public String selectStudentNameById(int id) {
		String sql = "select name from student where id=?";
		return this.getJdbcTemplate().queryForObject(sql, String.class, id);
	}
           

自定义对象查询

常用的自定义对象查询方法有:查询结果为单个对象的 queryForObject()与查询结果为 List 的 query()。

RowMapper 为记录映射接口,用于将查询结果集中每一条记录包装为指定对象。该接口中有一个方法需要实现:

参数 rowNum 表示总的结果集中当前行的行号,但参数 rs 并不表示总的结果集,而是表示 rowNum 所代表的当前行的记录所定义的结果集,仅仅是当前行的结果。一般来说,该方法体中就是实现将查询结果中当前行的数据包装为一个指定对象。

public class StudentRowMapper implements RowMapper<Student> {

	// rs:当查询出总的结果集后,框架会自动遍历这个结果集,每一次遍历的一行数据,都会被存放到
	//     这个方法的rs参数中。也就是说,这里的rs代表的是一行数据,并非所有查询结果。换个角度
	//     来说,只要能执行到这个方法,就说明这里的rs不会是空的
	@Override
	public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
		Student student = new Student();
		student.setId(rs.getInt("id"));
		student.setName(rs.getString("name"));
		student.setAge(rs.getInt("age"));
		return student;
	}

}
           
@Override
	public List<Student> selectAllStudents() {
		String sql = "select id,name,age from student";
		return this.getJdbcTemplate().query(sql, new StudentRowMapper());
	}

	@Override
	public Student selectStudnetById(int id) {
		String sql = "select id,name,age from student where id=?";
		return this.getJdbcTemplate().queryForObject(sql, new StudentRowMapper(), id);
	}
           

注意:

JdbcTemplate 对象是多例的,即系统会为每一个使用模板对象的线程(方法)创建一个 JdbcTemplate 实例,并且在该线程(方法)结束时,自动释放 JdbcTemplate 实例。所以在每次使用 JdbcTemplate 对象时,都需要通过 getJdbcTemplate()方法获取。