通过Spring和JDBC征服数据库
1.对象的持久化(Persistence)
对象持久化就是让对象的生存期超越使用对象的程序的运行期。将对象存储在可持久保存的存储介质上,在实际应用中,运用相应的对象持久化框架,将业务数据以对象的方式保存在数据库中,如比较早的Hibernate。在一定周期内保持不变就是持久化,持久化是针对时间来说的。数据库中的数据就是持久化了的数据,只要你不去删除或修改。比如在IE浏览器中一次Session会话中Session对象变量也是不变的,是Session容器中持久化。对象持久化的方式有很多种,根据周期不同有,page,Session,Application。
持久化是一种对象服务,就是把内存中的对象保存到外存中,让以后能够取回。需要实现至少3个接口:
+ void Save(object o)
把一个对象保存到外存中
+ Object Load(object oid)
通过对象标识从外存中取回对象
+ boolExists(object oid)
检查外存中是否存在某个对象
2.对象的序列化(Serialization)
JVM 向我们屏蔽了内存操作相关的信息,我们并不知道数据是以什么样的形式来存储和组织的,当对象需要进行传输时,java提供了序列化的方法方便我们对数据进行传输操作。对象序列化后的数据格式可以是二进制,可以是XML,也可以是JSON等任何格式,反序列化则是相反的操作。序列化是为了解决对象的传输问题,当传输一个对象时,则需要实现2个接口:
+ void Serialize(Stream stream,object o)
把对象序列化到流中
+ object Deserialize(Stream stream)
把流反序列化成对象
这种传输可以是线程之间、进程之间、内存外存之间、主机之间的,凡是可以持久化的对象都可以序列化。
10.1 Spring的数据访问哲学
为了避免持久化的逻辑分散到应用的各个组件中,最好将数据访问功能放到一个或多个专注于于此项任务的组件中。这样的组件通常称为数据访问对象(data access object, DAO)或Repository.
为了避免应用与特定的数据访问策略耦合在一起,编写良好的Repository应该以接口的方式暴露功能。服务对象本身并不会处理数据访问,而是将数据访问委托给Repository.
这样做的好处:
+ 使得服务对象容易测试
+ 数据访问层是以持久化技术无关的方式来访问的
10.1.1 了解Spring的数据访问异常体系
总结来讲,Spring的数据访问异常体系有两个优势
1. 相对于SQLException来讲,Spring JDBC提供的异常体系丰富得多
2. Spring 的异常体系没有和特定的持久化方法相关联
10.1.2 数据访问模块化
Spring将数据访问过程中固定的和可变的部分明确划分为两个不同的类:模板(template)和回调(callback)。模板管理过程中固定的部分,而回调处理自定义的数据访问代码。
Spring的模板类处理数据访问的固定部分:事务控制、管理资源以及异常处理;
回调的实现中处理:语句、绑定参数以及整理结果集。
针对不同的持久化平台,Spring提供了多个可选的模板。如果直接使用JDBC,可以选择JdbcTemplate;r如果使用对象关系映射框架,可以选择HibernateTemplate或JpaTemplate.
10.2 配置数据源
无论选择Spring的哪种数据访问方式,你都需要配置一个数据源的引用。Spring提供了在Spring应用上下文配置数据源bean的多种方式,包括:
+ 通过JDBC驱动程序定义的数据源
+ 通过JNDI查找的数据源
+ 链接池的数据源
10.2.1 使用JNDI数据源
Spring应用程序经常部署在JavaEE应用服务器中,如WebSphere,JBoss甚至Tomcat这样的Web容器中。这些服务器允许你通过配置JNDI获取数据源。这种配置的好处是:数据源完全可以在应用程序之外进行管理,这样应用程序只需在访问数据库时查找数据源就可以了。另外,在应用服务器中管理的数据源通常以池的方式组织,从而具备更好的性能,并且支持热切换。
利用Spring,我们可以像使用Spring bean那样配置JNDI中数据源的引用并将其装配到需要的类中。
<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/SpitterDS" resource-ref="true" />
@Bean
public JndiObjectFactoryBean dataSource(){
JndiObjectFactoryBean jndiObjectFB = new JndiObjectFactoryBean();
jndiObjectFB.setJndiName("/jdbc/SpitterDS");
jndiObjectFB.setResourceRef(true);
jndiObjectFB.setProxyInterface(javax.sql.DataSource.class);
return jndiObjectFB;
}
10.2.2 使用数据源连接池
- Apache Commons DBCP
- c3p0
- BoneCP
如下,配置DBCP BasicDataSource的方式:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="org.h2.Driver"
p:url="jdbc:h2:tep://localhost/~/spitter"
p:username="sa"
p:password=""
p:initialSize="5"
p:maxActive="10" />
@Bean
public BasicDataSource dataSource(){
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("org.h2.Driver");
ds.setUrl("jdbc:h2:tep://localhost/~/spitter");
ds.setUsername("sa");
ds.setPassword("");
ds.setInitialSize(5);
ds.setMaxActive(10);
return ds;
}
简单解释一下:
driverClassName指定了JDBC驱动类的全限定类名;url用于设置数据库的JDBC URL;最后,username和password用于在连接数据库时进行认证
10.2.3 基于JDBC驱动的数据源
在Spring中,通过JDBC驱动定义数据源是最简单的配置方式。Spring提供3个数据源类(均位于org.springframework.jdbc.datasource)供选择:
+ DriverManagerDataSource
+ SimpleDriverDataSource
+ SingleConnectionDataSource
10.2.4 使用嵌入式的数据源
嵌入式数据库作为应用的一部分运行,而不是应用连接的独立数据库服务器。因此在生产环境不会有太大用处,但是对于本地开发测试来讲,嵌入式数据库时很好的可选方案。
<jdbc:embedded-database id="dataSource" type="H2">
<jdbc:script location="com/habuma/spitter/db/jdbc/schema.sql" />
<jdbc:script location="com/habuma/spitter/db/jdbc/test-data.sql" />
</jdbc:embedded-database>
@Bean
public DataSource dataSource(){
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}