美文网首页
Spring中持久层事务配置

Spring中持久层事务配置

作者: Super超人 | 来源:发表于2018-12-11 14:45 被阅读30次

    前面写了这么久的持久层框架存储数据,今天来记录下 Spring 框架对于事物管理的配置,顺带记录下 Spring 框架与 Hibernate 和 Mybatis 这些持久层框架的整合。

    Spring 为事务管理提供了一致的编程模版,在高层次建立了统一的事务抽象,不管用户选择 Spring JDBC、Hibernate、JPA还是选择 MyBatis,Spring 都可以让用户用统一的编程模型进行事务管理。这种统一处理的方式带来的好处是不可估量的,用户完全可以抛开事务管理的问题编写程序,并在 Spring 中通过配置完成事务的管理工作。

    一、Spring事务管理实现类

    Spring 将事务管理委托给底层具体的持久化框架来完成。因此,Spring 为不同的持久化框架提供了不同的 PlantformTransactionManager 接口的实现类。

    事务类 说明
    org.springframework.jdbc.datasource.DataSourceTransactionManager 使用Spring JDBC 或者 MyBatis 等基于 DataSource 数据源的持久化技术时,使用该事务管理器
    org.springframework.orm.hibernateX.HibernateTemplate 使用Hibernate X.0版本进行持久化时,使用该事务管理器
    org.springframework.orm.jpa.JpaTransactionManager 使用JPA进行持久化时候,使用该事务管理器
    二、Spring JDBC 事务管理配置

    Dao 层实现

    public class ContactDaoImpl implements ContactDao {
    
        private JdbcTemplate jdbcTemplate;
    
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    
        @Override
        public Contact findObjectById(int id) throws Exception {
            String sql = "select * from contact where id=?";
            return jdbcTemplate.queryForObject(sql, new RowMapper<Contact>() {
                @Override
                public Contact mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Contact contact = new Contact();
                    contact.setId(rs.getInt("id"));
                    contact.setName(rs.getString("name"));
                    contact.setBirthday(rs.getDate("birthday"));
                    return contact;
                }
            }, id);
        }
    
        @Override
        public List<Contact> findAll() throws Exception {
            String sql = "select * from contact";
            return jdbcTemplate.query(sql, new RowMapper<Contact>() {
                @Override
                public Contact mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Contact contact = new Contact();
                    contact.setId(rs.getInt("id"));
                    contact.setName(rs.getString("name"));
                    contact.setBirthday(rs.getDate("birthday"));
                    return contact;
                }
            });
        }
    
        @Override
        public int insertObject(Contact contact) throws Exception {
            String sql = "insert into contact (name, birthday) values (?, ?)";
            return jdbcTemplate.update(sql, contact.getName(), contact.getBirthday());
        }
    
        @Override
        public int updateObject(Contact contact) throws Exception {
            String sql = "update contact set name = ?, birthday = ? where id = ?";
            return jdbcTemplate.update(sql, contact.getName(), contact.getBirthday(), contact.getId());
        }
    
        @Override
        public int deleteObjectById(int id) throws Exception {
            String sql = "delete from contact where id=?";
            return jdbcTemplate.update(sql, id);
        }
    }
    

    Service 层实现

    public class ContactServiceImpl implements ContactService {
    
        private ContactDao contactDao;
    
        public void setContactDao(ContactDao contactDao) {
            this.contactDao = contactDao;
        }
    
        @Override
        public Contact findObjectById(int id) throws Exception {
            return contactDao.findObjectById(id);
        }
    
        @Override
        public List<Contact> findAll() throws Exception {
            return contactDao.findAll();
        }
    
        @Override
        public int insertObject(Contact contact) throws Exception {
            int count = contactDao.insertObject(contact);
            return count;
        }
    
        @Override
        public int updateObject(Contact contact) throws Exception {
            return contactDao.updateObject(contact);
        }
    
        @Override
        public int deleteObjectById(int id) throws Exception {
            return contactDao.deleteObjectById(id);
        }
    }
    
    <?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:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/tx
                http://www.springframework.org/schema/tx/spring-tx.xsd
                http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
    
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${driver}"></property>
            <property name="jdbcUrl" value="${url}"></property>
            <property name="user" value="${username}"></property>
            <property name="password" value="${password}"></property>
            <property name="initialPoolSize" value="${initialPoolSize}"></property>
            <property name="minPoolSize" value="${minPoolSize}"></property>
            <property name="maxPoolSize" value="${maxPoolSize}"></property>
            <property name="maxIdleTime" value="${maxIdleTime}"></property>
        </bean>
    
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <constructor-arg ref="dataSource"></constructor-arg>
        </bean>
    
        <bean id="contactDao" class="com.ogemray.jdbc.dao.impl.ContactDaoImpl">
            <property name="jdbcTemplate" ref="jdbcTemplate"></property>
        </bean>
    
        <bean id="contactService" class="com.ogemray.jdbc.service.impl.ContactServiceImpl">
            <property name="contactDao" ref="contactDao"></property>
        </bean>
    
        <!--开始事务配置-->
        
        <!--事务管理类-->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
        <!--事务增强配置-->
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="find*" read-only="true"/>
                <tx:method name="*" read-only="false"/>
            </tx:attributes>
        </tx:advice>
    
        <!--AOP配置-->
        <aop:config>
            <aop:pointcut id="pt" expression="execution(* com.ogemray.jdbc.service.*.*(..))" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
        </aop:config>
    </beans>
    

    注意: 只要将 jdbcTemplate 注入到 Dao 的实现层就能实现接下来的JDBC操作,同时需要注意的是,事务管理配置在 Service 层,所以不管是 Dao 层还是 Service 层,都要将异常往上抛,这样才能达到事务管理效果,如果在 Service 层或者下层进行错误抛出,则到不到事务管理效果。

    三、Spring 与 MyBatis整合 事务管理配置

    Dao 层接口

    public interface ContactMapper {
    
        public List<Contact> findAll() throws Exception;
    
        public Contact findObjectById(int id) throws Exception;
    
        public int insertObject(Contact contact) throws Exception;
    
        public int updateObject(@Param("contact") Contact contact) throws Exception;
    
        public int deleteObjectById(int id) throws Exception;
    }
    

    Mapper XML文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.ogemray.mybatis.mapper.ContactMapper">
    
        <resultMap id="contactMap" type="com.ogemray.mybatis.entity.Contact">
            <id property="id" column="id"></id>
            <result property="name" column="name"></result>
            <result property="birthday" column="birthday"></result>
        </resultMap>
    
        <select id="findAll" resultMap="contactMap">
            select * from contact
        </select>
    
        <select id="findObjectById" resultMap="contactMap">
            select  * from  contact where id = #{id}
        </select>
    
        <insert id="insertObject"
                parameterType="com.ogemray.mybatis.entity.Contact"
                useGeneratedKeys="true"
                keyProperty="id">
            insert into contact (name, birthday) values (#{name}, #{birthday})
        </insert>
    
        <update id="updateObject">
            update contact
            <set>
                <trim suffixOverrides=",">
                    <if test="contact.name != null">name = #{contact.name}, </if>
                    <if test="contact.birthday != null">birthday = #{contact.birthday}</if>
                </trim>
            </set>
            where id = #{contact.id}
        </update>
    
        <delete id="deleteObjectById">
            delete from contact where id = #{id}
        </delete>
    </mapper>
    

    Service 层实现

    public class ContactServiceImpl implements ContactService {
    
        private ContactMapper contactMapper;
    
        public void setContactMapper(ContactMapper contactMapper) {
            this.contactMapper = contactMapper;
        }
    
        @Override
        public List<Contact> findAll() throws Exception {
            return contactMapper.findAll();
        }
    
        @Override
        public Contact findObjectById(int id) throws Exception {
            return contactMapper.findObjectById(id);
        }
    
        @Override
        public int insertObject(Contact contact) throws Exception {
            int count = contactMapper.insertObject(contact);
            return count;
        }
    
        @Override
        public int updateObject(Contact contact) throws Exception {
            return contactMapper.updateObject(contact);
        }
    
        @Override
        public int deleteObjectById(int id) throws Exception {
            return contactMapper.deleteObjectById(id);
        }
    }
    
    <?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:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${driver}"></property>
            <property name="jdbcUrl" value="${url}"></property>
            <property name="user" value="${username}"></property>
            <property name="password" value="${password}"></property>
            <property name="initialPoolSize" value="${initialPoolSize}"></property>
            <property name="minPoolSize" value="${minPoolSize}"></property>
            <property name="maxPoolSize" value="${maxPoolSize}"></property>
            <property name="maxIdleTime" value="${maxIdleTime}"></property>
        </bean>
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="mapperLocations" value="classpath*:com/ogemray/mybatis/mapper/*.xml"></property>
            <property name="configLocation" value="classpath:mybaitis-config.xml"></property>
        </bean>
    
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.ogemray.mybatis.mapper"></property>
        </bean>
    
        <bean id="contactService" class="com.ogemray.mybatis.service.ContactServiceImpl">
            <property name="contactMapper" ref="contactMapper"></property>
        </bean>
    
        <!--事务配置注入-->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
        <!--事务增强配置-->
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="find*" read-only="true"/>
                <tx:method name="get*" read-only="true"/>
                <tx:method name="*" read-only="false" no-rollback-for="java.lang.ArithmeticException"/>
            </tx:attributes>
        </tx:advice>
    
        <!--配置事务及切点-->
        <aop:config>
            <aop:pointcut id="txPointcut" expression="execution(* com.ogemray.mybatis.service.*.*(..))" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
        </aop:config>
    
    </beans>
    
    四、Spring 与 Hibernate整合 事务管理配置

    Dao 层实现类

    public class ContactDaoImpl implements ContactDao {
    
        private SessionFactory sessionFactory;
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    
        private Session getSession() {
            return sessionFactory.getCurrentSession();
        }
    
        @Override
        public List<Contact> findAll() throws Exception {
            String sql = "from " + Contact.class.getSimpleName();
            List<Contact> list = getSession().createQuery(sql).getResultList();
            return list;
        }
    
        @Override
        public Contact findById(int id) throws Exception {
            return getSession().get(Contact.class, id);
        }
    
        @Override
        public Serializable insertObject(Contact contact) throws Exception {
            return getSession().save(contact);
        }
    
        @Override
        public void updateObject(Contact contact) throws Exception {
            getSession().update(contact);
        }
    
        @Override
        public void deleteObject(Contact contact) throws Exception {
            getSession().delete(contact);
        }
    }
    

    Service 层实现

    public class ContactServiceImpl implements ContactService {
        private ContactDao contactDao;
    
        public void setContactDao(ContactDao contactDao) {
            this.contactDao = contactDao;
        }
    
        public List<Contact> findAll() throws Exception {
            return contactDao.findAll();
        }
    
        public Contact findById(int id) throws Exception {
            return contactDao.findById(id);
        }
    
        public Serializable insertObject(Contact contact) throws Exception {
            Serializable serializable = contactDao.insertObject(contact);
            return serializable;
        }
    
        public void updateObject(Contact contact) throws Exception {
            contactDao.updateObject(contact);
        }
    
        public void deleteObject(Contact contact) throws Exception {
            contactDao.deleteObject(contact);
        }
    }
    
    <?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:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd 
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context.xsd 
                http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx.xsd 
                http://www.springframework.org/schema/aop 
                http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
    
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${driver}"></property>
            <property name="jdbcUrl" value="${url}"></property>
            <property name="user" value="${username}"></property>
            <property name="password" value="${password}"></property>
            <property name="initialPoolSize" value="${initialPoolSize}"></property>
            <property name="minPoolSize" value="${minPoolSize}"></property>
            <property name="maxPoolSize" value="${maxPoolSize}"></property>
            <property name="maxIdleTime" value="${maxIdleTime}"></property>
        </bean>
    
        <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <!--<property name="configLocation" value="hibernate.cfg.xml"></property>-->
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQL55Dialect</prop>
                    <prop key="hibernate.hbm2ddl.auto">validate</prop>
                    <prop key="hibernate.show_sql">true</prop>
                    <prop key="hibernate.format_sql">false</prop>
                </props>
            </property>
    
            <property name="mappingLocations">
                <list>
                    <value>classpath:com/ogemray/hibernate/entity/*.hbm.xml</value>
                </list>
            </property>
        </bean>
    
        <bean id="contactDao" class="com.ogemray.hibernate.dao.impl.ContactDaoImpl">
            <property name="sessionFactory" ref="sessionFactory"></property>
        </bean>
    
        <bean id="contactService" class="com.ogemray.hibernate.service.ContactServiceImpl">
            <property name="contactDao" ref="contactDao"></property>
        </bean>
    
        <!--事务配置-->
        <bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"></property>
        </bean>
    
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                <tx:method name="find*" read-only="true"/>
                <tx:method name="*" read-only="false"></tx:method>
            </tx:attributes>
        </tx:advice>
    
        <aop:config>
            <aop:pointcut id="pt" expression="execution(* com.ogemray.hibernate.service.*.*(..))"></aop:pointcut>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
        </aop:config>
    </beans>
    

    另外也可以在 Spring 中注入 HibernateTempate 来完成持久层操作

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    
    <bean id="contactDao" class="com.ogemray.hibernate.dao.impl.ContactDaoImpl">
        <property name="hibernateTemplate" ref="hibernateTemplate"></property>
    </bean>
    

    持久层代码修改

    public class ContactDaoImpl implements ContactDao {
        private HibernateTemplate hibernateTemplate;
        public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
            this.hibernateTemplate = hibernateTemplate;
        }
    
        @Override
        public List<Contact> findAll() throws Exception {
            String sql = "from " + Contact.class.getSimpleName();
            List<Contact> list = (List<Contact>) hibernateTemplate.find(sql);
            return list;
        }
    
        @Override
        public Contact findById(int id) throws Exception {
            return hibernateTemplate.get(Contact.class, id);
        }
    
        @Override
        public void updateObject(Contact contact) throws Exception {
            hibernateTemplate.update(contact);
        }
    }
    

    相关文章

      网友评论

          本文标题:Spring中持久层事务配置

          本文链接:https://www.haomeiwen.com/subject/lndofqtx.html