您的位置:首页 > 其它

【Hibernate系列】(二):事务的应用

2015-12-31 17:30 197 查看

需求

  添加订单成功后,需要将购物车中的商品清空,这两个操作要么都执行,要么都不执行。这时,就用到了事务。

使用

1.配置

在hibernate.cfg.xml中添加

[code]<!--使用currentSession配置事务-->
    <property name="hibernate.current_session_context_class">thread</property>


2.开启,关闭,回滚

[code]    /** 添加订单信息 **/
    public Boolean addOrders(SchoolShop_Orders orders,int[] cids) {
        Boolean flag = true;
        Session session=getSession(); 
        try {
            //开启事务 
            session.beginTransaction(); 
            //添加订单  
            session.save(orders);
            //清空购物项
            deleteCarts(cids,session);
            //提交事务
            session.getTransaction().commit(); 
        } catch (Exception e) {
            flag = false;           
            e.printStackTrace();
            //回滚事务
            session.getTransaction().rollback();
        }
        return flag;
    }
    /**
     * 批量删除购物项
     * @param cids
     * @param session
     * @return
     */
    public Boolean deleteCarts(int[] cids,Session session) {
        int num=0;
        String hql = "";
        for(int i=0;i<cids.length;i++) {
            if(i==0) {
                hql = "cid="+cids[i];
            } else {
                hql =hql + " or cid="+cids[i];
            }
        } 
         Query q= session.createQuery("delete from SchoolShop_cart where "+hql);
         num=q.executeUpdate();

        if(num>0){
            return true;
        }else{
            return false;
        }

    }


3.getSession方法

[code]@Transactional
@SuppressWarnings("unchecked")
public class DaoSupportImpl<T> implements DaoSupport<T> {

    @Resource
    private SessionFactory sessionFactory;
    private Class<T> clazz;

    public DaoSupportImpl() {
        // 使用反射技术得到T的真实类型
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取当前new的对象的 泛型的父类 类型
        this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型
        System.out.println("clazz ---> " + clazz);
    }
    /**
     * 获取当前可用的Session
     * 
     * @return
     */
    protected Session getSession() {
        return sessionFactory.getCurrentSession();
    }

}


问题

【错误】:WARN JDBCExceptionReporter:233 - SQL Error: 1205, SQLState: 41000

org.hibernate.exception.GenericJDBCException: could not execute update query16:05:37,361

【原因】:锁等待超时

【解决】:事务范围内,出现异常时,事务提交不成功,没有回滚事务,所以必须加上session.getTransaction().rollback();

温故

  看看在不使用Hibernate框架的时候如何使用事务:

[code]public void addFlowCard(FlowCard flowCard) throws ApplicationException {
        Connection conn=null;
        try{
            conn = ConnectionManager.getConnection();
            //开始事务
            ConnectionManager.beginTransaction(conn);

            String flowCardVouNo=flowCardDao.generateVouNo();
            flowCardDao.addFlowCardMaster(flowCardVouNo, flowCard);
            flowCardDao.addFlowCardDetail(flowCardVouNo, flowCard.getFlowCardDetailList());
            //提交事务
            ConnectionManager.commitTransaction(conn);
        }catch(DaoException e){
            //回滚事务
            ConnectionManager.rollbackTransaction(conn);
            throw new ApplicationException("添加流向单失败!");
        }finally{
            //关闭Connection并从ThreadLocal中清除
            ConnectionManager.closeConnection();
        }
    }


知新

对比使用Hibernate框架和不使用框架的情况下,事务的使用方法有何不同。发现,基本步骤没有变(开启事务,提交事务,回滚事务)。不同的是:



获取连接对象的方式

不使用Hibernate的时候,借助ThreadLocal获得线程内的Connection对象:



[code]package com.tgb.drp.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class ConnectionManager {
    private static ThreadLocal<Connection> connectionHolder=new ThreadLocal<Connection>();

    /**
     * 获得Connection
     * @return
     */
    public static Connection getConnection(){

        Connection conn=connectionHolder.get(); 
        if(conn==null){
            try{
                JdbcConfig jdbcConfig=XmlConfigReader.getInstance().getJdbcConfig();            
                Class.forName(jdbcConfig.getDriverName());  
                conn= DriverManager.getConnection(jdbcConfig.getUrl(),jdbcConfig.getUsername(),jdbcConfig.getPassword()) ;
                connectionHolder.set(conn);
            }catch (ClassNotFoundException e){
                e.printStackTrace();
                throw new ApplicationException("系统错误,请联系管理员!");
            } catch (SQLException e) {

                e.printStackTrace();
                throw new ApplicationException("系统错误,请联系管理员!");
            }
        }
        return conn;
    }
    /**
     * 关闭Connection
     */
    public static void closeConnection(){
        Connection conn = connectionHolder.get();
        if (conn != null) {
            try {
                conn.close();
                //从ThreadLocal中清除Connection
                connectionHolder.remove();
            } catch (SQLException e) {
                e.printStackTrace();
            }   
        }
    }
    /**
     * 开始事务
     * @param conn
     */
    public static void beginTransaction(Connection conn) {
        try {
            if (conn != null) {
                if (conn.getAutoCommit()) {
                    conn.setAutoCommit(false); //手动提交
                }
            }
        }catch(SQLException e) {}
    }
    /**
     * 提交事务
     * @param conn
     */
    public static void commitTransaction(Connection conn) {
        try {
            if (conn != null) {
                if (!conn.getAutoCommit()) {
                    conn.commit();
                }
            }
        }catch(SQLException e) {}
    }

    /**
     * 回滚事务
     * @param conn
     */
    public static void rollbackTransaction(Connection conn) {
        try {
            if (conn != null) {
                if (!conn.getAutoCommit()) {
                    conn.rollback();
                }
            }
        }catch(SQLException e) {}
    }
    /**
     * 关闭命令
     * @param pstmt
     */
    public static void close(Statement pstmt) {
        if (pstmt != null) {
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static void close(ResultSet rs ) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}


 2.是否显示的打开和关闭连接对象

使用Hibernate的currensession时,并不需要我们自己去打开或关闭对象。

  所以使用Hibernate框架的好处在于框架帮我们封装好了一些东西,让我们尽可能少的关心数据库,减少重复代码的编写。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: