Hibernate初始化过程

来源:互联网 发布:java主方法与类重名 编辑:程序博客网 时间:2024/05/21 08:02

如果要写一个Hibernate的Hello World程序,我们大概需要做这么几件事情:

1. 创建对应表的实体类并编写其到对应表的映射文件;

2. 编写hibernate的配置文件,默认是hibernate.cfg.xml,你当然可以用其它的名字,只需自己传递配置文件名称给Configure就好;

3. 编写具体操作数据库的dataservice;

对于第三步,又可分为:创建SessionFactory;获取session;通过session对象执行数据库操作;等等

如Hibernate中一个Tutorial:

  1. public class HibernateUtil {
  2.  
  3. private static final SessionFactory sessionFactory;
  4.  
  5. static {
  6. try {
  7. // Create the SessionFactory from hibernate.cfg.xml
  8. sessionFactory = new Configuration().configure().buildSessionFactory();
  9. } catch (Throwable ex) {
  10. // Make sure you log the exception, as it might be swallowed
  11. System.err.println("Initial SessionFactory creation failed." + ex);
  12. throw new ExceptionInInitializerError(ex);
  13. }
  14. }
  15.  
  16. public static SessionFactory getSessionFactory() {
  17. return sessionFactory;
  18. }
  19.  
  20. }

这个工具类中创建了sessionFactory对象,其它的数据服务类都可以使用。(我们应该知道SessionFactory是一个比较“重”的对象,创建的开销过大,一般一个数据库使用一个SessionFactory)

  1. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  2. throws ServletException, IOException {
  3. ……
  4.  
  5. try {
  6. // Begin unit of work
  7. HibernateUtil.getSessionFactory()
  8. .getCurrentSession().beginTransaction(); //通过SessionFactory获取session并开始事务
  9.  
  10. ……
  11. createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate)); //数据库操作
  12. ……
  13.  
  14. } catch (Exception ex) {
  15. HibernateUtil.getSessionFactory()
  16. .getCurrentSession().getTransaction().rollback(); //异常则回滚事务
  17. throw new ServletException(ex);
  18. }
  19. }
  20.  
  21. protected void createAndStoreEvent(String title, Date theDate) {
  22. Event theEvent = new Event();
  23. theEvent.setTitle(title);
  24. theEvent.setDate(theDate);
  25.  
  26. HibernateUtil.getSessionFactory()
  27. .getCurrentSession().save(theEvent); //通过session的save方法保存对象到数据库
  28. }

 

这里无关的代码我都给删除了,可以看到其流程跟前面提到的第三部基本是一致的。下面便来分析一下这段代码的背后,Hibernate做了什么?整个过程的时序图如下:

hibernate01

Configuration构造函数中会创建Mapping和SettingsFactory,它们会在后续用于解析SessionFactory的配置属性,之后调用Configuration的configure()函数,在configure()中将通过doConfigure函数完成对Hibernate配置文件hibernate.cfg.xml的解析。

解析完配置文件后,便可以通过BuildSessionFactory()创建SessionFactory了,在这个函数中,首先在buildSettings()中通过之前创建的SettingsFactory建立各种属性设置,之后通过new一个SessionFactoryImpl完成SessionFactory的创建。

有了SessionFactory,Client端便可以通过它获取Session,并执行各种数据库操作了。

从getCurrentSession()函数中可以知道,Session是从CurrentSessionContext获取的,那么CurrentSessionContext是怎么来的?可以来看看buildCurrentSessionContext函数的实现:

  1. private CurrentSessionContext buildCurrentSessionContext() {
  2. String impl = this.properties.getProperty("hibernate.current_session_context_class");
  3.  
  4. if ((impl == null) && (this.transactionManager != null)) {
  5. impl = "jta";
  6. }
  7.  
  8. if (impl == null) {
  9. return null;
  10. }
  11. if ("jta".equals(impl)) {
  12. if (this.settings.getTransactionFactory().areCallbacksLocalToHibernateTransactions()) {
  13. log.warn("JTASessionContext being used with JDBCTransactionFactory; auto-flush will not operate correctly with getCurrentSession()");
  14. }
  15. return new JTASessionContext(this);
  16. }
  17. if ("thread".equals(impl)) {
  18. return new ThreadLocalSessionContext(this);
  19. }
  20. if ("managed".equals(impl)) {
  21. return new ManagedSessionContext(this);
  22. }
  23. try
  24. {
  25. Class implClass = ReflectHelper.classForName(impl);
  26. return ((CurrentSessionContext)implClass.getConstructor(new Class[] { SessionFactoryImplementor.class }).newInstance(new Object[] { this }));
  27. }
  28. catch (Throwable t)
  29. {
  30. log.error("Unable to construct current session context [" + impl + "]", t); }
  31. return null;
  32. }

可以看到,Hibernate会根据“hibernate.current_session_context_class”的属性值来决定创建哪一类上下文会话(Contextual Session),可以看看Hibernate的参考文档对这个属性的解释:“为当前Session的作用域选择一个自定义策略,可选的会话上下文有:jta|thread|managed|自定义类”。我们以thread类型会话来分析,ThreadLocalSessionContext会借助ThreadLocal实现每个线程有一个对应的session。

有了CurrentSessionContext,来看看getCurrentSession函数:

  1. public Session getCurrentSession()
  2. throws HibernateException
  3. {
  4. if (this.currentSessionContext == null) {
  5. throw new HibernateException("No CurrentSessionContext configured!");
  6. }
  7. return this.currentSessionContext.currentSession();
  8. }

它会通过CurrentSessionContext的currentSession()函数来获取session,针对ThreadLocalSessionContext,也即:

  1. public final org.hibernate.classic.Session currentSession()
  2. throws HibernateException
  3. {
  4. org.hibernate.classic.Session current = existingSession(this.factory); //检查ThreadLocal中是否有session,有则直接返回,保证一个线程一个session
  5. if (current == null) {
  6. current = buildOrObtainSession(); //通过openSession创建一个新的session
  7.  
  8. current.getTransaction().registerSynchronization(buildCleanupSynch());
  9.  
  10. if (needsWrapping(current)) {
  11. current = wrap(current); //包装session,主要是针对代理的情况
  12. }
  13.  
  14. doBind(current, this.factory); //当然是把新建的session绑定到ThreadLocal中啦
  15. }
  16. return current;
  17. }

到了这里,基本就完成了,后面就是通过session执行各种数据操作以及事务管理之类的了。

0 0