Spring 整合数据访问技术

Spring 作为一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,主要负责技术整合,那么Spring是如何整合数据访问的呢?下面就让我们一起来探讨,有不对的地方敬请指教。

一、Spring 提供了编写 DAO 的支持类
1、DaoSupport 类: JdbcDaoSupport、 HibernateDaoSupport,自己写的 DAO 按使用的访问技术,有选择的继承它们。
2、Template 类: JdbcTemplate、 HibernateTemplate,封装了通用操作,如:增删改查。特殊操作,如:分页查询。
3、继承 DaoSupport 类后,就可通过 getJdbcTemplate()、 getHibernateTemplate()方法获得对应的 Template 类对象,即可进行通用操作:
(1)update():实现更新。 

(2)query():实现查询多行记录。

(3)queryForObject():实现查询单行记录。 

(4)queryForInt():实现查询单个 int 值。
4、 将一条记录转换成一个实体对象,需要实现 Spring 提供的 RowMapper 接口(将实体与记录间的转换写在它的实现类中),因为 Spring 提供的 Template 对象中的查询方法 query()有 RowMapper 类型的参数。

二、Spring 提供了声明式事务管理方法
Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。 Spring事务管理器的接口org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。基于 AOP 配置实现,不需要写 Java 代码,加注解标签即可。

Spring 中常用的事务类型:
1、REQUIRED: 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是默认值。
2、SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行。
3、MANDATORY: 支持当前事务,如果当前没有事务,就抛出异常。
4、REQUIRES_NEW: 新建事务,如果当前存在事务,把当前事务挂起。
5、NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。
7、NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与REQUIRED 类似的操作。拥有多个可以回滚的保存点,内部回滚不会对外部事务产生影响。只对 DataSourceTransactionManager 有效。

三、Spring对JDBC的支持实例

1、新建一个工程,引入 Spring 开发包( IoC 和 AOP 开发包)和配置文件

2、引入JDBC技术相关的开发包(驱动包)

3、根据要操作的表,编写对应的实体类。

4、编写DAO接口TestDAO和实现类 JdbcTestDAO(实现类继承 JdbcDaoSupport,并使用其提供的 getJdbcTemplate 对象实现增删改查操作)
(1) TestDAO 接口
public test findById(int id);

public List findAll();
(2) JdbcTestDAO 实现类
public class JdbcTestDAO extends JdbcDaoSupport implements TestDAO{
public Test findById(int id) { 
String sql="select * from test where ID=?";
Object[] params={id};
RowMapper mapper=new TestRowMapper();
Test test=(Test)getJdbcTemplate().queryForObject(sql, params,mapper);
return test; }

public List findAll() {
String sql="select * from test";
/** 将一条记录转换成一个 Test 对象,需要实现 Spring 提供的 RowMapper 接口  */
RowMapper mapper=new TestRowMapper();
List list=getJdbcTemplate().query(sql,mapper); 
return list; }
}
(3) 在 org.audTest.entity 包中创建 TestRowMapper 类
public class TestRowMapper implements RowMapper{//实现 RowMapper 接口
/** rs:结果集。 index:当前记录的索引 。 Object:返回实体对象。 */
public Object mapRow(ResultSet rs, int index) throws SQLException {
Test test = new Test(); 
test.setId(rs.getInt("ID"));
Test.setName(rs.getString("NAME"));
return test;
}
 }

5、将 DAO 组件交给 Spring 容器,在 applicationContext.xml 中进行相关配置
(1)定义 DAO 组件的元素




(2) 需要 DAO 的 Bean 注入一个 dataSource 对象。 dataSource 对象采用一个连接池构建(此处使用 dbcp 连接池),先引入 dbcp 连接池开发包( commons-pool.jar、 commons-dbcp-1.2.2.jar、commons-collections-3.1.jar),再定义 dataSource 对象的元素。

destroy-method="close">
 
 
 
 
 
 
 
 

6、创建 TestJdbcTestDAO 类,用于测试 xml 配置,可正常执行
@Test
public void testFindAll() {

//测试基于 xml 配置方法
String conf="/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
TestDAO TestDAO=(TestDAO)ac.getBean("TestDAO");
List list=TestDAO.findAll();

for(Test c:list){ 

System.out.println(c.getId()+" "+c.getName()); 

}
System.out.println("findById: "+TestDAO.findById(1).getName()); 

}

