Hibernate学习5—Hibernate操作对象2

第二节:Session 常用方法讲解                                        

2)load和get()方法:

数据库中不存在与OID 对应的记录,Load()方法会抛出异常:

load方法默认采用延迟加载,load出来的对象是一个代理类。开始并没有值,只有用到它的属性等的时候,才会去发出sql语句。

而get方法一开始就发出sql语句。

如果说获取一个对象是为了删除它,可以用load,因为只要获取个引用就行了。

如果说获取一个对象是为了访问它的属性,建议用get;

@Test
    public void testLoadClass() {
        Class c = (Class) session.load(Class.class, Long.valueOf(2));    //class id为2的不存在,抛出异常
        System.out.println(c.getStudents());
    }

    @Test
    public void testGetClass() {
        Class c = (Class) session.get(Class.class, Long.valueOf(2));    //class id为2的不存在,打印null
        System.out.println(c);
    }

2)update:

@Test
    public void testUpdateClass(){
        Session session1=sessionFactory.openSession();
        session1.beginTransaction();
        Class c=(Class)session1.get(Class.class, Long.valueOf(1));
        session1.getTransaction().commit();
        session1.close();

        Session session2=sessionFactory.openSession();
        session2.beginTransaction();
        c.setName("08计算机本科2");
        session2.update(c);
        session2.getTransaction().commit();
        session2.close();
    }

补充:

update方法:
1.更新一个detached的对象;
2.更新一个transient的会报错;但是更新自己设定id的transient对象可以(数据库有对应记录);
3.上面的,比如更新teacher,我们只是想更新name,但是它会把所有的属性都更新一遍;这样会造成效率低,比如有个字段特别长...
4.持久化的对象,只要改变了它的内容,session在提交或者关闭的时候,会检查缓存中的和数据库中的是否一致,如果不一致,自动的发update语句;
但是也和上面一样,虽然只改了一个字段,也会更新所有的字段;
5.能不能做到:哪个字段改了才更新,哪个字段没改,哪个字段就不更新?怎么做:
a.xml配置:
<class name="com.cy.Teacher" dynamic-update="true">.....</class>
b.跨session更新的问题:
@Test
    public void testUpdate5() {

        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        Student s = (Student)session.get(Student.class, 1);
        s.setName("zhangsan5");
        session.getTransaction().commit();

        s.setName("z4");

        Session session2 = sessionFactory.getCurrentSession();
        session2.beginTransaction();
        session2.update(s);
        session2.getTransaction().commit();
    }
首先student对象被我们放到了缓存里,s.setName("zhangsan3"),Hibernate会检查哪些属性改过了,这时候生成sql语句,由于使用了dynamic-update,它就只更新name这个字段了;
session提交之后,关闭了。缓存中的这个对象没了。但是内存中Student s这个对象还在,是detached状态的。
这个对象又setName("z4"),第二个session2来了,这个session2里面没有s这个对象,然后update(s),它有没有地方来比较哪个字段改过了?
没有,它没法将内存中的s和session2缓存中的s来比较,所以update(s),发出的sql会更新全部的字段;

c.根据上面,如果想跨session,只更新改过的字段,怎么做:
将上面的update改为merge:
@Test
    public void testUpdate6() {

        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        Student s = (Student)session.get(Student.class, 1);
        s.setName("zhangsan6");
        session.getTransaction().commit();

        s.setName("z4");

        Session session2 = sessionFactory.getCurrentSession();
        session2.beginTransaction();
        session2.merge(s);
        session2.getTransaction().commit();
    }
merge:把这个对象给我合并到数据库;原来没改的内容还需要合并吗?不需要。
merge的时候,它怎么检查哪些字段改过哪些字段没改过呢?缓存中又没有,只能从数据库中load一次,所以它在update之前先发出了一条select语句,然后再比较你给我的对象和我load的对象在什么地方不同,再重新发update语句。

