学习Spring 的DAO理念:
通过与持久化技术无关的方式来访问数据访问层。也就是说,DAO接口不需要暴露它采用什么技术去访问数据。取而代之,只有相关的数据访问方法被暴露在接口中,这将有助于灵活的应用设计。
如果数据访问层的实现细节渗透在应用的其他部分中,整个应用都将和数据访问层紧密耦合在一起,导致一种僵硬的应用设计。
Spring 帮你把数据访问层从应用的其它部分隔离开来的一种方法是:提供一套贯穿整个DAO框架的一致的分级异常体系。
异常 | 何时抛出 |
CleanupFailureDataAccessException | 一项操作成功地执行,但在释放数据库资源时发生异常(例如,关闭一个Connection) |
DataAccessResourceFailureException | 数据访问资源彻底失败,例如不能连接数据库 |
DataIntegrityViolationException | Insert 或 Update数据时违反了完整性,例如违反了唯一性限制 |
DataRetrievalFailureException | 某些数据不能被检测到,例如不能通过关键字找到一条记录 |
DeadlockLoserDataAccessException | 当前的操作因为死锁而失败 |
IncorrectUpdateSemanticsDataAccessException | Update时发生某些没有预料到的情况,例如更改超过预期的记录数。当这个异常被抛出时,执行着的事务不会被回滚 |
InvalidDataAccessApiUsageException | 一个数据访问的Java API没有正确使用,例如必须在执行前编译好的查询编译失败了 |
InvalidDataAccessResourceUsageException | 错误使用数据访问资源,例如用错误的SQL语法访问关系型数据库 |
OptimisticLockingFailureException | 乐观锁的失败。这将由ORM工具或用户的DAO实现抛出 |
TypeMismatchDataAccessException | Java类型和数据类型不匹配,例如试图把String类型插入到数据库的数值型字段中 |
UncategorizedDataAccessException | 有错误发生,但无法归类到某一更为具体的异常中 |
从JNDI得到DataSource
通过JNDI获得DataSource 。在Spring,我们把它看作和应用中的任何其他服务对象一样----看作Spring Bean。在这里,我们使用JndiObjectFactoryBean。
用DataSource的JNDI名字来配置它:
- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
- <property name="jndiName">
- <value>java:comp/env/jdbc/myDatasourcevalue>
- property>
- bean>
创建一个DataSource连接池
假如Spring容器运行在一个不提供DataSource的环境中,但我们还希望拥有连接池的好处,我们仍然可以做到。我们所需要的就是一个实现DataSource的连接池Bean。说明这个问题的一个很好的例子就是Jakarta Commons DBCP项目中的BasicDataSource类。它的所有属性都是通过setter方法暴露在外面,我们可以像配置其他Spring Bean那样配置它:
- <bean id ="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driver">
- <value>${db.driver}value>
- property>
- <property name="url">
- <value>${db.url}value>
- property>
- <property name=“username”>
- <value>${db.username}value>
- property>
- <property name="password">
- <value>${db.password}value>
- property>
- bean>
在测试时使用DataSource
使代码易于测试是Spring理念的中心,如果不能对数据访问代码进行单元测试,那将是耻辱。幸运的是,Sring 专门为此提供了一种非常轻量级的DataSource实现:DriverManagerDataSource。这个类很容易配置,也很容易在一个或者一系列单元测试中使用。
- DriverManagerDataSource dataSource = new DriverManagerDataSource();
- dataSource.setDriverClassName(driver);
- dataSource.setUrl(url);
- dataSource.setUsername(username);
- dataSource.setPassword(password);
当测试你的数据访问代码时,你有一个DataSource可以用了。