【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: 41000org.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框架的好处在于框架帮我们封装好了一些东西,让我们尽可能少的关心数据库,减少重复代码的编写。
相关文章推荐
- 民谣吉他之新手调音,弦音不对的问题
- Broadcast system调用
- burp suite 抓 https
- HTML5网页如何调用浏览器APP的微信分享功能
- array_reduce()使用
- 多个电脑共用一套鼠标键盘synergy
- JVM学习笔记(一)------基本结构
- 新年程序员福利(多图)
- 大数据修炼高手之路
- springMVC dubbo zookeeper整合
- android studio系列之各种快捷方式
- Java基础-学习笔记(一)
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 老李推荐:第8章7节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-小结
- CMake编译opencv
- iOS用URL调用系统短信、电话、邮件
- android sdcard存储方案三(基于fuse文件系统):
- Paiting Series 1: Part 2
- 【经典工具】:如何通过程序获得系统时间
- My 2016