hibernate整合进spring后的事务处理
单独使用hibernate处理事务
本来只用hibernate开发,从而可以省了DAO层实现数据库访问和跨数据库,也可以对代码进行更好的封装,当我们web中单独使用hibernate时,我们需要单独的处理hibernate的事务,我是使用filter来对事务进行控制的:
单独使用hibernate使用filter进行事务控制:
02
03 public void destroy() {
04
05 }
06
07 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
08 ServletException {
09 Session session = HibernateUtils.openSession();
10 Transaction tx = null;
11 try {
12 tx = session.beginTransaction();
13 chain.doFilter(request, response);
14 tx.commit();
15 } catch (Exception e) {
16 if (tx != null) {
17 tx.rollback();
18 }
19 throw new RuntimeException(e);
20 } finally {
21 HibernateUtils.closeAndRemoveSession();
22 }
23 }
24
25 public void init(FilterConfig arg0) throws ServletException {
26 }
27
28 }
web.xml
02 <filter-name>hibernateSessionFilter</filter-name>
03 <filter-class> syx.jpkc.filter.HibernateSessionFilter</filter-class>
04 </filter>
05 <filter-mapping>
06 <filter-name>hibernateSessionFilter</filter-name>
07 <url-pattern>*.syx</url-pattern>
08 <url-pattern>*.jsp</url-pattern>
09 <url-pattern>*.eve</url-pattern>
10 </filter-mapping>
我主要在servlet(*.syx,*.eve)和jsp页面(没用struts)需要和数据库操作,所以需要使用事务处理。
上面我们还用到了一个 HibernateUtils的小工具类,主要为了获取Session对象和一点优化:
HibernateUitls.java
02 private static Map<Thread, Session> sessionMap;
03 private static SessionFactory sessionFactory;
04 static {
05 sessionMap = new HashMap<Thread, Session>();
06 sessionFactory = new Configuration().configure().buildSessionFactory();
07 }
08
09 /**
10 * can only use in web filter, beause it should remove and clear resources
11 * @return
12 */
13 public static Session openSession() {
14 System.out.println(Thread.currentThread().getStackTrace()[1] + " run in " + new Date());
15 Session session = sessionMap.get(Thread.currentThread());
16 if (session == null) {
17 session = sessionFactory.openSession();
18 sessionMap.put(Thread.currentThread(), session);
19 }
20 return session;
21 }
22 public static Session getCurrentSession() {
23 return sessionMap.get(Thread.currentThread());
24 }
25
26 public static void closeAndRemoveSession() {
27 System.out.println(Thread.currentThread().getStackTrace()[1]+ " run in " + new Date());//
28 Session session = sessionMap.remove(Thread.currentThread());
29 if (session != null) {
30 session.close();
31 }
32 }
33 }
01 public class HibernateUtils {
02 private static Map<Thread, Session> sessionMap;
03 private static SessionFactory sessionFactory;
04 static {
05 sessionMap = new HashMap<Thread, Session>();
06 sessionFactory = new Configuration().configure().buildSessionFactory();
07 }
08
09 /**
10 * can only use in web filter, beause it should remove and clear resources
11 * @return
12 */
13 public static Session openSession() {
14 System.out.println(Thread.currentThread().getStackTrace()[1] + " run in " + new Date());
15 Session session = sessionMap.get(Thread.currentThread());
16 if (session == null) {
17 session = sessionFactory.openSession();
18 sessionMap.put(Thread.currentThread(), session);
19 }
20 return session;
21 }
22 public static Session getCurrentSession() {
23 return sessionMap.get(Thread.currentThread());
24 }
25
26 public static void closeAndRemoveSession() {
27 System.out.println(Thread.currentThread().getStackTrace()[1]+ " run in " + new Date());//
28 Session session = sessionMap.remove(Thread.currentThread());
29 if (session != null) {
30 session.close();
31 }
32 }
33 }
hibernate整合进spring后的事务处理
spring事物处理的方式有很多,详见:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html
介绍常用的:
spring annotation声明式的事务管理
事物处理层?
比如保存一个User,可以在Service层和DAOImpl层实现:
02 userDAO.save(u);
03 }
04
05 public void save(User u) {
06 System.out.println("save user from:" + this);
07 Session s = sessionFactory.openSession();
08 s.beginTransaction();
09 s.save(u);
10 s.getTransaction().commit();
11 s.close();
12 }
假如我们还有个日志记录,没保存一个User对象,要写入日志进入数据库。
而save(log) 和 save(user)必须处在同一事务中,所以不能放在DAOImpl层,事务处理在Service层。
一般的事务处理
02 Transaction tx;
03 try {
04 tx = sess.beginTransaction();
05 //do some work
06 //save(user);
07 //save(log);
08 ...
09 tx.commit();
10 } catch (Exception e) {
11 if (tx!=null) tx.rollback();
12 throw e;
13 } finally {
14 sess.close();
15 }
并且要在实现层中的save()方法中也要加入事务处理,如果出出现异常要throws给上级处理!
并且实现层中的session必须使用openCurrentSession()得到。
2 s.save(u);
spring annotation事务处理
Beans.xml中引入相应的xml命名空间和相应配置:
02 http://www.springframework.org/schema/tx
03 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
04 <tx:annotation-driven transaction-manager="txManager"/>
05 <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
06 <property name="sessionFactory" ref="sessionFactory" />
07 </bean>
08 <bean id="dataSource"
09 class="org.apache.commons.dbcp.BasicDataSource"
10 destroy-method="close">
11 <property name="driverClassName"
12 value="${jdbc.driverClassName}" />
13 <property name="url" value="${jdbc.url}" />
14 <property name="username" value="${jdbc.username}" />
15 <property name="password" value="${jdbc.password}" />
16 </bean>
17 <bean id="sessionFactory"
18 class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
19 <property name="dataSource" ref="dataSource" />
20 <property name="annotatedClasses">
21 <list>
22 <value>com.syx.model.User</value>
23 <value>com.syx.model.Log</value>
24 </list>
25 </property>
26 <property name="hibernateProperties">
27 <props>
28 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
29 <prop key="hibernate.show_sql">true</prop>
30 <prop key="current_session_context_class">thread</prop>
31 </props>
32 </property>
33 </bean>
34 Save方法:
35 public void save(User u) {
36 Session s = sessionFactory.getCurrentSession();
37 s.save(u);
38 }
39 public void save(Log log) {
40 Session s = sessionFactory.getCurrentSession();
41 s.save(log);
42 }
43 Service层处理:
44 @Component("userService")
45 public class UserService {
46 UserDAO userDAO = null;
47 LogDAO logDAO = null;
48
49 public LogDAO getLogDAO() {
50 return logDAO;
51 }
52 @Resource(name="logDAOMySQLImpl")
53 public void setLogDAO(LogDAO logDAO) {
54 this.logDAO = logDAO;
55 }
56 @Transactional
57 public void save(User u) {
58 userDAO.save(u);
59 Log log = new Log();
60 log.setMsg(u.getName() + " saved in " + new Date());
61 logDAO.save(log);
62 }
63 public UserDAO getUserDAO() {
64 return userDAO;
65 }
66 @Resource(name="userDAOMySQLImpl")
67 public void setUserDAO(UserDAO userDAO) {
68 this.userDAO = userDAO;
69 }
70 }
@Transactional详解
什么时候rollback
运行期异常,非运行期异常不会触发rollback
必须uncheck (没有catch)
不管什么异常,只要你catch了,spring就会放弃管理
事务传播特性:propagation_required

