hibernate的Session的update方法

查看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;
	}
//	@Id
	public 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;
	@BeforeClass
	public static void beforeClass(){
		// 读取配置文件
		Configuration cfg = new AnnotationConfiguration();
		// 得到session工厂
		sf = cfg.configure().buildSessionFactory();
	}
	@Test
	public void testSave() {
		// 教师测试类
		Teacher t = new Teacher();
		t.setName("t1");
		t.setTitle("中级");

		System.out.println("transient状态下id============="+t.getId());
		// 得到session
		Session session = sf.openSession();
		// 开启事务
		session.beginTransaction();
		// session执行save
		session.save(t);
		System.out.println("persistent状态下id============="+t.getId());
		// 事务提交
		session.getTransaction().commit();
		// 关闭session
		session.close();
		System.out.println("ditached状态下id============="+t.getId());
	}
	@Test
	public void testDelete() {
		// 教师测试类
		Teacher t = new Teacher();
		t.setName("t1");
		t.setTitle("中级");
		
		System.out.println("transient状态下id============="+t.getId());
		// 得到session
		Session session = sf.getCurrentSession();
		// 开启事务
		session.beginTransaction();
		// session执行save
		session.save(t);
		System.out.println("persistent状态下id============="+t.getId());
		// 事务提交
		session.getTransaction().commit();
		// 关闭session
		System.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();
		// 关闭session
		System.out.println("ditached状态下id============="+t.getId());
	}
	@Test
	public 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();
		// 关闭session
		System.out.println("ditached状态下id============="+t.getId());
	}
	@Test
	public void testLoad() {
		//使用代理,只有使用到查询对象时才会打印sql
		Session 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());
	}
	@Test
	public void testGet() {
		//直接从数据库查询,会打印sql
		Session 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());
	}
	@Test
	public void testUpdate1() {
		//直接从数据库查询,会打印sql
		Session 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();
		
	}
	@Test
	public 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();
		
	}
	@Test
	public 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();
		
	}
	@Test
	public void testUpdate4() {
		// 直接从数据库查询,会打印sql
		Session 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();
		
	}
	@Test
	public void testUpdate5() {
		// 学生测试类

		// 得到session
		Session 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();
		// 关闭session
		session.close();
		
	}
	@Test
	public void testUpdate6() {
		// 直接从数据库查询,会打印sql
		Session 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执行save
		s.setName("zhangsan");
		// 直接从数据库查询,会打印sql
		Session session1 = sf.getCurrentSession();
		// 开启事务
		session1.beginTransaction();
		// session执行
		session1.update(s);
		// 事务提交
		session1.getTransaction().commit();
		
	}
	@Test
	public void testUpdate7() {
		// 直接从数据库查询,会打印sql
		Session 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执行save
		s.setName("zhangsan");
		// 直接从数据库查询,会打印sql
		Session session1 = sf.getCurrentSession();
		// 开启事务
		session1.beginTransaction();
		// session执行
		session1.merge(s);
		// 事务提交
		session1.getTransaction().commit();
		
	}
	@Test
	public void testUpdate8() {
		// 直接从数据库查询,会打印sql
		Session 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();
		
	}
	@AfterClass
	public 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,方法如下:

@Test
	public void testUpdate8() {
		// 直接从数据库查询,会打印sql
		Session 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查询等。


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值