void |
update(Object object) Update the persistent instance with the identifier of the given detached instance. |
还是通过例子来看看
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方法的描述:
Object |
merge(Object object) Copy the state of the given object onto the persistent object with the same identifier. |
执行update7,结果如下:
以上即为hibernate的Session的update相关内容,值得一提的是,对于上面提到的防止修改其他属性的3种方法,在实际的使用中多采用第三种方法,即使用HQL实现特定的修改,当然可能还会结合HQL查询等。