Hibernate框架(二)
(接上篇)
四.Hibernate持久化对象
Hibernate框架对JDBC做了轻量级的封装,使用Hibernate对数据进行操作时,不必再写繁琐的JDBC代码,而是完全以面向对象的思维模式,通过Session接口对数据进行增删改查操作,其使用方法十分简单,但是要注意对Hibernate事务的控制,下面是Hibernate持久化对象的流程:
Hibernate持久化对象的流程

1.编写Hibernate的初始化类
Hibernate的运行离不开Session对象,而Session对象依赖于SesssionFactory对象。
1.1SessionFactory的创建过程
Hibernate通过Configuration类来加载Hibernate配置信息,主要通过调用Configuration对象的configure方法实现。默认情况下加载classpath 下的hibernate.cfg.xml文件。

    Configuration cfg= new Configuration().configure();

加载完毕后通过Configuration对象的buildSessionFactory()方法创建SessionFactory对象:

    SessionFactory factory =cfg.buildSessionFactory();

1.2 并编写Hibernate初始化类


package com.shxt.tools;

import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

public class HibernateUtil {
    private static SessionFactory factory = null;
    static {
        try {
            Configuration cfg = new Configuration().configure();// 加载配置文件
            factory = cfg.buildSessionFactory();// 实例化SessionFactory
        } catch (HibernateException e) {
            e.printStackTrace();
        }
    }

    public static Session getSession() {// 获取Session对象的方法
        Session session = (factory != null) ? factory.openSession() : null;
        return session; // SessionFactory不为空就开启SessionFactory
    }

    public static SessionFactory getSessionFactory() {
        return factory;
    }

    public static void closeSession(Session session) {// 关闭session方法
        if (session != null) {
            if (session.isOpen()) {
                session.close();// 关闭session
            }
        }
    }
}

SessionFactory对象是重量级的对象,创建过程比较耗时与占用资源,可以将这个视为工厂,需要时调用一个即可。
注意:Session对象并不是线程安全的,在涉及多线程时,应该借助于ThreadLocal对象进行处理。

2.添加数据
添加数据用到Session接口的save方法,入口参数为object类型,代表持久化对象。语法格式如下:

public Serializabale save(Object obj) throws HibernateException
下面以添加药品信息为例:


public class SaveMedicine {
    public static void main(String[] args) {
        Session session = null;
        try {
            session = HibernateUtil.getSession();// 获取session
            session.beginTransaction();// 开启事务
            Medicine medicine = new Medicine();// 实例化对象并操作
            medicine.setName("XX感冒药");
            medicine.setPrice(28.00);
            medicine.setFactoryAdd("XX制药厂");
            medicine.setDescription("最新感冒药");
            session.save(medicine);// 保存药品对象
            session.getTransaction().commit();// 提交事务
        } catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();// 出错将回滚事务
        } finally {
            HibernateUtil.closeSession(session);// 关闭Session对象
        }
    }
}

Medicine的三种状态:
Transient(瞬时状态)=》Persistant(持久状态)=》Detached(托管状态)
Save()方法前 ====》 commit()后 ====》关闭session后

3.删除数据
删除数据的对象并不在session的管理当中,所以要先将对象转化成持久化状态才能删除,代码如下:

public class DeleteMedicine {
    public static void main(String[] args) {
        Session session = null;
        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            Medicine medicine = (Medicine) session.load(Medicine.class, 1);
            session.delete(medicine);
            session.getTransaction().commit();
        } catch (Exception e) {
            session.getTransaction().rollback();
        } finally {
            HibernateUtil.closeSession(session);
        }
    }
}

4.修改数据(自动更新/手动更新)
自动更新:当实例处在持久化的状态中,对于它所发生的任何更新操作,Hibernate在更新缓存时都会更新,此时Hibernate会发出两条SQL语句。
手动更新:Session接口提供了update()方法,可以调用此方法来更新数据,此时Hibernate会发出一条SQL语句,但是对于没有设置值的属性,数据表中将会同步为空值,应该谨慎使用,代码如下:

public class UpdateMedicine {
    public static void main(String[] args) {
        Session session = null;
        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            Medicine medicine = (Medicine) session.load(Medicine.class, 1);
            medicine.setName("新感冒胶囊");
            medicine.setPrice(18.88);
            /*
             * medicine.setId(1); medicine.setName("xxxxx");
             * session.update(medicine);这是手动更新的代码
             */
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        } finally {
            HibernateUtil.closeSession(session);
        }
    }
}

