在使用MyEclipse创建Hibernate之后都会自动生成一个HibernateSessionFactory,这个类的主要功能是进行数据库连接对象(Session)的取得与关闭。
在以后的开发之中,很少会在代码里面去关注:Configuration、SessionFactory等操作。包括如何连接如何创建工厂都会被实际的其它操作所取代。用户最关注的就是如何进行数据的CRUD操作。
但是在这个HibernateSessionFactory里面有一个重要的操作实现:java.lang.ThreadLocal<T>,这个类是一个帮助我们解决引用问题的操作类。这个类有如下两个重要的操作方法: (1)设置对象内容:public void set(T value) (2)取得对象内容:public T get() 下面通过一个实验来进行实际的使用分析。 范例:传统做法
package org.lks.test; public class News { private String title; } package org.lks.test; public class Message { public void print(News vo){ System.out.println(vo.getTitle()); } }传统的开发做法,是如果Message要想输出News类对象的内容,那么必须要在Message类里面传递一个News类对象的引用才可以进行处理。 范例:标准处理
package org.lks.test; public class TestMessage { public static void main(String[] args) { News vo = new News(); vo.setTitle("hhy big fool"); Message msg = new Message(); msg.print(vo); } }整个代码使用了一个明确的对象引用操作的方式完成。 那么如果说此时使用的是ThreadLocal类,处理的形式就可以发生一些变化,不再需要由用户自己来处理明确的引用关系。 范例:定义ThreadUtil类,这个类主要负责传送ThreadLocal
package org.lks.test; public class ThreadUtil { private static ThreadLocal<News> threadLocal = new ThreadLocal<News>(); public static ThreadLocal<News> getThreadLocal() { return threadLocal; } }范例:修改TestMessage的内容
package org.lks.test; public class TestMessage { public static void main(String[] args) { News vo = new News(); vo.setTitle("hhy big fool"); Message msg = new Message(); ThreadUtil.getThreadLocal().set(vo); msg.print(); } }此时没有必要再去处理引用关系,而直接利用ThreadLocal完成。
一般如果要在实际开发之中使用的话,往往用于数据库连接处理类的操作上。
在MyEclipse里面为了简化开发提供有这样的工具类,这个工具类的主要目的是取得SessionFactory以及Session对象。现在最为重要的实际上是Session对象,所有的数据操作由此展开。 范例:分析HibernateSessionFactory
package org.lks.dbc; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; /** * Configures and provides access to Hibernate sessions, tied to the * current thread of execution. Follows the Thread Local Session * pattern, see {@link http://hibernate.org/42.html }. */ public class HibernateSessionFactory { /** * Location of hibernate.cfg.xml file. * Location should be on the classpath as Hibernate uses * #resourceAsStream style lookup for its configuration file. * The default classpath location of the hibernate config file is * in the default package. Use #setConfigFile() to update * the location of the configuration file for the current session. */ //表示提供有ThreadLocal对象保存,适合于进行线程的准确处理 private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>(); private static org.hibernate.SessionFactory sessionFactory; //连接工厂 private static Configuration configuration = new Configuration(); //读取配置文件 private static ServiceRegistry serviceRegistry; //服务注册类 static { //静态代码块,可以在类加载的时候执行一次 try { configuration.configure(); //读取配置文件 serviceRegistry = new StandardServiceRegistryBuilder().configure().build(); try { //在静态块中就已经准备好了SessionFactory类的对象 sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory(); } catch (Exception e) { StandardServiceRegistryBuilder.destroy(serviceRegistry); e.printStackTrace(); } } catch (Exception e) { System.err.println("%%%% Error Creating SessionFactory %%%%"); e.printStackTrace(); } } private HibernateSessionFactory() { //构造方法私有化,因为本类不需要提供构造 } /** * Returns the ThreadLocal Session instance. Lazy initialize * the <code>SessionFactory</code> if needed. * * 取得Session对象,对象是通过ThreadLocal类取得的,如果没有保存的Session,那么会重新连接 * * @return Session操作对象 * @throws HibernateException */ public static Session getSession() throws HibernateException { //为了防止用户可能重复使用Session对象,是通过保存在ThreadLocal类中的Session直接使用的 Session session = (Session) threadLocal.get(); if (session == null || !session.isOpen()) { //如果第一次使用或者之前关闭了,那么Session为null if (sessionFactory == null) { //判断此时是否存在有SessionFactory类对象 rebuildSessionFactory(); //如果SessionFactory不存在,则重新创建一个SessionFactory } //判断此时是否取得了SessionFactory类对象,如果取得,则使用openSession()打开新Session,否则返回null session = (sessionFactory != null) ? sessionFactory.openSession() : null; threadLocal.set(session); //为了防止可能重复使用Session,将其保存在ThreadLocal中。 } return session; } /** * Rebuild hibernate session factory * * 重新进行SessionFactory类对象的创建 * */ public static void rebuildSessionFactory() { try { configuration.configure(); serviceRegistry = new StandardServiceRegistryBuilder().configure().build(); try { sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory(); } catch (Exception e) { StandardServiceRegistryBuilder.destroy(serviceRegistry); e.printStackTrace(); } } catch (Exception e) { System.err.println("%%%% Error Creating SessionFactory %%%%"); e.printStackTrace(); } } /** * Close the single hibernate session instance. * * 所有操作的最后一定要关闭Session,在业务层中关闭 * * @throws HibernateException */ public static void closeSession() throws HibernateException { Session session = (Session) threadLocal.get(); //取得已有的Session对象 threadLocal.set(null); //清空ThreadLocal的保存 if (session != null) { //将Session进行关闭 session.close(); } } /** * return session factory * * 取得SessionFactory类的对象,目的是为了进行缓存操作 * */ public static org.hibernate.SessionFactory getSessionFactory() { return sessionFactory; } /** * return hibernate configuration * * 取得Configuration类的对象 * */ public static Configuration getConfiguration() { return configuration; } }这个类只要使用就可以取得Session、SessionFactory、Configuration类的对象,至于如何取的,可以暂时不关心(因为Hibernate不可能单独使用,单独使用没有优势,都会结合到Spring上使用)。 范例:使用这个连接工厂类
package org.lks.test; import java.text.ParseException; import java.text.SimpleDateFormat; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.lks.dbc.HibernateSessionFactory; import org.lks.pojo.Member; public class TestMemberInsertDemoSimple { public static void main(String[] args) throws ParseException { // 1、设置VO的属性内容的操作应该由控制层完成 Member pojo = new Member(); pojo.setMid("31613012201"); pojo.setMname("lks"); pojo.setMage(23); pojo.setMsalary(2000.0); pojo.setMnote("hhy big fool!"); pojo.setMbirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1996-10-15")); // 2、数据的保存操作应该由数据层完成 HibernateSessionFactory.getSession().save(pojo); // 3、事务以及Session的关闭应该由业务层完成 HibernateSessionFactory.getSession().beginTransaction().commit(); HibernateSessionFactory.closeSession(); } }以后在讲解Hibernate过程之中,就是用如上的操作方式。