2.session生命周期(hibernate笔记)

一、持久化对象的状态

来源于网络.jpg
  • 1.瞬时对象(Transient Objects)
    或临时对象,使用new操作符初始化的对象不是立刻就持久化的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收。没有纳入Session的管理。

  • 2.持久化对象(Persistent Objects)
    持久化实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久化实例是在事务中进行操作的-它们的状态在事务结束时同数据库集进行同步。当事务提交时,通过执行sql的insert、update和delete语句把内存中的状态同步到数据库中。纳入到Session的管理,在清零缓存(脏数据检查)的时候,会和数据库同步。

  • 3.离线对象(Detached Objects)
    Session关闭后,持久化对象就变成离线对象。离线表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理。在数据库中有与之匹配的数据(和瞬时对象的主要区别,如瞬时对象就不能进行如updata操作),但是没有纳入Session的管理。

示例:(工程hibernate_session
由于Session对象是一个重量级对象,所以我们采用单例模式:
HibernateUtils.java

package cn.itcast.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
    private static SessionFactory factory;
    
    static{
        try{
            //读取配置文件
            Configuration cfg = new Configuration().configure();
            //初始化SessionFactory
            factory = cfg.buildSessionFactory();
            
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public static SessionFactory getSessionFactory(){
        return factory;
    }
    public static Session getSession(){
        //Session由工厂产生
        return factory.openSession();
    }
    public static void closeSession(Session session){
        if(session != null){
            if(session.isOpen()){
                session.close();
            }
        }
    }
}

其他文件和上个例子基本一样,我们在这里新建一个数据库hibernate_session,然后使用类ExportDB.java自动生成数据库表。

测试:
SessionTest.java

package junit.test;
import java.util.Date;
import java.util.UUID;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.model.User;
import cn.itcast.util.HibernateUtils;
public class SessionTest {
    
    @Test
    public void testSave1(){
        Session session = null;
        Transaction transaction = null;
        User user = null;
        try{
            //得到Session
            session = HibernateUtils.getSession();
            //开启事务
            transaction = session.beginTransaction();
            
            //Transient状态(临时状态)
            user = new User();
            user.setId(UUID.randomUUID().toString());
            user.setName("zhang");
            user.setPassword("1111");
            user.setCreateTime(new Date());
            user.setExpireTime(new Date());
            
            //persistent状态,当属性发生改变的时候,hibernate会自动和数据库同步
            session.save(user);
            user.setName("tom");
            session.update(user);
            transaction.commit();

        }catch(Exception e){
            e.printStackTrace();
            transaction.rollback();
        }finally{
            HibernateUtils.closeSession(session);
        }
        
        //detached状态(离线状态)
        user.setName("jack");
        try{
            session = HibernateUtils.getSession();
            session.beginTransaction();
            //persistent状态
            session.update(user);
            session.getTransaction().commit();
        }catch(Exception e){
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally{
            HibernateUtils.closeSession(session);
        }
    }
}

说明:可以看到当执行save方法之后对象变为了persistent状态,此时会发出insert语句,同时此时的状态下,如果我们修改对象,在提交事务的时候会清理缓存(或叫脏数据检查),会将新的对象存到数据库中,发出update语句。而当Session关闭之后,对象变成了离线状态,此时如果我们想修改数据库中对象的值,那么需要重新获取Session并开启事务,最后提交。

测试get方法:

@Test
    public void testReadByGetMethod1(){
        Session session = null;
        try{
            session = HibernateUtils.getSession();
            session.beginTransaction();
            
            //会立即发出查询语句,加载User对象,此时对象是persistent状态
            User user = (User) session.get(User.class, "61bb68a4-5835-4825-8fa5-a93c41f2987f");
            System.out.println("user.name = " + user.getName());
            
            //persistent状态下改变对象会自动和数据库同步
            user.setName("tom");
            session.getTransaction().commit();
        }catch(Exception e){
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally{
            HibernateUtils.closeSession(session);
        }
    }

说明:其中get方法的第二个参数是上个测试例子中存入数据的id,试验可知,当使用get方法时会立即发出查询语句,对象称为persistent状态,此时改变对象会在事务提交的时候清理缓存,发出修改语句。但是,如果我们给出的id号在数据库中不存在,那么get方法返回null。

测试load方法:

@Test
    public void testReadByLoadMethod1(){
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            //执行load方法时不会立即发出查询语句,而是在要使用此对象的时候才会发出,比如下面的打印语句
            //因为load方法实现了lazy方法(懒加载或延迟加载)
            User user = (User) session.load(User.class, "61bb68a4-5835-4825-8fa5-a93c41f2987f");
            //执行下面这条语句的时候才会发出查询语句
            System.out.println("user.name = " + user.getName());
            
            user.setName("jack");
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally{
            HibernateUtils.closeSession(session);
        }
    }

说明:这里要注意load方法和get方法的区别,load方法采用的是延迟加载,只有当要使用对象的时候才会去数据库中查询。同时如果我们给出的id号在数据库中不存在,则会抛出ObjectNotFoundException异常。

测试update方法:

@Test
    public void testUpdate1(){
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            //手动构造的detached对象
            User user = new User();
            user.setId("61bb68a4-5835-4825-8fa5-a93c41f2987f");
            user.setName("德华");
            user.setPassword("2222");
            session.update(user);
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally{
            HibernateUtils.closeSession(session);
        }
    }

说明:手动构造detached状态对象时我们给出的id必须是数据库中存在的,不然会抛出异常。同时表明detached对象可以update。虽然这里的对象是我们new出来的,但是在数据库中是有与之对应的主键的,所以是detached状态对象。

测试delete方法:

@Test
    public void testDelete1(){
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            
            User user = (User) session.load(User.class, "61bb68a4-5835-4825-8fa5-a93c41f2987f");
            session.delete(user);
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally{
            HibernateUtils.closeSession(session);
        }
        //删除之后称为Transient状态
    }

说明:这里我们可以看到从数据库中删除数据之后对象成为了Transient状态。本来对象是persistent状态,删除之后就变为Transient状态。

最后:

  • get和load方法的区别是get不支持lazy,而load支持;采用get加载数据,如果没有与之匹配的数据返回null,而load则抛出异常。
  • Transient状态的特征是:在数据库中没有与之匹配的数据,没有纳入Session的管理。
  • detached的特征是:在数据库中有与之匹配的数据,也没有纳入Session的管理。
  • get和load方法都只能根据主键进行查询,即单一查询。

二、Query接口入门

我们可以使用Query接口发送hql语句进行查询。
QueryTest.java

package junit.test;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.junit.Test;
import cn.itcast.model.User;
import cn.itcast.util.HibernateUtils;

public class QueryTest {
    
    @Test
    public void testQuery(){
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            Query query = session.createQuery("from User");
            //查询从哪里开始
            query.setFirstResult(0);
            //查询出多少条数据
            query.setMaxResults(2);
            //查询出的数据Query接口会自动帮我们存入到一个List集合中
            List<User> list = query.list();
            for(User user : list){
                System.out.println(user.getId());
                System.out.println(user.getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally{
            HibernateUtils.closeSession(session);
        }
    }
}

说明:这里我们可以使用hql语句将所有数据都查询出来,同时还可以进行分页,对于hql语句,它是针对对象的查询语句,所以对于对象名是区分大小写的。查询出来都 数据Query接口会自动帮我们存入到一个List集合中。在后面我们还会详细说明。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容