hibernate的Session的update方法

来源:互联网 发布:他趣是什么软件 编辑:程序博客网 时间:2024/06/09 19:51
查看hibernate的API文档,其中Session的update方法说明如下:

 voidupdate(Object object)
          Update the persistent instance with the identifier of the given detached instance.意思大概是detached使用update方法通过Id更新为persistent

还是通过例子来看看

1.用之前的Teacher

package com.baosight.model;import javax.persistence.Column;import javax.persistence.EmbeddedId;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.IdClass;import javax.persistence.SequenceGenerator;import javax.persistence.TableGenerator;/** * <p>Title: </p> * <p>Description:Teacher </p> * <p>Company: </p>  * @author yuan  * @date 2016-4-10 下午12:32:46*/@Entity@TableGenerator(name="tableGEN",table="table_gen",pkColumnName="pk_key",valueColumnName="pk_value",pkColumnValue="teacher",allocationSize=1)@SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB")//@IdClass(value=TeacherPK.class)public class Teacher {private String id;private String name;private String title;//private TeacherPK pk;@Id@GeneratedValue//auto//@GeneratedValue(strategy=GenerationType.TABLE,generator="tableGEN")//@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="teacherSEQ")public String getId() {return id;}public void setId(String id) {this.id = id;}//@Idpublic String getName() {return name;}public void setName(String name) {this.name = name;}@Column(updatable=false)//不参与自动更新public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}//@EmbeddedId//@Id/*public TeacherPK getPk() {return pk;}public void setPk(TeacherPK pk) {this.pk = pk;}*/}
2.JUnit测试类为TeacherTest.java