7、使用注解配置,保留 5 中的连接资源 MyDataSource,而 Bean 组件 TestDAO 删除,并添加开启组件扫描的配置

8、在 JdbcTestDAO 中添加注解
@Repository //id 值默认为类名首字母小写
@Scope("prototype") //设置非单例模式
public class JdbcTestDAO extends JdbcDaoSupport implements TestDAO{
@Resource //将容器中的 myDataSource 按类型匹配注入
/** 虽然继承了 JdbcDaoSupport,但我们无法在别人的代码中添加注解,所以我们
添加一个 set 方法, 注意名字别用 setDataSource!因为 JdbcDaoSupport 有同名的 set 方法,
且是 final 修饰的,所以需要稍微改变一下。 */
public void setMyDataSource(DataSource ds){
super.setDataSource(ds);//将注入的 dataSource 给 DaoSupport 注入 }

9、在 TestJdbcTestDAO 类添加方法,用于测试注解配置,可正常执行
@Test
public void testFindAllByAnnotation() {

//测试基于注解配置方法
String conf="/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
TestDAO TestDAO=(TestDAO)ac.getBean("jdbcTestDAO");
List list=TestDAO.findAll(); 
for(Test c:list){ System.out.println(c.getId()+" "+c.getName()); }
System.out.println("findById: "+TestDAO.findById(1).getName()); }

10、优化,当大量 Bean 组件需要采取注解配置时,每个 Bean 都要写 set 方法注入 dataSource连接资源,所以比较麻烦,可采取继承方式:
(1) 新建 JdbcBaseDAO 类,并继承 JdbcDaoSupport,把 set 方法写入
public class JdbcBaseDAO extends JdbcDaoSupport {
@Resource //将容器中的 myDataSource 按类型匹配注入
public void setMyDataSource(DataSource ds){//注意名字,详见8
super.setDataSource(ds); } }
(2) 删除8中JdbcTestDAOset的 set 方法及其前面的注解,并继承 JdbcBaseDAO
public class JdbcTestDAO extends JdbcBaseDAO implements TestDAO{ …… }

四、连接池优点
1、增强数据访问的稳定性。
2、连接池可以将连接数控制在安全的范围内。
3、连接池中的连接对象始终与数据库保持联通状态,它的 close 方法被重写,不是真正的关闭,而是把连接又放回池中,避免了重复的新建连接和释放连接过程。

五、Spring对Hibernate的支持实例

1、新建一个工程,引入 Spring 开发包( IoC 和 AOP 开发包)和配置文件

2、引入 Hibernate 相关的开发包( Hibernate 开发包+驱动)

3、编写实体类和 hbm.xml 映射描述文件

4、编写 DAO 接口和 HibernateTestDAO 实现类(实现类继承 HibernateDaoSupport,并使用其提供的 HibernateTemplate 对象实现增删改查操作)

5、将 DAO 组件交给 Spring 容器管理,在 applicationContext.xml 中进行相关配置
class="org.audTest.dao.impl.HibernateTestDAO">

6、在 applicationContext.xml 中配置 sessionFactory 资源(相当于 Hibernate 的主配置)
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">






org.hibernate.dialect.OracleDialect
true
true




org/audTest/entity/Test.hbm.xml

7、在 applicationContext.xml 中配置 dataSource 数据库连接资源dataSource 对象采用一个连接池构建(此处使用 dbcp 连接池),先引入 dbcp 连接池开发包

destroy-method="close">
 
 property name="url" value="jdbc:mysql://localhost:3306/web?useUnicode=true&characterEncoding=UTF-8">
 
 
 
 
 
 

8、创建 TestHibernateTestDAO 类,用于测试 xml 配置


9、使用注解配置,新建 applicationContext-annotation.xml 配置文件,并添加开启组件
扫描的配置


10、在 HibernateTestDAO 中添加注解
@Repository("HibernateTestDAO")
@Scope("prototype")
public class HibernateTestDAO extends HibernateDaoSupport implements TestDAO {
@Resource //setSessionFactory 名字用不了是 final 
public void setMySessionFactory(SessionFactory sf){
super.setSessionFactory(sf);//将注入的 sessionFactory 给 HibernateDaoSupport 传入
}

11、在 TestHibernateTestDAO 类添加方法,用于测试注解配置,可正常执行

12、在 TestHibernateTestDAO 类添加方法,用于测试查询

你可能感兴趣的:(Spring)