一、Spring的DAO理念
DAO用于访问数据的对象,虽然我们在大多数情况下,将数据保存在数据库中,但这并不是唯一的选择,用户也可以将数据存储到文件中或LDAP中。DAO不但屏蔽了数据储存的最终介质的不同,也屏蔽了具体的实现技术的不同。
提供DAO层的抽象可以带来一些好处:首先,我们可以很容易的地构造模拟对象,方便单元测试的开展;其次在使用切面时,我们有更多的选择,既可以使用JDK动态代理,又可以使用CGLib动态代理。
Spring本质上希望以统一的方式整合底层的持久化技术:以统一的方式进行调用及事务管理,避免让具体的实现侵入业务层的代码中。由于每个持久化实现技术都有各自的异常体系,所以Spring提供了统一的异常体系,使不同异常体系的阻抗得以弥消,方便定义出和具体实现技术无关的DAO接口,以及整合到相同相同的事务管理体系中。
二、Spring的DAO异常体系
Spring在org.springframework.dao包中提供了一套完备优雅的DAO异常体系,这些异常都继承与DataAccessException,而DataaccessException本身又继承于NestedRuntimeException,NestedRuntimeException异常以嵌套的方式封装了源异常。虽然不同持久化技术的特定异常被转换到Spring的DAO异常体系中,原始的异常信息并不会丢失,只要用户愿意,就可以方便地通过getCause()方法获取原始的异常信息。
三、数据源
(一)、配置一个数据源
Spring在第三方依赖包中包含了两个数据源的实现类包:其一是Apache的DBCP;其二是C3O0。可以在Spring配置文件中利用这两者中的任何一个配置数据源。
(1)、DBCP
DBCP包位于<SPRING_HOME>/lib/Jakarta-commons/commons-dbcp.jar,DBCP是一个依赖Jakartacommons-pool对象池机制的数据库连接池。DBCP配置MySql数据源的片段:
<!-- DBCP数据源 -->
<bean id="dbcpSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="com.mysql.jdbc.Dviver"
p:url="jdbc:mysql://localhost:3306/sampledb"
p:username="root"
p:password="123456"/>
BasicDataSource提供了close()方法关闭数据源,所以必须设定destory-method=”close”属性,以便Spring容器关闭时,数据源能够正常关闭。
(2)、C3P0
C3P0是一个开放源代码的JDBC数据源实现项目,它在lib目录中与Hibernate一起发布,实现了JDBC3和JDBC2扩展规范说明的Connection和Statement池。C3P0类包位于<SPRING_HOME>/lib/c3p0/c3p0-0.9.0.4.jar。下面使用C3P0配置一个Oracle数据源:
<!-- C3P0数据源 -->
<bean id="c3p0Source" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"
p:driverClass="oracle.jdbc.driver.OracleDriver"
p:jdbcUrl="jdbc:oracle:thin:@localhost:1521:db"
p:use="admin"
p:password="123456"/>
ComboPooledDataSource和BasicDataSource一样提供了用于关闭数据源的close()方法,这样我们就可以保证Spring容器关闭时数据源能够成功释放。并且C3P0拥有比DBCP更丰富的配置属性,通过这样属性,可以对数据源进行各种有效的控制。
(二)、获取JNDI数据源
如果应有配置在高性能的应有服务器(如WebLogic或Websphere等)上,我们可能更希望使用应有服务器本身提供的数据源。应用服务器的数据源使用JNDI开放调用者使用,Spring为此专门提供引用JNDI资源的JndiPbjectFactoryBean类。下面是一个简单的配置:
<!-- JNDI数据源 -->
<bean id="jndiSource" class="org.springframework.jndi.JndiObjectFactoryBean"
p:jndiName="java:comp/env/jdbc/bbt"/>
<!-- 也可以使用jee命名空间简化配置JNDI数据源 -->
<jee:jndi-lookup id="jeeJndiSource" jndi-name="java:comp/env/jdbc/bbt"/>
通过jndiName指定引用的JNDI数据源名称。
Spring为获取J2EE资源提供了一个jee命名空间,通过jee命名空间,可以有效地简化J2EE资源的引用。
(三)、Spring的数据源实现类
Spring本身也提供了一个简单的数据源实现类DriverManagerDataSource,它位于org.springframework.jdbc.datasource包中。这个类实现类javax.sql.DataSource接口,但它并没有提供池化连接的机制,每次调用getConnection()获取新连接时,只是简单地创建一个新的连接。因此,这个数据源比较适合在单元测试或简单的独立应有中使用,因为它不需要额外的依赖类。