package com.baosight.model;import static org.junit.Assert.*;import javax.persistence.Column;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.AnnotationConfiguration;import org.hibernate.cfg.Configuration;import org.junit.AfterClass;import org.junit.BeforeClass;import org.junit.Test;/** * <p>Title:TecherTest </p> * <p>Description:TODO </p> * <p>Company: </p>  * @author yuan  * @date 2016-4-13 下午10:32:17*/public class TeacherTest {private static SessionFactory sf = null;@BeforeClasspublic static void beforeClass(){// 读取配置文件Configuration cfg = new AnnotationConfiguration();// 得到session工厂sf = cfg.configure().buildSessionFactory();}@Testpublic void testSave() {// 教师测试类Teacher t = new Teacher();t.setName("t1");t.setTitle("中级");System.out.println("transient状态下id============="+t.getId());// 得到sessionSession session = sf.openSession();// 开启事务session.beginTransaction();// session执行savesession.save(t);System.out.println("persistent状态下id============="+t.getId());// 事务提交session.getTransaction().commit();// 关闭sessionsession.close();System.out.println("ditached状态下id============="+t.getId());}@Testpublic void testDelete() {// 教师测试类Teacher t = new Teacher();t.setName("t1");t.setTitle("中级");System.out.println("transient状态下id============="+t.getId());// 得到sessionSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();// session执行savesession.save(t);System.out.println("persistent状态下id============="+t.getId());// 事务提交session.getTransaction().commit();// 关闭sessionSystem.out.println("ditached状态下id============="+t.getId());//删除Session session2 = sf.getCurrentSession();// 开启事务session2.beginTransaction();// session执行session2.delete(t);System.out.println("persistent状态下id============="+t.getId());// 事务提交session2.getTransaction().commit();// 关闭sessionSystem.out.println("ditached状态下id============="+t.getId());}@Testpublic void testDelete2() {// 教师测试类Teacher t = new Teacher();t.setId("24");System.out.println("transient状态下id============="+t.getId());//删除Session session2 = sf.getCurrentSession();// 开启事务session2.beginTransaction();// session执行session2.delete(t);System.out.println("persistent状态下id============="+t.getId());// 事务提交session2.getTransaction().commit();// 关闭sessionSystem.out.println("ditached状态下id============="+t.getId());}@Testpublic void testLoad() {//使用代理,只有使用到查询对象时才会打印sqlSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();// session执行Teacher t = (Teacher) session.load(Teacher.class, "1");//打印代理对象名称System.out.println(t.getClass().getName());//System.out.println(t);//System.out.println("id============="+t.getId());// 事务提交session.getTransaction().commit();// 关闭session//System.out.println("id============="+t.getId());}@Testpublic void testGet() {//直接从数据库查询,会打印sqlSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();// session执行Teacher t = (Teacher) session.get(Teacher.class, "1");System.out.println(t.getClass().getName());//System.out.println(t);//System.out.println("id============="+t.getId());// 事务提交session.getTransaction().commit();// 关闭session//System.out.println("id============="+t.getId());}@Testpublic void testUpdate1() {//直接从数据库查询,会打印sqlSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();// session执行Teacher t = (Teacher) session.get(Teacher.class, "1");// 事务提交session.getTransaction().commit();//将detached通过update变为persistent//修改t.setName("zhangsan");Session session2 = sf.getCurrentSession();// 开启事务session2.beginTransaction();// session执行session2.update(t);// 事务提交session2.getTransaction().commit();}@Testpublic void testUpdate2() {// 教师测试类Teacher t = new Teacher();t.setName("zhangsan");//transient没有Id无法进行update操作//修改Session session2 = sf.getCurrentSession();// 开启事务session2.beginTransaction();// session执行session2.update(t);// 事务提交session2.getTransaction().commit();}@Testpublic void testUpdate3() {// 教师测试类Teacher t = new Teacher();t.setId("1");t.setName("lisi");//transient有Id可以进行update操作//修改Session session2 = sf.getCurrentSession();// 开启事务session2.beginTransaction();// session执行session2.update(t);// 事务提交session2.getTransaction().commit();}@Testpublic void testUpdate4() {// 直接从数据库查询,会打印sqlSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();// session执行Teacher t = (Teacher) session.get(Teacher.class, "1");//对persistent直接set也能执行//测试@Column(updatable=false)指定age不参与修改t.setName("wangwu");// 事务提交session.getTransaction().commit();}@Testpublic void testUpdate5() {// 学生测试类// 得到sessionSession session = sf.openSession();// 开启事务session.beginTransaction();// session执行Student s = (Student) session.get(Student.class, "1");//xml文件<property中update="false"指定age不参与修改//或者在class使用dynamic-update="true"说明只修改变化的列s.setName("lisi3");// 事务提交session.getTransaction().commit();// 关闭sessionsession.close();}@Testpublic void testUpdate6() {// 直接从数据库查询,会打印sqlSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();// session执行Student s = (Student) session.get(Student.class, "1");// 对persistent直接set也能执行// 测试@Column(updatable=false)指定age不参与修改s.setName("lisi");// 事务提交session.getTransaction().commit();//detached执行saves.setName("zhangsan");// 直接从数据库查询,会打印sqlSession session1 = sf.getCurrentSession();// 开启事务session1.beginTransaction();// session执行session1.update(s);// 事务提交session1.getTransaction().commit();}@Testpublic void testUpdate7() {// 直接从数据库查询,会打印sqlSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();// session执行Student s = (Student) session.get(Student.class, "1");// 对persistent直接set也能执行// 测试@Column(updatable=false)指定age不参与修改s.setName("lisi");// 事务提交session.getTransaction().commit();//detached执行saves.setName("zhangsan");// 直接从数据库查询,会打印sqlSession session1 = sf.getCurrentSession();// 开启事务session1.beginTransaction();// session执行session1.merge(s);// 事务提交session1.getTransaction().commit();}@Testpublic void testUpdate8() {// 直接从数据库查询,会打印sqlSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();//通过HQl来实现特定的修改Query q = session.createQuery("update Student s set s.name='lisi' where s.id='1'");q.executeUpdate();// 事务提交session.getTransaction().commit();}@AfterClasspublic static void afterClass(){// 关闭session工厂sf.close();}}

3.测试结果如下:

update1方法用来测试detached执行update的效果,发现是可以执行的,但是,存在修改1个字段其它字段也被修改的问题,结果如下:




update2用来测试transient执行update的问题,由于未设定Id,所以执行失败,结果如下:


update3为transient设定了Id,可以正常执行,结果如下:

update4用来测试对于persistent直接使用set属性进行修改,能够执行,结果如下:



4.从以上的测试可以发现一个问题,就是对1个属性的修改可能会影响到其他的属性,为了解决这一问题有三种方案:

一是使用annotation的@Column(updatable=false),放在不想被自动修改的属性的get方法上面,比如上面使用在getTitle,对于使用xml的需要修改<property中update="false"指定该属性不不参与自动修改

二是对于xml使用在class使用dynamic-update="true"说明只修改变化的列

三是通过HQl来实现特定的修改

5.使用annotation的@Column(updatable=false)

修改Teacher的getTitle,使用注解

@Column(updatable=false)public String getTitle() {return title;}
重新执行update4,结果如下:

6.对于使用xml的需要修改<property中update="false"指定该属性不不参与自动修改

使用之前的Student

package com.baosight.model;import javax.persistence.Column;/** * <p>Title: </p> * <p>Description:Student </p> * <p>Company: </p>  * @author yuan  * @date 2016-4-10 下午12:32:46*/public class Student {private String id;private String name;//private StudentPK pk;private int age;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}/*public StudentPK getPk() {return pk;}public void setPk(StudentPK pk) {this.pk = pk;}*/}
修改Student.hbm.xml,使用<property中update="false"

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.baosight.model"><class name="Student" dynamic-update="true"><id name="id" ><generator class="uuid"></generator></id><!-- <composite-id name="pk" class="StudentPK"><key-property name="id"></key-property><key-property name="name"></key-property></composite-id> --><property name="name"></property><property name="age"></property><!-- <property name="age" update="false"></property> --></class></hibernate-mapping>
运行update5,结果如下:

7.对于xml使用在class使用dynamic-update="true"说明只修改变化的列,xml见上面

运行update5,结果如下:



8.通过HQL来实现特定的修改

直接通过执行特定的HQL来实现特定的修改

比如本例中的update8,方法如下:

@Testpublic void testUpdate8() {// 直接从数据库查询,会打印sqlSession session = sf.getCurrentSession();// 开启事务session.beginTransaction();//通过HQl来实现特定的修改Query q = session.createQuery("update Student s set s.name='lisi' where s.id='1'");q.executeUpdate();// 事务提交session.getTransaction().commit();}
执行结果如下:

9.执行update6,结果如下:

发现persistent的update只修改变化的属性,而detached则可能修改其他属性,针对这一情况,可以考虑使用merge

10.merge的使用

hibernate的API文档中对Session的merge方法的描述:

 Objectmerge(Object object)
          Copy the state of the given object onto the persistent object with the same identifier.
将给定对象的状态复制到具有相同标识符的持久对象上。会先做查询再做修改,类似于persistent的update

执行update7,结果如下:


以上即为hibernate的Session的update相关内容,值得一提的是,对于上面提到的防止修改其他属性的3种方法,在实际的使用中多采用第三种方法,即使用HQL实现特定的修改,当然可能还会结合HQL查询等。


1 0
原创粉丝点击