工程结构

问题描述

在工程中通过spring aop的方式配置事务,使用hibernate做持久化。在代码实现中使用hibernate persit()方法插入数据到数据库,使用hibernate update()方法更新数据。问题是执行这两个方法没有报错,但是也没有插入数据或者更新数据。

原因

hibernate persist()以及update()方法只有事务执行flush()或者commit()方法,才将数据写入数据库。详细内容可以阅读博客:http://www.cnblogs.com/xiaoheike/p/5374613.html。使用spring aop配置的事务,在方法运行结束之后会运行commit()方法。程序实例可以看PersonDAOImpl.java(实现方法)小结,重点原因在于spring aop事务与session自己创建的事务是两个不同的事务,虽然最后spring aop 配置的事情 commit,但是session对象的事务并没有调用commit。以下是实例程序。

事务配置(applicationContext.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: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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/Testdb" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean> <!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hiberante.format_sql">true</prop>
</props>
</property>
<!-- hibernate配置文件放置位置,这个配置文件似乎也没有多大的作用了 -->
<property name="configLocations">
<list>
<value>
classpath:/hibernate.cfg.xml
</value>
</list>
</property>
</bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean> <tx:advice id="personServiceTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 表达式中的这些方法会执行如下的规则 -->
<tx:method name="delete*" isolation="DEFAULT" read-only="false" propagation="REQUIRED" />
<tx:method name="update*" isolation="DEFAULT" read-only="false" propagation="REQUIRED" />
<tx:method name="save*" isolation="DEFAULT" read-only="false" propagation="REQUIRED" />
<tx:method name="*" isolation="DEFAULT" read-only="false" propagation="REQUIRED" />
</tx:attributes>
</tx:advice> <aop:config>
<aop:pointcut id="personServiceTxPointcut" expression="execution(* com.journaldev.dao.PersonDAO.*(..))" />
<aop:advisor id="personServiceTxAdvisor" advice-ref="personServiceTxAdvice" pointcut-ref="personServiceTxPointcut" />
</aop:config> <bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl">
<property name="sessionFactory1" ref="sessionFactory" />
<property name="sessionFactory2" ref="sessionFactory" />
</bean>
</beans>

PersonDAOImpl.java(实现方法)

package com.journaldev.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction; import com.journaldev.model.Person; public class PersonDAOImpl implements PersonDAO { private SessionFactory sessionFactory1;
private SessionFactory sessionFactory2; public void setSessionFactory1(SessionFactory sessionFactory1) {
this.sessionFactory1 = sessionFactory1;
} public void setSessionFactory2(SessionFactory sessionFactory2) {
this.sessionFactory2 = sessionFactory2;
} public void save1(Person person) {
Session session1 = this.sessionFactory1.openSession();
session1.persist(person);
session1.close();
} public void save2(Person person) {
Session session1 = this.sessionFactory1.openSession();
Session session2 = sessionFactory2.openSession();
Transaction tx = session2.beginTransaction();
session1.persist(person);
tx.commit();
session2.close();
session1.close();
} public void save3(Person person) {
Session session1 = this.sessionFactory1.openSession();
Transaction tx = session1.beginTransaction();
session1.persist(person);
tx.commit();
session1.close();
} @SuppressWarnings("unchecked")
public List<Person> list() {
Session session = this.sessionFactory1.openSession();
List<Person> personList = session.createQuery("from Person").list();
session.close();
return personList;
} public Person findOne(Integer id) {
Session session = this.sessionFactory1.openSession();
Person p = (Person) session.get(Person.class, id);
session.close();
return p;
} public void delete(Person person) {
Session session = this.sessionFactory1.openSession();
session.delete(person);
session.close();
} public void update1(Person person) {
Session session = this.sessionFactory1.openSession();
session.update(person);
session.close();
} public void update2(Person person) {
Session session1 = this.sessionFactory1.openSession();
Session session2 = this.sessionFactory1.openSession();
Transaction tx = session2.beginTransaction();
session1.update(person);
tx.commit();
session2.close();
session1.close();
} public void update3(Person person) {
Session session1 = this.sessionFactory1.openSession();
Transaction tx = session1.beginTransaction();
session1.update(person);
tx.commit();
session1.close();
}
}

测试类

package com.journaldev.main;

import java.util.List;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.journaldev.dao.PersonDAO;
import com.journaldev.model.Person; public class SpringHibernateMain { public static void main(String[] args) {
test1();
test2();
test3();
} public static void test1() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonDAO personDAO = context.getBean(PersonDAO.class);
System.out.println("=================save1()==================");
// 增加一条数据
Person person = new Person();
person.setName("Pankaj");
person.setCountry("India");
personDAO.save1(person);
System.out.println("================listAll()===================");
// 检索所有数据
List<Person> list = personDAO.list();
for (Person p : list) {
System.out.println("所有记录:" + p);
}
System.out.println("================update1()===================");
// 更新一条Person记录
person.setCountry("zhongguo");
personDAO.update1(person);
System.out.println("更新一条记录India-->zhongguo:" + personDAO.findOne(person.getId()));
System.out.println("================delete()===================");
// 删除一条Person记录
personDAO.delete(person); context.close();
} public static void test2() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonDAO personDAO = context.getBean(PersonDAO.class);
System.out.println("=================save3()==================");
// 增加一条数据
Person person = new Person();
person.setName("Pankaj");
person.setCountry("India");
personDAO.save1(person);
System.out.println("================listAll()===================");
// 检索所有数据
List<Person> list = personDAO.list();
for (Person p : list) {
System.out.println("所有记录:" + p);
}
System.out.println("================update2()===================");
// 更新一条Person记录
person.setCountry("zhongguo");
personDAO.update1(person);
System.out.println("更新一条记录India-->zhongguo:" + personDAO.findOne(person.getId()));
System.out.println("================delete()===================");
// 删除一条Person记录
personDAO.delete(person); context.close();
} public static void test3() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonDAO personDAO = context.getBean(PersonDAO.class);
System.out.println("=================save3()==================");
// 增加一条数据
Person person = new Person();
person.setName("Pankaj");
person.setCountry("India");
personDAO.save3(person);
System.out.println("================listAll()===================");
// 检索所有数据
List<Person> list = personDAO.list();
for (Person p : list) {
System.out.println("所有记录:" + p);
}
System.out.println("================update3()===================");
// 更新一条Person记录
person.setCountry("zhongguo");
personDAO.update3(person);
System.out.println("更新一条记录India-->zhongguo:" + personDAO.findOne(person.getId()));
System.out.println("================delete()===================");
// 删除一条Person记录
personDAO.delete(person); context.close();
}
}

