Spring 与 mybatis整合---事务管理

MyBatis与Spring整合前后事务管理有所区别

整合前:通过

  session = sessionFactory.openSession(true);  //或者是false

设置事务是否自动提交;

整合后,在这样写就不起作用了,无论设置为true还是false  都会自动提交事务;

如果想设置事务非自动提交有以下几种方案:

  ① 创建session之后,手动拿到connection,设置事务非自动提交

  session.getConnection().setAutoCommit(false);

  ② 通过spring管理事务

    @Test
    /**
     * 测试插入数据,同时测试手动提交事务
     */
    public void test_insert() {
        System.out.println("==============插入数据==================");
        //开启事务
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        DataSourceTransactionManager transactionManager = (DataSourceTransactionManager) DaoApplicationContext
                .getInstance().getBean("txManager");
        TransactionStatus transactionStatus = (TransactionStatus) transactionManager
                .getTransaction(definition);

        Fh_fullnote order = new Fh_fullnote();
        order.setHf_serialid("HF100120160829155555012507");
        order.setHf_orderid("OD100120160829155555012507");
        order.setCharge_phone("18201304217");
        order.setCharge_money(50D);
        int insertRet = fh_fullnoteDao.insert(order);
        
        //提交事务
        transactionManager.commit(transactionStatus); 
        System.out.println("插入数据返回值:" + insertRet);
    }

  

  ③ 注解式事务

  首先对Dao层做一个详细的解析

  Dao层应用上下文

package ctp.demo.dao.fh.dao;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DaoApplicationContext {
    private static ApplicationContext ctx=null;
    
    public static ApplicationContext getCtx() {
        return ctx;
    }
    public static void setCtx(ApplicationContext ctx) {
        DaoApplicationContext.ctx = ctx;
    }
    
    
    public static ApplicationContext getInstance(){
        if(ctx == null){
            ctx=new ClassPathXmlApplicationContext("applicationContext-Dao.xml");
        }
        return ctx;
    }
}
DaoApplicationContext.java

  Dao数据模型

package ctp.demo.dao.fh.vo;

import java.util.Date;

public class Fh_fullnote {
    String hf_serialid ;    //流水号
    String hf_orderid ;        //订单号
    Integer isp_id ;        //运营商ID
    Integer province_id;    //省份ID
    Integer city_code;        //城市编码
    Integer service_type;    //业务类型
    String charge_phone;    //充值手机号
    Double charge_money;    //充值金额
    Double finish_money;    //完成金额
    Double charge_flux;        //充值流量
    Double finish_flux;        //完成充值的流量
    Double charge_status;    //充值状态
    Integer error_code ;    //错误码
    String error_info ;        //错误描述
    Date begin_time ;        //开始时间
    Date end_time ;            //结束时间
    String charge_serialid ;//对端流水
    Integer query_count ;    //查询次数
    Integer query_status ;    //查询状态
    Integer notify_flag ;    //通知标识
    Integer notify_count ;    //通知次数
    Integer card_source ;    //卡来源
    String card_num ;        //卡号
    Date charge_datetime ;    //入库时间
    Date query_begintime ;    //查询开始时间
    Integer channel_id ;    //渠道ID
    String card_pwd ;        //卡密
    