d:dynamic-update这种xml配置,对应的JPA Annotation没有对应的属性;
在真正开发中建议使用HQL:
session.createQuery("update Student s set s.name=‘z5‘ where s.id = 1");
@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");
        q.executeUpdate();
        session.getTransaction().commit();

    }

3)saveOrUpdate:

saveOrUpdate(): 如果传的是一个临时对象,则执行save方法;如果传的是游离对象,就调用update方法;

@Test
    public void testSaveOrUpdateClass(){
        Session session1=sessionFactory.openSession();
        session1.beginTransaction();
        Class c=(Class)session1.get(Class.class, Long.valueOf(1));
        session1.getTransaction().commit();
        session1.close();

        Session session2=sessionFactory.openSession();
        session2.beginTransaction();
        c.setName("08计算机本科3");

        Class c2=new Class();
        c2.setName("09计算机本科3");
        session2.saveOrUpdate(c);        //c是游离状态,执行update
        session2.saveOrUpdate(c2);        //c2临时状态,执行save
        session2.getTransaction().commit();
        session2.close();

        /**
         * 发出的sql:
         *     Hibernate: select class0_.classId as classId1_0_0_, class0_.className as classNam2_0_0_ from t_class class0_ where class0_.classId=?
            Hibernate: insert into t_class (className) values (?)
            Hibernate: update t_class set className=? where classId=?
         */
    }

4)merge:

有的时候update会报错:session中有两个对象,拥有相同的OID(比如OID为1),更新的时候,session发现缓存中你已经有一个OID为1的对象了,所以更新的时候就报错了;

比如:

@Test
    public void testUpdateClass2(){
        Session session1=sessionFactory.openSession();
        session1.beginTransaction();
        Class c=(Class)session1.get(Class.class, Long.valueOf(1));
        session1.getTransaction().commit();
        session1.close();

        Session session2=sessionFactory.openSession();
        session2.beginTransaction();
        Class c2=(Class)session2.get(Class.class, Long.valueOf(1));
        c.setName("08计算机本科3");

        session2.update(c);
        session2.getTransaction().commit();
        session2.close();
    }     

执行报错:

为了解决这个问题,多了个merge方法,合并对象:

更新的时候如果发现这个对象OID和session缓存中另一个对象OID重合了,调用merge方法就会合并,把这两个对象的属性合并,然后更新;

@Test
    public void testMergeClass(){
        Session session1=sessionFactory.openSession();
        session1.beginTransaction();
        Class c=(Class)session1.get(Class.class, Long.valueOf(1));
        session1.getTransaction().commit();
        session1.close();

        Session session2=sessionFactory.openSession();
        session2.beginTransaction();

        Class c2=(Class)session2.get(Class.class, Long.valueOf(1));
        c.setName("08计算机本科4");

        session2.merge(c);

        session2.getTransaction().commit();
        session2.close();
    }

5)delete:

@Test
    public void testDeleteStudent(){
        Student student=(Student)session.load(Student.class, Long.valueOf(1));
        session.delete(student);
        session.getTransaction().commit();
        session.close();
    }

因为删除的时候,只需要获得它的引用,这里使用了load延迟加载就行了。不需要使用get了,因为不需要获取它里面的属性。

session.delete的时候还没有真正删除,提交事务的时候,才同步数据库,真的删了。

时间: 2024-10-06 15:24:16

Hibernate学习5—Hibernate操作对象2的相关文章

Hibernate学习之——Hibernate环境搭建

之前在写关于安卓闹钟的教程,写了一半就没后一半了,其实自己也没做好,在校外实习,校内毕业实习又有任务,只能先放放了,等毕业实习结束之后,在继续安卓闹钟开发之旅,相信这个时间不会很久的.现在毕业实习用到的SSH框架(Struts+Spring+Hibernate),自己没有多少时间去好好学习,但是还是想把学到的东西记录下来. 一.Hibernate简介 1.什么是Hibernate? Hibernate是数据持久层的一个轻量级框架.数据持久层的框架有很多比如:iBATIS,myBatis,Nhib

