Spring总结4—对持久层的支持(附:事务管理)

本文介绍Spring框架如何支持JDBC、Hibernate等持久层技术,包括数据源配置、DAO模式的应用、事务管理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Spring对持久层采用的策略
  1. 没有重新实现新的持久层,只是对现有持久层方案进行封装,更利于使用
  2. 采用DAO模式
  3. 提供了大量的模板类来简化编程(HibernateTemplate、JdbcTemplate等)
二、Spring对JDBC的支持

1、 配置数据源
方式一、开源数据库产品dbcp.BasicDataSource DBCP(database connection pool)

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/spring" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

或是新建文件jdbc.perperties,里面配置数据连接池

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <value>classpath:jdbc.properties</value>
    </property>
</bean>
<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>

其中jdbc.perperties中配置如下:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username = root
jdbc.password =root

方式二、采用Spring内置的数据源,Spring内置实现 DriverManagerDataSource

<bean id="dataSource"   class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName">
         <value>com.mysql.jdbc.Driver</value>
    </property>
    <property name="url">
         <value>jdbc:mysql://localhost:3306/hibdb</value>
    </property>
    <property name="username">
         <value>root</value>
    </property>
    <property name="password">
        <value>windows</value>
    </property>
</bean>

方式三、使用容器提供的数据源(如Tomcat,Weblogic,Sun Application Server)
用的少,这里不详细阐述,主要是使用JdbcTemplate或是HibernateTemplate模板类(封装了绝大多数数据库操作)


三、Spring 对DAO的支持

DAO模式优点

  • 减少开发代码量 提高工作效率
  • 降低系统资源消耗 提高系统性能
  • 业务逻辑层与持久层(数据层)的分离,使数据与操作更为清晰。
  • 数据访问独立到了一层,修改具体实现类,不影响系统的架构运行

DAO模式的四个组件

  • DAO接口
  • DAO接口实现类
  • pojo值对象
  • DAO实例的定位(工厂 或 spring注入)

1、使用Spring的Dao支持来写Dao层,继承JdbcDaoSupport类,JdbcDaoSupport类中有一个字段dataSource。也就是数据库连接,因此只需继承JdbcDaoSupport类,并给它注入dataSource,就隐式的获得了数据库连接,可以在bean.xml文件中注入connection(即:dataSource)

  <beans>
     <!-- spring 方式获得dataSource-->
      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
        <property name="url"><value>jdbc:mysql://localhost:3306/j2ee</value></property>
        <property name="username"><value>root</value></property>
        <property name="password"><value>123456</value></property>
       </bean>
        <bean id="xxx" class="包名.类名(dao的实现类)">
            <property name="dataSource">
                <ref local="dataSource"/>
            </property>
        </bean>
</beans>

2.在这个Dao 实现类中写一个内部类,使其实现:RowMapper接口,用来封装成具体的pojo对象,查询时用RowMapper实现类,代码如下:

private class PersonRowMapper implements RowMapper
{
    public Object mapRow(ResultSet resultSet, int rowNumber)throws SQLException {
        User user = new User();
        user.setId(resultSet.getLong("id"));
        user.setName(resultSet.getString("name"));
        user.setSex(resultSet.getString("sex"));
        user.setAge(resultSet.getInt("age"));
        user.setAddr(resultSet.getString("addr"));
        return user;
     }
}
四、Spring对Hibernate的支持

1. 配置数据源,参考JDBC处
2. 配置sessionFactory

<!--sessionFactory-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.cdd.*" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">
                org.hibernate.dialect.MySQLDialect
            </prop>
            <prop key="hibernate.show_sql">
                true
            </prop>
        </props>
    </property>
</bean>

3. 配置DAO
给DAO类注入SessionFactory

<bean id="UserDao" class="com.cdd.dao.impl.userDAOImpl">
    <property name="sessionFactory">
          <ref bean="sessionFactory" />
    </property>
</bean>
五、Spring声明式的事务管理

1、概念:
Spring支持声明式事务。Spring的事务管理是通过spring AOP来实现的。
Spring使用事务服务代理和事务管理器(如HibernateTransactionManager)来支持事务服务。
Spring对事务的边界多了一种嵌套事务(PROPAGATION_NESTED)。


PROPAGATION_NESTED:如果客户端启动了事务T1,那么Bean启动一个嵌套在T1中的子事务T2;如果客户端没有启动事务,那么Bean会启动一个新的事务,类似于REQUIRED_NEW


2、Annotation形式来声明事务管理
(1)加入annotation.xsd以及txManager bean
(2)加上注解<tx:annotation-driven

<tx:annotation-driven transaction-manager="txManager"/>

(3)在需要事务的方法上加:@Transactional
注:
a)事务加在DAO层还是Service层?事务应该添加在事务(一组操作数据库的动作集合)开始和结束的地方。在此案例中添加log日志,加到service层。代码在后面。
b)使用SessionFactory.getCurrentSession 不要使用OpenSession

//DAO具体实现层的方法,可以直接从sessionFactory中拿出session
public void save(Log log) {
    //整合Hibernate
    Session session = sessionFactory.getCurrentSession();
    session.save(log);
    System.out.println(" log save!");
}

@Transactional详解
1.什么时候rollback回滚,只要事务其中的一部分或多步执行失败,导致没有步骤被提交,则事务必须回滚到最初的系统状态。
2.运行期异常,非运行期异常不会触发rollback
3.必须uncheck (没有catch)
4.不管什么异常,只要你catch了,spring就会放弃管理
5.事务传播特性:propagation_required

代码示例如下:

//添加用户
    //事务边界,保存用户同时保存日志。
    @Transactional(propagation = Propagation.REQUIRED)

    //重要记住(默认):(propagation = Propagation.REQUIRED)在当前方法中,如果已有一个transaction,就加进去,如果没有transaction就会创建一个新的
    //nested(内嵌)(用的很少)在当前存在的事务上新建事务,回滚的时候回滚到起始点
    //never:不可以有事务
    //required_new:如果当前有transaction则挂起当前的,新建一个。当回滚的时候不会带动新的事务回滚
    //@Transaction properties
    //readOnly:true。Connection is readOnly.只读无法执行插入和更新语句
    public void add(User user){
        Log log = new Log();
        log.setMsg("hello hibernate");
        logDAO.save(log);
        userDAO.save(user);
    }

(4)异常处理:
在默认情况下,Spring的容器对于非受查异常(服务模块中抛出的非受查异常),会回滚事务。对于受查异常,会提交事务。

如果即使发生了某种受查异常,也要回滚事务,可以用 “- 异常类型“来声明。同样,对于非受查异常,如果不要求回滚事务,可以用”+异常类型”来声明。
4、xml(推荐,可以同时配置好多方法)
Spring的事务管理其实就是AOP,Spring的事务管理是通过spring AOP来实现的。

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<aop:config>
    <aop:pointcut expression="execution(public * com.cdd.service..*.*(..))"  id="bussinessService" />
    <aop:advisor pointcut-ref="bussinessService" advice-ref="txAdvice" />
</aop:config>

<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="getUser" read-only="true" />
        <tx:method name="add*" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值