    public String getHf_serialid() {
        return hf_serialid;
    }
    public void setHf_serialid(String hf_serialid) {
        this.hf_serialid = hf_serialid;
    }
    public String getHf_orderid() {
        return hf_orderid;
    }
    public void setHf_orderid(String hf_orderid) {
        this.hf_orderid = hf_orderid;
    }
    public Integer getIsp_id() {
        return isp_id;
    }
    public void setIsp_id(Integer isp_id) {
        this.isp_id = isp_id;
    }
    public Integer getProvince_id() {
        return province_id;
    }
    public void setProvince_id(Integer province_id) {
        this.province_id = province_id;
    }
    public Integer getCity_code() {
        return city_code;
    }
    public void setCity_code(Integer city_code) {
        this.city_code = city_code;
    }
    public Integer getService_type() {
        return service_type;
    }
    public void setService_type(Integer service_type) {
        this.service_type = service_type;
    }
    public String getCharge_phone() {
        return charge_phone;
    }
    public void setCharge_phone(String charge_phone) {
        this.charge_phone = charge_phone;
    }
    public Double getCharge_money() {
        return charge_money;
    }
    public void setCharge_money(Double charge_money) {
        this.charge_money = charge_money;
    }
    public Double getFinish_money() {
        return finish_money;
    }
    public void setFinish_money(Double finish_money) {
        this.finish_money = finish_money;
    }
    public Double getCharge_flux() {
        return charge_flux;
    }
    public void setCharge_flux(Double charge_flux) {
        this.charge_flux = charge_flux;
    }
    public Double getFinish_flux() {
        return finish_flux;
    }
    public void setFinish_flux(Double finish_flux) {
        this.finish_flux = finish_flux;
    }
    public Double getCharge_status() {
        return charge_status;
    }
    public void setCharge_status(Double charge_status) {
        this.charge_status = charge_status;
    }
    public Integer getError_code() {
        return error_code;
    }
    public void setError_code(Integer error_code) {
        this.error_code = error_code;
    }
    public String getError_info() {
        return error_info;
    }
    public void setError_info(String error_info) {
        this.error_info = error_info;
    }
    public Date getBegin_time() {
        return begin_time;
    }
    public void setBegin_time(Date begin_time) {
        this.begin_time = begin_time;
    }
    public Date getEnd_time() {
        return end_time;
    }
    public void setEnd_time(Date end_time) {
        this.end_time = end_time;
    }
    public String getCharge_serialid() {
        return charge_serialid;
    }
    public void setCharge_serialid(String charge_serialid) {
        this.charge_serialid = charge_serialid;
    }
    public Integer getQuery_count() {
        return query_count;
    }
    public void setQuery_count(Integer query_count) {
        this.query_count = query_count;
    }
    public Integer getQuery_status() {
        return query_status;
    }
    public void setQuery_status(Integer query_status) {
        this.query_status = query_status;
    }
    public Integer getNotify_flag() {
        return notify_flag;
    }
    public void setNotify_flag(Integer notify_flag) {
        this.notify_flag = notify_flag;
    }
    public Integer getNotify_count() {
        return notify_count;
    }
    public void setNotify_count(Integer notify_count) {
        this.notify_count = notify_count;
    }
    public Integer getCard_source() {
        return card_source;
    }
    public void setCard_source(Integer card_source) {
        this.card_source = card_source;
    }
    public String getCard_num() {
        return card_num;
    }
    public void setCard_num(String card_num) {
        this.card_num = card_num;
    }
    public Date getCharge_datetime() {
        return charge_datetime;
    }
    public void setCharge_datetime(Date charge_datetime) {
        this.charge_datetime = charge_datetime;
    }
    public Date getQuery_begintime() {
        return query_begintime;
    }
    public void setQuery_begintime(Date query_begintime) {
        this.query_begintime = query_begintime;
    }
    public Integer getChannel_id() {
        return channel_id;
    }
    public void setChannel_id(Integer channel_id) {
        this.channel_id = channel_id;
    }
    public String getCard_pwd() {
        return card_pwd;
    }
    public void setCard_pwd(String card_pwd) {
        this.card_pwd = card_pwd;
    }
}
Fh_fullnote.java

  Dao操作类

package ctp.demo.dao.fh.dao;

import java.sql.SQLException;
import java.util.Map;
import java.util.TreeMap;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import ctp.demo.dao.fh.vo.Fh_fullnote;

public class Fh_fullnote_dao {
    SqlSession session = null;
    String dao_namespace = "fh.dao.fh_fullnote.";
    /**
     * 订单插入
     * @param order 订单类模型
     * @return 0:插入正常   -1:插入数据异常
     */
    public int insert(Fh_fullnote order){
        try{
            checkSession();
            session.insert(dao_namespace + "addOrder", order);
            return 0;
        }catch(Exception e){
            e.printStackTrace();
            return -1;
        }
    }
    
    /**
     * 根据订单号更新订单状态
     * @param hf_id    订单号
     * @param orderStatus 订单状态
     * @return 0:正常   -1:异常
     */
    public int updateChargeStatusByHF(String hf_id,String orderStatus){
        try{
            checkSession();
            Map<String, String> map = new TreeMap<String, String>();
            map.put("hf_id", hf_id);
            map.put("orderStatus", orderStatus);
            session.update(dao_namespace + "updateChargeStatusByHF", map);
            return 0;
        }catch(Exception e){
            e.printStackTrace();
            return -1;
        }
    }
    