运行结果

=================save1()==================
================update1()===================
Hibernate: select person0_.id as id1_0_0_, person0_.country as country2_0_0_, person0_.name as name3_0_0_ from PERSON person0_ where person0_.id=?
更新一条记录India-->zhongguo:null =================save2()==================
================update2()===================
Hibernate: select person0_.id as id1_0_0_, person0_.country as country2_0_0_, person0_.name as name3_0_0_ from PERSON person0_ where person0_.id=?
更新一条记录India-->zhongguo:null =================save3()==================
Hibernate: insert into PERSON (country, name) values (?, ?)
================update3()===================
Hibernate: update PERSON set country=?, name=? where id=?
Hibernate: select person0_.id as id1_0_0_, person0_.country as country2_0_0_, person0_.name as name3_0_0_ from PERSON person0_ where person0_.id=?
更新一条记录India-->zhongguo:id=8, name=Pankaj, country=zhongguo

原因分析

一共有三个测试例子,第一个例子test1()方法,调用save1()方法,使用spring aop配置的事务,从输出结果可以看出,数据没有插入数据库。update1()方法与save1()方法是相同情况。

第二个例子test2()方法,调用save2()方法,persist()方法被包围在spring aop配置的事务和session2的事务中(事务有提交),从输出结果可以看出,数据没有插入数据库。update2()方法与save2()方法是相同情况。

第三个例子test3()方法,persist()方法被包围在spring aop配置的事务和session1的事务中(事务有提交),从输出结果可以看出,数据成功插入数据库。update3()方法与save3()方法是相同情况。

通过实例程序可以看出,persist(),以及update()方法需要在调用它们的session中的事务中执行,最后该session的事务需要commit。

源代码可以从github获取:https://github.com/xiaoheike/SpringHibernateWithTransactionExample,这份源代码是spring + hibernate + spring aop 配置事务的demo工程。在完成demo过程中发现该问题,一直无法理解,一周之后恍然大悟,遂写这篇博客。

教程结束,感谢阅读。

欢迎转载,但请注明本文链接,谢谢。

2016/4/15 18:38:01