5.查询数据
Session接口提供了两个加载数据的方法,分别为get()和load()方法,都用于加载数据,但是二者之间存在一定的区别:get()方法返回实际对象,load()方法返回对象的代理,只有在被调用的时候Hibernate才会发出sql语句去查询对象。
两者的语法格式如下:

    public Object get(Class entityClass,Serializable id) throws HibernateException
    public Object load(Class entityClass,Serializable id) throws HibernateException

五.Hibernate缓存及延迟加载
缓存在计算机世界中经常被用到,它的基本实现原理是将原始的数据通过一定的算法备份到新的媒介中,使其访问速度远远高于原始数据的访问速度,然而在实际应用中缓存是很复杂的,通常情况下,介质为内存。
在Hibernate框架中应用了缓存技术(其中分别为Session的缓存,SessionFactory的缓存,也称为一级缓存和二级缓存),使得Hibernate具有强大的功能。
1.一级缓存
一级缓存是Session级的缓存,其生命周期很短,与Session相互对应,由Hibernate进行管理,属于事务范围的缓存。
当程序调用load()、get()、save()、update()、saveOrUpdate()方法或查询接口方法时,hibernate会对实体对象进行缓存,当通过load()或get()查询时,先到缓存中进行查询,在找不到实体对象时,Hibernate才会发出sql语句到数据库中查询,从而提高Hibernate的使用效率。
例:由于一级缓存的存在,在同一个Session中连续两次查询同一对象,Hibernate只会发出一条SQL语句。
注意:一级缓存的生命周期与Session相对应,,它并不会在Session中共享,在不同Session中不能得到其他Session中缓存的实体对象。
2.※二级缓存
二级缓存是SessionFactory级的缓存,其生命周期与SessionFactory一致。二级缓存可以在多个Session间共享,属于进程范围或群集范围的缓存。
二级缓存属于一个可插拔的缓存插件,它的使用需要第三方缓存产品的支持。在Hibernate框架中,通过配置文件可以配置二级缓存的使用策略。
下面通过EHCache演示二级缓存的使用,主要包括以下两个步骤:
(1)加入缓存配置文件ehcache.xml
Ehcache.xml用于设置二级缓存的缓存策略,此文件位于下载的Hibernate的ZIP包的etc目录中,在使用过程中需要将此文件加入到该项目的src目录中。
(2)设置Hibernate配置文件
在配置文件Hibernate.cfg.xml中,开启二级缓存及指定缓存产品提供商,同时需要指定二级缓存应用到的实体对象,示例代码如下:

                <!-- 开启二级缓存 -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!-- 指定缓存产品提供商 -->
    <property name="hibernate.cache.provider_class">
    org.hibernate.cache.EhCacheProvider</property>
        <!-- 映射文件 -->
        <mapping resource="com/shxt/model/Medicine.hbm.xml">
        <!-- 指定二级缓存应用到的实体对象 -->
        <class-cache class="com.shxt.model.Medicine" usage="read-only">

对于二级缓存,可以使用一些不经常更新的数据或者参考的数据,此时性能会得到明显的提升。例如一个新闻网站,当发布一条热点新闻时,会有成千上万的访问量,而此条新闻并没有发生任何的变化,如果每一个用户访问都要查询数据库,将会在性能方面造成一定的问题,此时可以考虑应用二级缓存。如果经常变化的数据应用二级缓存,则将失去意义。
3.Lazy策略
Lazy策略为延迟加载策略,Hibernate通过JDK代理机制对其进行实施,它意味着使用延迟加载的对象在获取对象时返回的是对象的代理,并不是对象的真正的引用,只有在对象呗真正调用时,Hibernate才会对其进行查询,返回真正的对象。
Lazy策略就像现实生活中用钱买物品,钱只是个代理对象,购买成功后忏悔变成实际的物品,即真正的对象。而Lazy对象相当于因为天气原因推迟了一天购买,即延迟加载。但是在购买物品之前或者延迟加载过程中可能会又不需要物品的情况发生,这样就不必购买此物品,从而节省了时间,相当于JVM对其进行了垃圾回收。因此,使用延迟加载策略,某种情况下会对性能起到一定的优化作用。
此外,Hibernate的延迟加载还可以减少程序与数据库的连接次数,因为使用了延迟加载,Hibernate会延缓执行SQL语句,减少数据库的访问次数,从而提高执行的效率。