先看写代码的方法:


@Test

    public void testUpdate3() {



        Teacher t = new Teacher();

        t.setId(1);//指定了主键也可以直接更新

        t.setName("zhanglaoshi");


        Session session2 = sessionFactory.getCurrentSession();

        session2.beginTransaction();

        session2.update(t);


        session2.getTransaction().commit();

    }


    @Test

    public void testUpdate4() {



        Session session = sessionFactory.getCurrentSession();

        session.beginTransaction();

        Teacher t = (Teacher)session.get(Teacher.class, 1);

        t.setName("zhangsan2");

        session.getTransaction().commit();//提交的时候会自动检查和数据库中的数据一样不一样,如果有就会自动进行更新。

    }


只写代码并不好使,因为他们更新的时候不会只更新name,会把所有字段都更新一遍,就算和原来数据一致也会更新。这导致效率降低很多。为了解决这一情况,我们可以做一些修改。有以下几种方式:



方式1(不推荐)

修改注解,将不打算参与更新的字段的get方法上加上这么一段:@Column(updatable=false)。

关于持久化相关注解的更多内容可以参看jee api的javax.persistence相关内容。


方式2(不推荐)

修改映射关系xml,<property name="age" update="false" />

关于持久化映射关系xml配置的更多内容可以参看hibernate的doc文档​(关于本例,参考目录hibernate-release-4.2.8.Final\documentation\manual\en-US\html_single中的5. Basic O/R Mapping---5.1. Mapping declaration---5.1.4. Property---5.1.4.2 )


方式3

在hbm配置文件上加上下面的黑体行

<hibernate-mapping>

    <class name="com.test.hibernate.Student" dynamic-update="true">

如此,在同一个session中更新数据就可以只更新变更了的数据。

如果想跨session只更新修改了的字段,可以手动让hibernate去比较,​session.merge​(要比较的从别的session里取出来后修改过的对象)。但是为了作比较hibernate会自动先查询一遍数据库。


但是用注解怎么实现呢?????用注解能实现吗????难道为了只更新修改的字段我们就要把映射关系都在xml文件里实现而放弃注解?这个我暂时也不知道,如果你看到了就自己查去吧。。


方式4(推荐

使用HQL(EJBQL)自己写一条类似sql而非sql的语句

@Test

public void testUpdate7() {



    Session session = sessionFactory.getCurrentSession();

    session.beginTransaction();

    ​Query q​ = session.createQuery("update ​Student​ ​s​ set s.name='z5' where s.id = 1");//这个org.hibernate.Query对象类似于jdbc的statement,这里update的不是表而是对象s,所以指明Student类用了大写的S

    ​q.executeUpdate();

    session.getTransaction().commit();


}