Spring DAO
一、简介
DAO (Data Access Object)数据访问对象
Spring DAO 基于IOC,增加了一些组件,主要实现了以下的功能:
- 提供对JDBC的支持,对JDBC进行封装,简化了DAO的编写,允许JDBC使用Spring资源,
提供了AOP模式的事物管理,统一管理JDBC事物,
<bean id="tx" class="...DataSourceTransactionManager"> <!-- 开启@Transactional标记 --> <tx:annotation-driven transaction-manager="tx"/>
统一了异常处理层次,它包装的异常类型DataAccessException继承自RuntimeException,无需显示捕获
二、提供的API
Spring DAO为整合Jdbc提供了JdbcTemplate和JdbcDAOSupport类
JdbcTemplate
1. 简介
JdbcTemplate封装了connection、statement、执行SQL、释放连接资源等操作。只需要提供SQL语句和参数就可以完成对数据库的增、删、改、查。在进行查询方法时还要提供一个rowmapper方法,即记录映射,将记录转换为对象。
2. 构造方法
(1) 无参构造
(2) 1参构造 JdbcTemplate(DataSource) //最常用
这里传入的是DataSource接口的实现类对象BasicDataSource
**关于BasicDataSource的使用**
a. 在java代码中利用BasicDataSource操作jdbc
1. 创建DataSource
BasicDataSource dataSource = new BasicDataSource();
2. 设置驱动类的全名
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
3. 设置数据库的链接地址
dataSource.setUrl("jdbc:oracle:thin:@localhost:1521");
4. 设置数据库的帐号
dataSource.setUsername("liweijie");
5. 设置数据库的密码
dataSource.setPassword("123456");
6. 获取数据库的连接对象
Connection conn = dataSource.getConnection();
7. 进行数据库的操作
Statement state = conn.createStatement();
b. 将BasicDataSource配置到Spring容器中,并给其注入属性值:具体操作步骤如下:
方法一:直接注入BasicDataSource 的属性
<bean id="basicDataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
设置驱动类的全名
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
设置数据库的链接地址
<property name="url" value="jdbc:oracle:thin:@localhost:1521"></property>
设置数据库的帐号
<property name="username" value="liweijie"></property>
设置数据库的密码
<property name="password" value="123456"></property>
</bean>
方法二:将BasicDataSource的属性值存储在properties文件中进行读取
db.properties文件中的信息如下:
driverClassName:oracle.jdbc.driver.OracleDriver
url:jdbc:oracle:thin:@localhost:1521:xe
username:a2011102394
password:123456
applicationContext.xml文件中的配置如下:
<util:properties id = "db" location="classpath:db.properties">
</util:properties>
<bean id = "basicDataSource"
class = "org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value = "#{db.driverClassName}">
</property>
<property name="url"
value = "#{db.url}">
</property>
<property name="username" value = "#{db.username}"></property>
<property name="password" value = "#{db.password}" ></property>
</bean>
(3) 2参构造 JdbcTemplate(DataSource ,boolean )
3. 常用方法 主要对数据库进行增删改查的操作
queryForObject()
query()函数
用来执行查询操作 两参 参数1. 要查询的SQL语句 参数2. 结果产生时的回调函数 操作案例: template.query("select * from person", new ResultSetExtractor<List<Person>>() { /** * 当结果产生时 ,自动执行 */ @Override public List<Person> extractData(ResultSet result) throws SQLException, DataAccessException { ArrayList<Person> ps = new ArrayList<>(); while (result.next()) { String name = result.getString("name"); String age = result.getString("age"); Person p = new Person(name, age); ps.add(p); } return ps; } });
三参
参数1. 要查询的预编译SQL语句
参数2. 预编译语句中参数的填充, 是一个String 数组
参数3. 结果产生时的回调函数
操作案例:
Boolean flag = template.query("select * from person where name=? and age=?", new String[]{"明达","179"}, new ResultSetExtractor<Boolean>(){
@Override
public Boolean extractData(ResultSet result) throws SQLException, DataAccessException {
if(result.next()){
return true;
}
return false;
}
});
* 查询语句中常用的回调函数类型: *
1. RowMapper<T> 接口
回调方法为:
//参数1. 结果集对象
//参数2. 查询的行数
public <T> T mapRow(ResultSet result, int rowCount);
2. ResultSetExtractor<T> 接口
回调方法为:
//参数1. 结果集对象
public <T> T extractData(ResultSet result);
3. BeanPropertyRowMapper<Boolean>(T.class) 类 (属于RowMapper的实现类)
用来更快捷的直接获取结果使用
回调方法由系统实现, 无序添加回调方法, 可直接传入泛型 ,获取结果
获取案例:
List<Person> ps = template.query("select*from person"
,new BeanPropertyRowMapper<Person>(Person.class));
update()函数
一般用来执行对于数据库的更新操作: 更新数据库的操作 包含了: insert update delete语句 参数1. 要执行的预编译的SQL语句 参数2. 是一个可变参数 ,是要执行的预编译的SQL语句中的参数的填充 返回值 : 返回的是 当前SQL语句 对于数据的影响 行数
操作案例:
int count = template.update("insert into person values(?,?)", "向阳","3"); System.out.println("这条SQL 影响了:"+count+"条数据");
execute()函数
用来执行所有的SQL语句
参数1. 要执行SQL语句 没有返回值
案例:
template.execute("create table user(uname varchar2(20),upass varchar2(20))");
提供了JdbcTemplate的组件,这个组件的作用
- 封装了connection、statement、执行SQL、释放连接资源等操作。只需要提供SQL语句和参数就可以完成对数据库的增、删、改、查。在进行查询方法时还要提供一个rowmapper方法,即记录映射,将记录转换为对象。
事物控制–声明式事物管理。
异常处理
jdbcTemplate之中对异常进行了统一捕获处理,封装成了统一的DateAccessException,便于底层数据库技术的切换。
JdbcDaoSupport的使用步骤
JdbcDaoSupport的底层实现
JdbcDaoSupport类中有一个私有属性JdbcTemplate的属性,该属性不能直接访问,但提供了get和set方法供子类进行访问。同时有一个setDateSource()的方法,该方法内部new出了一个JdbcTemplate对象,所以可以直接在z
在配置文件中, 添加dataSource对象
编写Class 继承自 JdbcDaoSupport
将编写的类, 添加到配置文件的bean节点中
将dataSource对象, 注入这个bean节点
配置文件案例:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<!-- 通过set方法 注入数据库的驱动地址 -->
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<!-- 注入数据库地址 -->
<property name="url" value="jdbc:oracle:thin:@localhost:1521"></property>
<!-- 注入数据库的帐号 -->
<property name="username" value="liweijie"></property>
<!-- 注入数据库的密码 -->
<property name="password" value="123456"></property>
</bean>
<bean id="userDBUtil" class="cn.xdl.dao.UserDBUtil">
<!--
根据传入的name
得到了一个Set方法:
setDataSource(dataSource)
-->
<property name="dataSource" ref="dataSource"></property>
</bean>
Java代码案例:
public class UserDBUtil extends JdbcDaoSupport{}
JDBC事务
1. 编程式事务
2. 声明式事务
编程式事务
使用步骤
1. 创建了事务的管理对象
DataSourceTransactionManager manager = new DataSourceTransactionManager(getDataSource());
2. 创建一个事务模版对象 , 并传入事务管理对象, 进行事务的托管
TransactionTemplate tt = new TransactionTemplate(manager);
3. 创建事务的回调方法
TransactionCallback<String> callback = new TransactionCallback<String>() {
//此方法自动调用
/**
*在这个方法中,默认情况下的所有jdbc操作 ,被视为一个整体, 代表一个事务
*/
@Override
public String doInTransaction(TransactionStatus status) {
};
4. 执行事务
tt.execute(callback);
声明式事务
1. 通过applicationContext.xml向容器中添加事务管理组件 , 并注入dataSource属性
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="basicDataSource"></property>
</bean>
2. applicationContext.xml中开启事务注解扫描
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>
3. 在代码中, 对于想要使用事务管理的方法/类, 进行注解:
transactionl注解中的属性:
propagation: 设置事务传播
isolation : 设置事务隔离级别
readOnly : 设置为只读,还是可读写
rollbackFor : 设置遇到哪些异常必须回滚
noRollbackFor : 设置遇到哪些异常不回滚
声明式事务与编程式事务的区别:
1. 声明式事务是采用的aop方式 ,可以在不更改原有代码的情况下, 动态的加入事务! 解除了代码与事务的耦合!
2. 声明式事务的应用范围最小为一个方法,不灵活!
而编程式事务的应用最小范围可以控制到一行代码!更灵活!**