hibernate persist update 方法没有正常工作(不保存数据,不更新数据)

简介: 工程结构问题描述在工程中通过spring aop的方式配置事务,使用hibernate做持久化。在代码实现中使用hibernate persit()方法插入数据到数据库,使用hibernate update()方法更新数据。

工程结构

工程结构

问题描述

在工程中通过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

目录
相关文章
|
2月前
|
Java 数据库连接 API
解锁高效开发秘籍:深入探究 Hibernate 如何优雅处理一对多与多对多关系,让数据映射再无烦恼!
【9月更文挑战第3天】Hibernate 是 Java 领域中最流行的 ORM 框架之一,广泛用于处理实体对象与数据库表之间的映射。尤其在处理复杂关系如一对多和多对多时,Hibernate 提供了丰富的 API 和配置选项。本文通过具体代码示例,展示如何使用 `@OneToMany`、`@JoinColumn`、`@ManyToMany` 和 `@JoinTable` 等注解优雅地实现这些关系,帮助开发者保持代码简洁的同时确保数据一致性。
45 4
|
3月前
|
Java 数据库连接 数据库
从零到精通:揭秘 Hibernate 构建持久层服务的全过程,你离数据持久化大师还有多远?
【8月更文挑战第31天】本文详细介绍了如何从零开始使用 Hibernate 构建一个持久层服务。首先,通过在 Maven 项目中添加必要的依赖,确保项目具备使用 Hibernate 的条件。接着,配置 `hibernate.cfg.xml` 文件以连接 MySQL 数据库,并设置了基本属性。然后定义了一个简单的 `User` 实体类及其映射关系。此外,还创建了一个 `HibernateUtil` 工具类来管理 `SessionFactory`。
38 0
|
3月前
|
Java 数据库连接 数据库
强强联手!JSF 与 Hibernate 打造高效数据访问层,让你的应用如虎添翼,性能飙升!
【8月更文挑战第31天】本文通过具体示例详细介绍了如何在 JavaServer Faces (JSF) 应用程序中集成 Hibernate,实现数据访问层的最佳实践。首先,创建一个 JSF 项目并在 Eclipse 中配置支持 JSF 的服务器版本。接着,添加 JSF 和 Hibernate 依赖,并配置数据库连接池和 Hibernate 配置文件。然后,定义实体类 `User` 和 DAO 类 `UserDAO` 处理数据库操作。
58 0
|
3月前
|
Java 数据库连接 数据库
|
3月前
|
缓存 Java 数据库连接
|
3月前
|
Java 数据库连接 API
|
3月前
|
Java 数据库连接 应用服务中间件
|
6月前
|
SQL 缓存 Java
框架分析(9)-Hibernate
框架分析(9)-Hibernate
|
10天前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
9 1