zoukankan      html  css  js  c++  java
  • Hibernate之session

    Hibernate在对资料库进行操作之前,必须先取得Session实例,相当于JDBC在对资料库操作之前,必须先取得Connection实例, Session是Hibernate操作的基础,它不是设计为执行绪安全(Thread-safe),一个Session由一个执行绪来使用。

    • 开启Session
    Session实例由SessionFactory开启获得,例如:
    Configuration config = new Configuration().configure();
    SessionFactory sessionFactory = config.buildSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    ....
    tx.commit();
    session.close();

    开 启Session不会马上取得Connection,而是在最后真正需要连接资料库进行更新或查询时才会取得Connection,如果有设定 Connection pool,则从Connection pool中取得Connection,而关闭Session时,如果有设定Connection pool,则是将Connection归还给Connection pool,而不是直接关闭Connection。

    在Hibernate中,开启一个Session会建立一个Persistence context,它可以进行快取管理、dirty check等,而所有的读取、更新、插入等动作,则是在Transaction中完成。


    • 储存资料
    透过Session,可以对资料库进行新增、删除、更新,例如使用save()新增一笔资料:
    User user = new User();
    user.setName("momor");
    user.setAge(new Integer(26));

    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    session.save(user);
    tx.commit();
    session.close();

    save() 之后,不会马上对资料库进行更新,而是在Transaction的commit()之后才会对资料库进行更新,在Transaction之间的操作要就全 部成功,要就全部失败,如果更新失败,则在资料库层面会撤消所有更新操作,然而记忆体中的持久物件是不会回复原有状态的,事实上,当 Transaction失败,这一次的Session就要马上跟着失效,放弃所有记忆体中的物件,而不是尝试以原物件再进行更新的动作。


    • 取得资料
    您使用get()或load()方法取得id为1的资料:
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    User user = (User) session.get(User.class, new Integer(1));
    tx.commit();
    session.close();

    如果未能发现相符合的资料,则get()方法会返回null,而load()方法会丢出ObjectNotFoundException,在进阶的应用中,load()方法可以返回代理(proxy)物件,在必要时才真正查询资料库取得对应资料,并可充分利用快取机制。

    在Hibernate 3中,取消了find()方法,您必须透过Query或Criteria来进行资料查询。


    • 删除资料
    接下来看看使用Session删除资料,可使用delete()删除资料:
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    User user = (User) session.get(User.class, new Integer(1));
    session.delete(user);
    tx.commit();
    session.close();
    • 更新资料
    当您在同一个Session中取出资料并封装为Persistence Object,接着更新物件状态,而后将Transaction commit,则物件上的状态更新将反应至资料库中,您无需额外进行任何的更新操作。

    如果您开启了一个Session,从资料表中取出资料显示到使用者介面上,之后关闭Session,当使用者在介面上操作完毕并按下储存时,这时您要重新开启一个Session,使用update()方法将物件中的资料更新至对应的资料表中:

    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    User user = (User) session.get(User.class, new Integer(2));
    tx.commit();
    session.close();
    ....
    user.setAge(new Integer(27));
    session = sessionFactory.openSession();   
    tx= session.beginTransaction();
    session.update(user);
    tx.commit();
    session.close();


    Session提供了一个saveOrUpdate()方法,为资料的储存或更新提供了一个统一的操作介面,藉由定义映射文件时,设定< id>标签的unsaved-value来决定什么是新的值必需,什么是已有的值必须更新:
    <id name="id" column="id" type="java.lang.Integer" unsaved-value="null">
        <generator class="native"/>
    </id>

    unsaved-value可以设定的值包括:
    • any:总是储存
    • none:总是更新
    • null:id为null时储存(预设)
    • valid:id为null或是指定值时储存

    这样设定之后,您可以使用Session的saveOrUpdate()方法来取代update()方法。


    • 合并状态
    以这边的例子来说:
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    User user1 = (User) session.get(User.class, new Integer(2));
    tx.commit();
    session.close();
    ....
    user1.setAge(new Integer(27));

    session = sessionFactory.openSession();   
    tx= session.beginTransaction();
    User user2 = (User) session.get(User.class, new Integer(2)); // 同一个id
    // user1 == user2 为 false
    session.update(user1); // 丢出NonUniqueObjectException
    tx.commit();
    session.close();


    在 进行update()之前,您就先从资料库中取得另一笔资料,之后再尝试更新user1,由于目前的Persistence context已载入一笔资料,并有同一个id的User 实例了,同一个Persistence context不会有两个相同id的物件实例,因此丢出NonUniqueObjectException。

    就这边的例子来说,您应该使用merge()而不是update():
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    User user1 = (User) session.get(User.class, new Integer(2));
    tx.commit();
    session.close();
    ....
    user1.setAge(new Integer(27));

    session = sessionFactory.openSession();   
    tx= session.beginTransaction();
    User user2 = (User) session.get(User.class, new Integer(2)); // 同一个id
    User user3 = (User) session.merge(user1);
    // user1 == user2 为 false
    // user2 == user3 为 true
    tx.commit();
    session.close();


    merge()会将user1与user2的状态合并,传回的物件实例就是user2原先所参考的实例。

  • 相关阅读:
    go-zero尝试运行输出hello-world
    grpc客户端 服务端测试
    protobuf序列化
    protobuff3语法详情
    【转】普通程序员如何转向AI方向
    深度学习微软 azure-云服务器组 centos特殊内核版本 gpu NVIDIA 驱动及CUDA 11.0安装
    分享一个主要用于nas场景的集成了迅雷,百度网盘等软件的docker ubuntu vnc镜像-适用于x86环境
    以spark sql 维护spark streaming offset
    打通es及lucene应用,lucene应用es Query,应用完整的es query
    打通es及lucene应用,lucene应用es Query,结合非queryString查询(二)
  • 原文地址:https://www.cnblogs.com/batys/p/2231228.html
Copyright © 2011-2022 走看看