propagation 默认是 REQUIRED ,意思是有我们就用现成的,没的我们就创造一个,其他详细见文档
spring xml声明式的事务管理
配置环境和annotation版本一致,只是在用@Transactional处注释调用,在beans.xml中加入如下配置:
02 <aop:config>
03 <aop:pointcut id="serviceOperation"
04 expression="execution(* com.syx.service..*.*(..))" />
05 <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
06 </aop:config>
07
08 <tx:advice id="txAdvice" transaction-manager="txManager">
09 <tx:attributes>
10 <tx:method name="getUser" read-only="true" />
11 <tx:method name="save" /><!-- 相当于在上面切面pointcut@Transactional效果 -->
12 </tx:attributes>
13 </tx:advice>
hibernateTemplate.getSessionFactory().getCurrentSession()
我们使用spring和hibernate结合,操作数据库最常用可能是HibernateTemplate,HibernateTemplate中集成了很多使用的方法,可惜的是没的createQuery方法,也许我们使用hibernate的时候喜欢使用Query,我们可能会封装hibernateTemplate.getSessionFactory().getCurrentSession()方法得到Session,session创建Query,这是一个方法,但你应该会得到异常 “createQuery without an active transaction”,因为使用hibernateTemplate.getSessionFactory().getCurrentSession(),你是使用的hibernate的事务管理,而你指望spring管理的事务是hibernateTemplate,所以你会提示没有打开事务的异常,解决方法:1)使用hibernate事务处理,就像上面单独使用hibernate一样,但这也许不是你想要的。2)使用hibernateTemplate的HibernateCallBack回调:
2 new HibernateCallback<List<T>>() {
3 public List<T> doInHibernate(Session session)
4 throws HibernateException, SQLException {
5 return session.createQuery
6 ("FROM " + entityClass.getName() + " WHERE id IN (:ids)")//
7 .setParameterList("ids", idList).list();
8 }
实际上hibernateTemplate中封装的find方法也很强大,如果熟练使用完全可以替代createQuery的。
备注:
如果出现异常:对同一个集合处理不能使用2个session,这是因为getCurrentSession方法出错,导致打开一个新的session,检查配置文件,如果使用tomcat+spring+hibernate 配置hibernate.current_session_context_class 最好为thread,虽然支持jta,配置比较麻烦,而且jta支持多个sessionFactory,即可以跨数据库,比较强大!
如果hibernate+spring出现session没有提交情况,应该是你让spring负责事务处理,而你有使用了hibernate的session,从而脱离spring事务处理,即没的begintransaction和commit之类的操作了。
hibernate整合进spring后的事务处理的更多相关文章
- Spring第九篇【Spring与Hibernate整合】
前言 前面已经学习了如何使用Spring与Struts2进行整合,本博文主要讲解如何使用Spring对Hibernate进行整合 Spring和Hibernate整合的关键点: SessionFact ...
- Hibernate【与Spring整合】
前言 前面已经学习了如何使用Spring与Struts2进行整合,本博文主要讲解如何使用Spring对Hibernate进行整合 Spring和Hibernate整合的关键点: SessionFact ...
- 整合struts2+spring+hibernate
一.准备struts2+spring+hibernate所须要的jar包: 新建web项目并将jar包引入到project项目中. 二.搭建struts2环境 a.在 ...
- 一 SSH整合:Spring整合Struts2的两种方式,struts.xml管理Action&Bean管理Action
SSH回顾 1 引入jar包 Struts2的jar包 D:\Struts2\struts-2.3.35\apps\struts2-blank\WEB-INF\lib 开发基本包 Struts2有一 ...
- Spring与Hibernate整合中,使用OpenSessionInViewFilter后出现sessionFactory未注入问题
近期在知乎看到一句话,保持学习的有一种是你看到了很多其它的牛人,不甘心,真的不甘心. Spring和hibernate整合的时候,jsp页面做展现,发现展现属性出现: org.apache.jaspe ...
- Struts+Spring+Hibernate整合入门详解
Java 5.0 Struts 2.0.9 Spring 2.0.6 Hibernate 3.2.4 作者: Liu Liu 转载请注明出处 基本概念和典型实用例子. 一.基本概念 St ...
- 框架篇:Spring+SpringMVC+hibernate整合开发
前言: 最近闲的蛋疼,搭个框架写成博客记录下来,拉通一下之前所学知识,顺带装一下逼. 话不多说,我们直接步入正题. 准备工作: 1/ IntelliJIDEA的安装配置:jdk/tomcat等..(本 ...
- Java Web开发之Spring | SpringMvc | Mybatis | Hibernate整合、配置、使用
1.Spring与Mybatis整合 web.xml: <?xml version="1.0" encoding="UTF-8"?> <web ...
- springmvc框架(Spring SpringMVC, Hibernate整合)
直接干货 model 考虑给用户展示什么.关注支撑业务的信息构成.构建成模型. control 调用业务逻辑产生合适的数据以及传递数据给视图用于呈献: view怎样对数据进行布局,以一种优美的方式展示 ...
随机推荐
- SecureCRT中使用 rz 上传文件 遇到 rz: command not found 的解决办法
-bash: rz: command not foundrz命令没找到?执行sz,同样也没找到. 安装lrzsz: # yum -y install lrzsz 现在就可以正常使用rz.sz命令上传. ...
- Debugging Java Native Memory Leaks
GZIP造成JAVA Native Memory泄漏案例 https://www.elastic.co/blog/tracking-down-native-memory-leaks-in-elasti ...
- .NET MVC+ EF+调用存储过程 多表联查以及VIEW列表显示
直接上干活,至于网上的一大堆处理方式不予评论,做好自己的就是最好的,供大家不走弯路 1.view页面 <link href="~/Content/bootstrap.css" ...
- SpringBoot整合SpringKafka实现消费者史上最简代码实现
该项目是使用的技术:SpringBoot + SpringKafka + Maven 先看pom.xml文件中引入的依赖: <?xml version="1.0" enco ...
- GitHub支持的Markdown语法 GitHub Flavored Markdown
GitHub支持的Markdown语法,简称GFM.相比标准的Markdown(SM)语法,有少数几个区别,并添加了新的功能. 本位参考 GitHub Flavored Markdown 撰写.有兴趣 ...
- RAID常见问题集锦+底部案例
磁盘阵列(Redundant Arrays of Inexpensive Disks,RAID),有“价格便宜具有冗余能力的磁盘阵列”之意.原理是利用数组方式来作磁盘组,配合数据分散排列的设计,提升数 ...
- js实现裁剪头像上传编辑器
插件: 1.富头像上传编辑器是一款支持本地上传.预览.视频拍照和网络加载的flash头像编辑上传插件,可缩放.裁剪.旋转.定位和调色等. http://www.fullavatareditor.com ...
- python 使用pillow将图片转换为webp格式
1.webp格式 webp格式是谷歌开发的一种旨在加快图片加载速度的格式,将图片转为webp格式后,体积约为原来的2/3,这可以节省大量的服务器带宽,微信公众号文章里的图片就是这种格式的. 2.使用p ...
- hdu1217(spfa,存在环,但需要将环的元素历遍一次.....求乘积的最大)
题意:有n个国家货币,给出m种两个国家之间的货币兑换率,求是否可以盈利....... 思路:其实就是看国家货币兑换间是否存在一个环,使得从v点出发时,dis[v]=1,经过环回到v点时,dis[v]& ...
- Faiss教程:入门
Faiss处理固定维度d的数据,矩阵每一行表示一个向量,每列表示向量的一项.Faiss采用32-bit浮点型存储. 假设xb为数据集,维度为\(nb\times{d}\):xq是查询数据,维度为\(n ...