1.spring 对数据库访问的支持
当我们开发持久层的时候,我们面临着多种选择,比如使用JDBC、Hibernate、java持久化API或其它持久化框架。幸好的是spring能够支持所有这些持久化机制。
DAO(data access boject)数据访问对象,这个名字就很形象描述了DAO在应用程序中所扮演的角色。DAO提供了数据的读取、写入到数据库中的一种方式。它们应该以接口的方式发布功能,而应用程序的其它部分就可以通过接口来进行访问了。
注:服务对象本身并不会处理数据访问,而是将数据访问委托给DAO。DAO接口确保其与服务对象的松耦合。
2.配置数据源
spring提供了在spring上下文中配置数据源Bean的多种方式,包括:
a.通过JDBC驱动程序定义的数据源;
b.通过JNDI查找的数据源;
c.连接池的数据源;
接下我们就专门来讲讲从使用连接池获取连接的数据源!(即c点)
上下文配置Bean的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!
--配置数据源 -->
<bean id=
"dataSource"
class=
"org.apache.commons.dbcp.BasicDataSource"
>
<property
name
=
"driverClassName"
value=
"oracle.jdbc.driver.OracleDriver"
/>
<property
name
=
"url"
value=
"jdbc:oracle:thin:@localhost:1521:orcl"
/>
<property
name
=
"username"
value=
"wwo"
/>
<property
name
=
"password"
value=
"wwo"
/>
<!
-- 连接池启动时的初始值 -->
<property
name
=
"initialSize"
value=
"3"
/>
<!
-- 连接池的最大值 -->
<property
name
=
"maxActive"
value=
"300"
/>
<!
-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property
name
=
"maxIdle"
value=
"2"
/>
<!
-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property
name
=
"minIdle"
value=
"1"
/>
<!
-- end -->
</bean>
|
注:JDBC驱动数据源并没有池的概念,因此没有存在池属性的配置!
好了,到这一步,我们已经完成了通过数据源建立了与数据库的连接,接下来就是实际访问数据库了。
3.在Spring中集成Hibernate
Hibernate一些特性:
a.延迟加载(Lazy loading):例如一个Bean对象由其属性及另一个Bean对象组成,如果我们只关注的只是这个Bean对象的属性,那么我们可以借助于延迟加载,只抓取需要的数据;
b.预先抓取(Eager fetching):这与延迟加载是相对的,一个Bean所关联的其它Bean都会被查询出来,这就节省了多次查询的成本;
c.级联(Cascading):有时候删除一个Bean对象后,也希望其同时能数据库中删除掉与其关联的其它Bean。
Spring对Hibernate ORM框架的支持提供了与这些框架集成点以及一些附加的服务,如下所示:
a.Spring声明式事务的集成支持;
b.透明的异常处理;
c.线程安全的、轻量级的模板类;
d.DAO支持类;
e.资源管理。
4.声明会话工厂(Session Factory)
使用Hibernate的主要接口是org.hibernate.Session。Session提供了基本的数据访问功能,如保存、更新、删除以及从数据库加载对象的功能。
能过借助于Hibernate的SessionFactory来获取Session对象,SessionFactory主要负责Hibernate Session的打开、关闭以及管理。
配置在xml上下文的Bean如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<bean id=
"sessionFactory"
class=
"org.springframework.orm.hibernate4.LocalSessionFactoryBean"
>
<property
name
=
"dataSource"
ref=
"dataSource"
/>
<property
name
=
"packagesToScan"
>
<!
--扫描一下实体目录 -->
<list>
<value>com.blog.entity</value>
</list>
</property>
<property
name
=
"hibernateProperties"
>
<props>
<prop
key
=
"hibernate.dialect"
>org.hibernate.dialect.Oracle10gDialect</prop>
<prop
key
=
"hibernate.show_sql"
>
true
</prop>
<prop
key
=
"hibernate.format_sql"
>
true
</prop>
<prop
key
=
"current_session_context_class"
>thread</prop>
</props>
</property>
</bean>
|
5.创建自己的基础DAO类
Spring可以通过Spring的Hibernate模板来保证每个事务都使用同一个会话。既然Hibernate能够对其自己进行管理,那就不必要使用模板类了。接下我们直接将Hibernate Session装配到自己的DAO类中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
/**
* 基础dao
*
* @author ckz
*
* @param <T>
*/
public
abstract class BaseDAO<T> {
/**
* 注入sessionFactory
*/
@Autowired
private SessionFactory sessionFactory;
/**
* 获得session
*
* @
return
*/
protected Session getCurrentSession() {
return
sessionFactory.getCurrentSession();
}
/**
* 保存
*
* @param entity
* @throws Exception
*/
public
void
add
(T entity) throws Exception {
getCurrentSession().save(entity);
}
/**
* 调用存储过程
*
* @param proName
* @
return
*/
public
CallableStatement citePro(final String proName){
Session session = getCurrentSession();
CallableStatement proc=session.doReturningWork(
new ReturningWork<CallableStatement>() {
@Override
public
CallableStatement
execute
(
Connection
connection
) throws SQLException{
CallableStatement resultSet =
connection
.prepareCall(proName);
return
resultSet;
}
}
);
return
proc;
}
/**
* 更新
*
* @param entity
* @throws Exception
*/
public
void
update
(T entity) throws Exception {
getCurrentSession().
update
(entity);
}
/**
* 保存或更新
*
* @param entity
* @throws Exception
*/
public
void saveOrUpdate(T entity) throws Exception {
getCurrentSession().saveOrUpdate(entity);
}
/**
* 删除
*
* @param entity
* @throws Exception
*/
public
void
delete
(T entity) throws Exception {
getCurrentSession().
delete
(entity);
}
}
|
</dd>