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集合中。在后面我们还会详细说明。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容