Spring的统一异常体系和持久层技术

    DAO是用户访问数据的对象,虽然在很多情况下,我们将数据存放在数据库中,但是有时候也会将数据存放到文件或者LDAP中。DAO不仅屏蔽了数据存储的介质的不同,也屏蔽了具体实现技术的不同。

    Spring本质上希望以一种统一的方式整合底层的持久化技术:以统一的方式进行调用和事务管理,避免让具体的实现侵入到业务层代码中。由于每个持久化技术都有各自的异常体系,所以Spring提供了统一的异常体系,方便定义出和具体实现技术无关的DAO接口。

1 Spring的统一异常体系

    统一的异常体系是整合不同持久化技术的关键,Spring提供了一套和实现技术无关的,面向DAO层语义的异常体系,并通过异常转换器将不同持久化技术的异常转换为Spring的异常。
    要详细了解Spring为什么要提供统一的异常体系,可以参考这篇文章:http://my.oschina.net/u/218421/blog/38478
    在JDBC和很多的持久层技术中,检查型异常被过度使用,以至于在代码里充斥着大量的try/catch样板式的代码。但是,引发异常的问题往往是不可恢复的,强制捕捉检查型异常除了限制开发人员的自由度以外,并没有提供有价值的东西。因此,Spring的异常体系都是建立在运行期异常的基础上,开发者可以根据需要捕捉感兴趣的异常。
    Spring的异常体系都继承自DataAccessException,而DataAccessException又继承于NestedRuntimeException,NestedRuntimeException异常以嵌套的方式封装了源异常。因此,虽然不同持久化技术的特定异常被转换到Spring的DAO异常体系中,但是,原始的异常信息并不会丢失,只要用户愿意,就可以通过getCause()方法获取原始异常信息。

2统一数据访问模板

    JDBC数据访问的代码,包含以下操作:准备资源,启动事务,具体数据操作,提交事务,关闭资源。但是,对于我们真正有用的代码就是具体的数据操作,其他的行为都是固定的。因此Spring将这个相同的数据访问流程固化在模板类中,并将数据访问中固定和变化的部分分开,同时保证模板类是线程安全的,以便多个数据访问线程共享同一模板实例。固定的部分已经在模板类中准备好,而变化的部分通过回调接口开放出来,用于定义具体数据访问和结果返回操作。

2.1 JdbcTemplate

applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:jee="http://www.springframework.org/schema/jee" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd	
	http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://www.springframework.org/schema/jee 
	http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
	http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <context:component-scan base-package="com.bbc"/>
    <!-- 数据源 -->    
	<context:property-placeholder location="classpath:jdbc.properties"/>
	<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!-- jdbcTemplate  -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
        p:dataSource-ref="dataSource"
    />
</beans>
随便举一个DAO的例子:
public class LoginLogDao implements ILoginLogDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;

	public void insertLoginLog(LoginLog log) {
		// TODO Auto-generated method stub
		String sql="insert into t_login_log(user_id,ip,login_time) values(?,?,?)";
		jdbcTemplate.update(sql, new Object[]{log.getUser_id(),log.getIp(),log.getLogin_time()});
	}
}
从上面我们可以看到,如果我们直接使用模板类,一般都需要在DAO中定义一个模板对象,然后在xml中定义数据源和模板。Spring为每一个持久化技术都提供了支持类,支持类已经为我们完成这样的功能。我们只需要提供数据源,支持类会为我们创建好模板,我们只需要编写实际的数据访问逻辑。
	public class JdbcCustomerDAO extends JdbcDaoSupport implements CustomerDAO
	{
	   //no need to set datasource here
	   public void insert(Customer customer){
 
		String sql = "INSERT INTO CUSTOMER " +
			"(CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
 
		getJdbcTemplate().update(sql, new Object[] { customer.getCustId(),
				customer.getName(),customer.getAge()  
		});
 
	}

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
	<bean id="customerDAO" class="com.mkyong.customer.dao.impl.JdbcCustomerDAO">
		<property name="dataSource" ref="dataSource" />
	</bean>
 
</beans>
我们可以看一下JdbcDaoSupport的源码:
public abstract class JdbcDaoSupport extends DaoSupport {

	private JdbcTemplate jdbcTemplate;


	/**
	 * Set the JDBC DataSource to be used by this DAO.
	 */
	public final void setDataSource(DataSource dataSource) {
		if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
			this.jdbcTemplate = createJdbcTemplate(dataSource);
			initTemplateConfig();
		}
	}
      ... ... 略
}
    setDataSource()方法是final的,无法重写,类中也没有dataSource属性。因此,我们在通过支持类来编写自己的DAO时,只能通过xml的方式来生成相应的bean,无法通过注解的方式来设置dataSource,因为setDataSource是final的,而且是无法修改的第三方类库。
    可以注意到jdbc并没有对象关系映射ORM。下面的hibernate是有ORM的:

2.2 HibernateTemplate

可以参考我的这篇文章: Spring中使用hibernate
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值