hibernate persist update 方法没有正常工作(不保存数据,不更新数据)的更多相关文章

  1. hibernate的update() 更新延迟或者无法更新,导致同个service调用存储过程执行方法不精确

    hibernate的update()方法无法更新,不报错 原因是hibernate的update方法操作的是缓存,可以flush下先. 设置缓存为false理论上也可. 在一个serivce方法里,执 ...

  2. Hibernate的注解方法的使用

    1.配置映射关系的xml方式 我们知道,Hibernate是一个典型的ORM框架,用以解决对象和关系的不匹配.其思想就是将关系数据库中表的记录映射成为对象,以对象形式展现,这样一来,就可以把对数据库的 ...

  3. [原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  4. Hibernate各保存方法之间的差 (save,persist,update,saveOrUpdte,merge,flush,lock)等一下

    hibernate保存  hibernate要保存的目的是提供一个方法,多.它们之间有许多不同之处,点击此处详细说明.使得差: 一.预赛: 在所有.阐释.供hibernate,,transient.p ...

  5. hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)等

    hibernate的保存hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,这里细说一下,以便区别:一.预备知识:在所有之前,说明一下,对于hibernate,它的对象有三种状态,t ...

  6. hibernate的各种保存方式的区别 (save,persist,update,saveOrUpdte,merge,flush,lock)

    hibernate的保存hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,这里细说一下,以便区别:一.预备知识:在所有之前,说明一下,对于hibernate,它的对象有三种状态,t ...

  7. hibernate中保存一个对象后再设置此对象的属性为什么不需要调用update方法了

    hibernate中保存一个对象后再设置此对象的属性为什么不需要调用update方法了 例如session.save(user);user.setAge(20); 原因: hibernate对象的三种 ...

  8. Hibernate HQL的update方法详解

    虽然hibernate提供了许多方法对数据库进行更新,但是这的确不能满足开发需要.现在讲解一下用hql语句对数据进行更新. 不使用参数绑定格式String hql="update User ...

  9. Hibernate的hql语句save,update方法不执行

    Hibernate的hql语句save,update方法不执行 可能出现的原因问题: 未进行事务管理 需要进行xml事务配置或者注解方式的事务配置

随机推荐

  1. linux 网卡问题 Device eth0 does not seem to be present,delaying initialization.

    Device eth0 does not seem to be present,delaying initialization. 网上搜索后才发现原因所在:原来vmware在复制了虚拟机后会自动生成一 ...

  2. μC/OS-Ⅲ中的临界段代码

    临界段代码(critical sections),也叫临界区(critical region),是指那些必须完整连续运行,不可被打断的代码段.μC/OS-Ⅲ系统中存在大量临界段代码.采用两种方式对临界 ...

  3. python cmd下运行中文乱码 策略

    如我运行一个脚本,执行后输出中文看不懂 然后呢在文件头加上 from __future__ import unicode_literals 注意:需要去掉所有字符串前的 u, 这样所有字符串均默认为u ...

  4. Android中的数据保存

    形式 Android的数据保存分为3种形式:file, SharedPreference, Database 文件 主要思想就是通过Context类中提供的openFileInput和openFile ...

  5. GDAL C# 开发出现的异常

    在使用开发C#下的GDAL时,编译时正确. 在执行 Gdal.AllRegister(); 出现异常:OSGeo.GDAL.GdalPINVOKE”的类型初始值设定项引发异常. 解决方案: 编译正常, ...

  6. PowerDesigner从Physical Data Model转Excel

    参考资料:http://www.cnblogs.com/hggc/archive/2013/10/15/3369857.html 由于有把ER图转Excel的需求,幸运地找到一个可用脚本,稍做修改完成 ...

  7. Birt使用总结

    把report放到其他服务器要重新建立Data Source ,这是配置,拷贝项目时不会同时拷贝 (1)在EXTJs中利用Report实现报表的刷新 Ext.getCmp("showview ...

  8. [转]OC与JS的交互详解

    事情的起因还是因为项目需求驱动.折腾了两天,由于之前没有UIWebView与JS交互的经历,并且觉得这次在功能上有一定的创造性,特此留下一点文字,方便日后回顾. 我要实现这样一个需求:按照本地的CSS ...

  9. 排序系列 之 直接插入排序算法 —— Java实现

    直接插入排序算法 基本思想: 把n个待排序的元素看成一个有序表和一个无序表,开始时有序表中只有一个元素,无序表中有n-1个元素:排序过程即每次从无序表中取出第一个元素,将它插入到有序表中,使之成为新的 ...

  10. Typescript中的class interface 只是在声明,其实什么也没有干!

    由于vue.js的特殊机制,初始化后给对象添加的属性是无法更新UI的. 最近结合typescript和vue进行web开发,就遇到了这样的坑. class user{ name:string; age ...