    /**
     * 根据流水号 获取订单
     * @param hf_id 流水号
     * @return 订单 or null
     */
    public Fh_fullnote getOrderByHF_ID(String hf_id){
        try {
            checkSession();
            Fh_fullnote order = (Fh_fullnote)session.selectOne(dao_namespace+"getOrderByHF_ID", hf_id);
            return order;
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 检查当前是否有session,没有则打开一个session
     */
    public void checkSession(){
        if(session == null){
            SqlSessionFactory sessionFactory = (SqlSessionFactory)DaoApplicationContext.getInstance().getBean("sqlSessionFactory");
            session = sessionFactory.openSession();
            
            try {
                System.out.println("是否自动提交:" + session.getConnection().getAutoCommit());
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
Fh_fullnote_dao.java

  映射文件

<?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="fh.dao.fh_fullnote">
    <!-- 插入数据 -->
    <insert id="addOrder" parameterType="ctp.demo.dao.fh.vo.Fh_fullnote">         
        insert into fh_fullnote ( HF_SERIALID, HF_ORDERID, ISP_ID, PROVINCE_ID, CITY_CODE, SERVICE_TYPE, CHARGE_PHONE, CHARGE_MONEY, FINISH_MONEY, CHARGE_FLUX, FINISH_FLUX, CHARGE_STATUS, ERROR_CODE, ERROR_INFO, BEGIN_TIME, END_TIME, CHARGE_SERIALID, QUERY_COUNT, QUERY_STATUS, NOTIFY_FLAG, NOTIFY_COUNT, CARD_SOURCE, CARD_NUM, CHARGE_DATETIME, QUERY_BEGINTIME, CHANNEL_ID, CARD_PWD) 
                values(#{hf_serialid},#{hf_orderid},#{isp_id},#{province_id},#{city_code},#{service_type},#{charge_phone},#{charge_money},#{finish_money},#{charge_flux},#{finish_flux},#{charge_status},#{error_code},#{error_info},#{begin_time},#{end_time},#{charge_serialid},#{query_count},#{query_status},#{notify_flag},#{notify_count},#{card_source},#{card_num},#{charge_datetime},#{query_begintime},#{channel_id},#{card_pwd}); 
    </insert>
    
    <!-- 根据流水号修改充值状态 -->
    <update id="updateChargeStatusByHF" parameterType="java.util.Map">
        update fh_fullnote set CHARGE_STATUS = #{orderStatus}
            where HF_SERIALID = #{hf_id}
    </update>
    
    <!-- 根据流水号获取订单 -->
    <select id="getOrderByHF_ID" parameterType="String" resultType = "ctp.demo.dao.fh.vo.Fh_fullnote">
        select * from fh_fullnote where HF_SERIALID = #{hf_id}
    </select>
</mapper>
fh_fullnote_mapper.xml

   Spring配置文件

<?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:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"
    >
    <!--开启注解配置  -->     
    <context:annotation-config />
    <!-- 扫描注解 -->
    <context:component-scan base-package="ctp" />
    <!-- 配置数据源 -->
    <bean id = "dataSource" name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
        <property name="url" value="jdbc:mysql://192.168.61.28:3306/ctp" />  
        <property name="username" value="encysys48" />     
        <property name="password" value="encysys48" />
    </bean>
    
    <!-- 配置事务管理器 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
        <property name="dataSource" ref="dataSource"/>  
    </bean>
    <!-- 事务注解驱动 -->
    <tx:annotation-driven transaction-manager="txManager" /> 
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入mybatis的配置文件 -->
        <property name="configLocation">
            <!-- 不加classpath:会出现错误 -->
            <value>classpath:mybatis-config.xml</value>
        </property>
        <property name="dataSource">
            <!-- 此处填写ID -->
            <ref local="dataSource"/>
        </property>
        <property name="mapperLocations" value="classpath:ctp/**/*mapper.xml">
        </property>
    </bean>
    
    <bean id="Fh_fullnote_dao" class="ctp.demo.dao.fh.dao.Fh_fullnote_dao">
    </bean>
    
     <!-- 自动扫描映射器 -->  
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  
        <property name="basePackage" value="ctp" />  
    </bean>
    
</beans>
applicationContext-Dao.xml

 

  下面看Service层:

package ctp.demo.service.fh;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import ctp.demo.dao.fh.dao.Fh_fullnote_dao;
import ctp.demo.dao.fh.vo.Fh_fullnote;

@Component("fh_fullnoteService")
@Transactional
public class Fh_fullnoteService {
    
    @Autowired
    Fh_fullnote_dao fh_fullnoteDao;
    
    @Transactional(rollbackFor={Exception.class, RuntimeException.class})
    public int addOrder(Fh_fullnote order){
        try {
            int insertRet = fh_fullnoteDao.insert(order);
            System.out.println("下单结果:" + insertRet);
            return 0;
        } catch (Exception e) {
            // TODO: handle exception
            return -1;
        }
    }
    
    public Fh_fullnote_dao getFh_fullnoteDao() {
        return fh_fullnoteDao;
    }
    public void setFh_fullnoteDao(Fh_fullnote_dao fh_fullnoteDao) {
        this.fh_fullnoteDao = fh_fullnoteDao;
    }
}

  测试代码:  

package ctp.demo.service.fh;

import static org.junit.Assert.*;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import ctp.demo.dao.fh.dao.DaoApplicationContext;
import ctp.demo.dao.fh.vo.Fh_fullnote;

public class Test_Fh_fullnoteService {

    @Test
    public void test() {
        System.out.println("===============下单开始================");
        
        Fh_fullnote order = new Fh_fullnote();
        order.setHf_serialid("HF100120160829155555012510");
        order.setHf_orderid("OD100120160829155555012510");
        order.setCharge_phone("18201304217");
        order.setCharge_money(50D);
        //关于Dao层的配置文件,需要在service层读取,然后将上下文注入到Dao里面
        //否则的话 @Transactional注解是不生效的
        String[] configeRations = new String[]{"applicationContext-Service.xml","applicationContext-Dao.xml"};
        ApplicationContext ctx=new ClassPathXmlApplicationContext(configeRations);
        DaoApplicationContext.setCtx(ctx);
        Fh_fullnoteService fullnote_service = (Fh_fullnoteService)ctx.getBean("fh_fullnoteService");
        fullnote_service.addOrder(order);
        System.out.println();
    }

}

  通过断点调试,发现跳出函数之前,是不会提交的,说明注解事务生效。

  需要注意的是,Dao层应用的上下文应该与Service应用的上下文一致,那么Dao层的配置文件就应该在Service层读取,然后将上下文注入到Dao层中。

  附配置文件:

<?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:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
    >
    
    <!-- 配置数据源 -->
    <bean id = "dataSource" name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
        <property name="url" value="jdbc:mysql://192.168.61.28:3306/ctp" />  
        <property name="username" value="encysys48" />     
        <property name="password" value="encysys48" />
    </bean>
    
    <!-- 配置事务管理器 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
        <property name="dataSource" ref="dataSource"/>  
    </bean>
    <!-- 事务注解驱动 -->
    <tx:annotation-driven transaction-manager="txManager" /> 
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入mybatis的配置文件 -->
        <property name="configLocation">
            <!-- 不加classpath:会出现错误 -->
            <value>classpath:mybatis-config.xml</value>
        </property>
        <property name="dataSource">
            <!-- 此处填写ID -->
            <ref local="dataSource"/>
        </property>
        <property name="mapperLocations" value="classpath:ctp/**/*mapper.xml">
        </property>
    </bean>
    
    <bean id="Fh_fullnote_dao" class="ctp.demo.dao.fh.dao.Fh_fullnote_dao">
    </bean>
</beans>
applicationContext-Dao.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:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"
    >
    
    <!--开启注解配置  -->     
    <context:annotation-config />
    <!-- 扫描注解 -->
    <context:component-scan base-package="ctp" />
    <!-- 注解自动生效 -->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
    
    
    <bean id="fh_fullnoteDao" class="ctp.demo.dao.fh.dao.Fh_fullnote_dao" />
</beans>
applicationContext-Service.xml

    全部源码:http://download.csdn.net/detail/panpanteng/9618044

posted @ 2016-08-30 15:11  沙中世界  阅读(514)  评论(0编辑  收藏  举报