本章内容主要包含两部分:Spring 所使用的操作数据库的技术之一,JDBC模板的使用;另一部分则为 Spring 对于事务的管理。
Spring 与 Dao 部分,是 Spring 的两大核心技术 loC 与 AOP 的典型应用体现:
(1)对于 JDBC 模板的使用,是 loC 的应用,是将 JDBC 模板对象注入给了 Dao 层的实现类。
(2)对于 Spring 的事务管理,是 AOP 的应用,将事务作为切面织入到了 Service 层的业务方法中。
Spring 与 JDBC 模板
为了避免直接使用 JDBC 而带来的复杂且冗长的代码,Spring 提供了一个强有力的模板类 —— JdbcTemplate 来简化 JDBC 操作。并且,数据源 DataSource 对象与模板 JdbcTemplate 对象均可通过 Bean 的形式定义在配置文件中,充分发挥了依赖注入的威力。
举例:项目Spring_Dao_ JdbcTemplate。
导入 Jar 包
除了 Spring 的基本 Jar 包,数据库驱动 Jar 外,还需要导入两个 Jar 包。她们均在 Spring 框架解压目录下的 libs 目录中。
(1)Spring 的 JDBC Jar 包
(2)Spring 的事务 Jar 包
搭建测试环境
(1)定义实体类 User
(2)定义数据库及表
(3)定义 IUserDao
(4)初步定义 UserDaoImpl
这里仅仅定义一个 UserDaoImpl 类实现了 IUserDao 接口,但不具体写每个方法的方法实现。保持默认即可。后面会逐个通过 Jdbc 模板来实现。
(5)定义 IUserService
(6)定义 UserServiceImpl
(7)定义测试类 MyTest
数据源的配置
使用 JDBC 模板,首先需要配置好数据源,数据源直接以 Bean 的形式配置在 Spring 配置文件中。根据数据源的不同,其配置方式也不同。下面主要讲解三种常用数据源的配置方式:
① Spring 默认的数据源
② DBCP 数据源
③ C3P0 数据源
(1)Spring 默认数据源 DriverManagerDataSource
Spring 默认的数据源为 DriverManagerDataSource,其有一个属性 DriverClassName,用于接收 DB 驱动。
Ctrl + O 查看类结构及源码:
DriverManagerDataSource 类继承自 AbstractDriverBasedDataSource。 其有三个属性用于接收连接数据库的URL、用户名与密码。
Ctrl + O 查看父类的类结构及源码:
(2)DBCP 数据源 BasicDataSource
DBCP,DataBase Connection Pool,是 apache 下的项目,使用该数据源,需要导入两个 Jar 包。它们在 Spring 依赖库的解压目录的 org.apache.commons 目录中 dbcp 与 pool 子包中。
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.pool-1.5.3.jar
DBCP 数据源是 BasicDataSource,Ctrl + O 查看其类结构可看到,其有driverClassName、url、username、 password 四个DB连接属性。
(3)C3P0 数据源 ComboPooledDataSource
使用 C3P0 数据源,需要导入一个 Jar 包,在 Spring 依赖库的解压目录的 com.mchange.c3p0 目录。
C3P0 数据源是 ComboPooledDataSource ,Ctrl + O 查看其类结构可看到,其有driverClass、jdbcUrl、user、 password 四个DB连接属性。
从属性文件读取数据库连接信息
为了便于维护,可以将数据库连接信息写入到属性文件中,使 Spring 配置文件从中读取数据。
属性文件名称随意,但一般都放在 src 下。
Spring 配置文件从属性文件中读取数据时,需要在<property/>的 value 属性中使用 ${},将属性文件中定义的 key 括起来,以引用指定属性的值。
该属性文件若要被 Spring 配置文件读取,其必须在配置文件中进行注册。注册方式有两种:
① <bean/>方式
② <context/>方式
(1)<bean/>方式 — 使用 class 为 PropertyPlaceholderConfigurer
以 PropertyPlaceholderConfigurer 类的 bean 实例的方式进行注册。该类有一个属性
location,用于指定属性文件的位置。这种方式不常用。
(2)<context:property-placeholder/>
该方式要求在 Spring 配置文件头部加入 context 的约束,即修改配置文件头。
<context:property-placeholder/>标签中有一个属性 location,用于指定属性文件的位置。
配置 JDBC 模板
JDBC 模板类 JdbcTemplate 从其父类 JdbcAccessor 继承了一个属性 dataSource,用于接收数据源。
查看 JdbcTemplate 源码,及 JdbcAccessor 的类结构:
Dao 实现类继承 JdbcDaoSupport 类
JdbcDaoSupport 类中有一个属性 JdbcTemplate,用于接收 JDBC 模板。所以 Dao 实现类继承了JdbcDaoSupport 类后,也就具有了 JDBC 模板属性。在配置文件中,只要将模板对象注入即可。
再仔细查看 JdbcDaoSupport 类,发现其有一个 dataSource 属性,查看 setDataSource() 方法体可知,若JDBC模板为 null,则会自动创建一个模板对象。
故,在 Spring 配置文件中,对于 JDBC 模板对象的配置完全可以省去,而是在 Dao 实现类中直接注入数据源对象。这样会让系统白动创建 JDBC 模板对象。
对 DB 的增、删、改操作
JdbcTemplate 类中提供了对 DB 进行修改、查询的方法。 Dao 实现类使用继承自 JdbcDaoSupport 的 getTemplate()方法,可以获取到 JDBC 模板对象。
对 DB 的增、删、改都是通过 update() 方法实现的。该方法常用的重载方法有两个:
public int update ( String sql)
public int update ( String sql, Object.. args)
第1个参数为要执行的 sq l语句,第2个参数为要执行的 sql 语句中所包含的动态参数。其返回值为所影响记录的条数。一般不用。
对 DB 的查询操作
JDBC 模板的查询结果均是以对象的形式返回。根据返回对象类型的不同,可以将查询分为两类:简单对象查询与自定义对象查询。
简单对象查询:查询结果为String、Integer 等简单对象类型,或该类型做为元素的集合类型,如List<String>等。
自定义对象查询:查询结果为自定义类型,如 User 等,或该类型做为元素的集合类型,如 List<User> 等。
(1)简单对象查询
常用的简单对象查询方法有:查询结果为单个对象的 queryForObject() 与查询结果为 List 的 queryForList()。
pubic T queryForObject (String sql, Class<T> type, Object... args)
pubic List<T> queryForList (String sql, Class<T> type, Objec.. args)
(2)自定义对象查询
常用的自定义对象查询方法有:查询结果为单个对象的 queryForObject() 与查询结果为 List 的 query()。
pubic T queryForObject (String sql, RowMapper<T> m , 0bject... args)
pubic List<T> query (String sq|l, RowMapper<T > m, bject... args)
注意,RowMapper 为记录映射接口,用于将查询结果集中每一条记录包装为指定对象。
该接口中有一个方法需要实现:
public Object mapRow(ResultSet rs, int rowNum)
参数 rowNum 表示总的结果集中当前行的行号,但参数 rs 并不表示总的结果集,而是表示 rowNum 所代表的当前行的记录所定义的结果集,仅仅是当前行的结果。
一般,该方法体中就是实现将查询结果中当前行的数据包装为一个指定对象。
- 注意:JDBC 模板对象是多例的
JdbcTemplate 对象是多例的,即系统会为每一个使用模板对象的线程(方法)创建一个JdbcTemplate 实例,并且在该线程(方法)结束时,自动释放 JdbcTemplate 实例。所以在每次使用 JdbcTemplate 对象时,都需要通过 getJdbcTemplate() 方法获取。
网友评论