Hibernate学习0.Hibernate入门

Hibernate是什么 面向java环境的对象/关系数据库映射工具. 1.开源的持久层框架. 2.ORM(Object/Relational Mapping)映射工具,建立面向对象的域模型和关系数据模型之间的映射. 3.连接java应用和数据库的中间件. 4.对JDBC进行封装,负责java对象的持久化. 5.在分层结构中处于持久化层,封装对数据库的访问细节,使业务逻辑层更专注于实现业务逻辑 Hibernate作用 Hibernate是Java应用和关系数据库之间的桥梁,它负责Java对象和关

Hibernate学习之Hibernate流程

Hibernate的核心组件 在基于MVC设计模式的JAVA WEB应用中,Hibernate可以作为模型层/数据访问层.它通过配置文件(hibernate.properties或hibernate.cfg.xml)和映射文件(***.hbm.xml)把JAVA对象或PO(Persistent Object,持久化对象)映射到数据库中的数据库,然后通过操作PO,对数据表中的数据进行增,删,改,查等操作.除配置文件,映射文件和持久化类外,Hibernate的核心组件包括以下几部分:a)Config

Hibernate学习5—Hibernate操作对象

第一节:Hibernate 中四种对象状态 删除状态:处于删除状态的Java 对象被称为删除对象.比如说session delete一个对象,这个对象就不处于session缓存中了, 已经从session的缓存中移出来了,只要提交事务的话,对应的数据库记录也会被删除. 游离状态:比如说session被关闭了,这里面的对象就变为游离状态了,游离状态和删除状态中的对象,如果不用的话,会被垃圾收集器回收. 几种状态之间的转化: 例子: public class StudentTest { public

hibernate学习(5)——对象状态与一级缓存

1.对象状态 1.1   状态介绍 hibernate 规定三种状态:瞬时态.持久态.脱管态 瞬时态:transient,session没有缓存对象,数据库也没有对应记录.没有与hibernate关联,与数据库中的记录没有产生关联. OID特点:没有值 持久态:persistent,session缓存对象,数据库最终会有记录.(事务没有提交)与hibernate关联,对象有id OID特点:有值 脱管态:detached,session没有缓存对象,数据库有记录.没有与hibernate关联,对

【Hibernate学习】——级联操作

级联策略:负责控制关联两端对象到对象的级联关系的操作,包括更新.删除等,也就是说对一个对象进行更新.删除时,其它对象也受影响,比如我删除一个对象,那么跟它是多对一关系的对象也全部被删除. 在前面用了抓取策略之后,后面试了一下级联操作的注解:cascadeType.MERGE方式 @OneToOne(cascade={CascadeType.MERGE}) @JoinColumn(name="company_id") publicCompany getCompany() { return

Hibernate学习之hibernate执行顺序

Hibernate 执行的顺序如下:  (1) 生成一个事务的对象,并标记当前的 Session 处于事务状态(注:此时并未启动数据库级事务).  (2) 应用使用 s.save 保存对象,这个时候 Session 将这个对象放入 entityEntries ,用来标记对象已经和当前的会话建立了关联,由于应用对对象做了保存的操作, Session 还要在 insertions 中登记应用的这个插入行为(行为包括:对象引用.对象 id . Session .持久化处理类).  (3) s.evic

Hibernate学习之hibernate状态

hibernate有三种状态,transient(瞬时状态),persistent(持久化状态)以及detached(离线状态),瞬时状态就是刚new出来一个对象,还没有被保存到数据库中,持久化状态就是已经被保存到数据库中,离线状态就是数据库中有,但是session中不存在该对象. 1 session = HibernateUtil.openSession(); 2 session.beginTransaction(); 3 Person person = new Person(); 4 per

Hibernate学习10——Hibernate 查询方式

本章主要是以查询Student的例子: Student.java: package com.cy.model; public class Student { private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name;