2015-11-05 22 views
0

我想在Hibernate 5.0.3中註冊集成器來觸發特定的EventListener。我正在修改Hibernate入門指南中提供的示例之一。最初的JUnit測試類行之有效如下:在Hibernate 5.0.3中添加集成器

package org.hibernate.tutorial.annotations; 

    import java.util.Date; 
    import java.util.List; 

    import org.hibernate.Session; 
    import org.hibernate.SessionFactory; 
    import org.hibernate.boot.MetadataSources; 
    import org.hibernate.boot.registry.BootstrapServiceRegistry; 
    import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder; 
    import org.hibernate.boot.registry.StandardServiceRegistry; 
    import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 

    import junit.framework.TestCase; 

    /** 
    * Illustrates the use of Hibernate native APIs. The code here is unchanged from the {@code basic} example, the 
    * only difference being the use of annotations to supply the metadata instead of Hibernate mapping files. 
    * 
    * @author Steve Ebersole 
    */ 
    public class AnnotationsIllustrationTest extends TestCase { 
     private SessionFactory sessionFactory; 

     @Override 
     protected void setUp() throws Exception { 
      // A SessionFactory is set up once for an application!   
      final StandardServiceRegistry registry = new StandardServiceRegistryBuilder() 
        .configure() // configures settings from hibernate.cfg.xml 
        .build(); 
      try { 
       sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory(); 
      } 
      catch (Exception e) { 
       // The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory 
       // so destroy it manually. 
       StandardServiceRegistryBuilder.destroy(registry); 
      } 
     } 

     @Override 
     protected void tearDown() throws Exception { 
      if (sessionFactory != null) { 
       sessionFactory.close(); 
      } 
     } 

     @SuppressWarnings({ "unchecked" }) 
     public void testBasicUsage() { 
      // create a couple of events... 
      Session session = sessionFactory.openSession(); 
      session.beginTransaction(); 
      session.save(new Event("Our very first event!", new Date())); 
      session.save(new Event("A follow up event", new Date())); 
      session.getTransaction().commit(); 
      session.close(); 

      // now lets pull events from the database and list them 
      session = sessionFactory.openSession(); 
      session.beginTransaction(); 
      List result = session.createQuery("from Event").list(); 
      for (Event event : (List<Event>) result) { 
       System.out.println("Event (" + event.getDate() + ") : " + event.getTitle()); 
      } 
      session.getTransaction().commit(); 
      session.close(); 
     } 
    } 

現在我只是修改這樣的設置()方法:

@Override 
    protected void setUp() throws Exception { 
     // A SessionFactory is set up once for an application! 
     BootstrapServiceRegistry bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder().applyIntegrator(new MyEventListenerIntegrator()).build(); 

     try { 
      sessionFactory = new MetadataSources(bootstrapServiceRegistry).buildMetadata().buildSessionFactory(); 
     } 
     catch (Exception e) { 
      // The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory 
      // so destroy it manually. 
      StandardServiceRegistryBuilder.destroy(bootstrapServiceRegistry); 
     } 
    } 

當我執行的測試情況下,我得到以下錯誤:

java.lang.ClassCastException: org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl cannot be cast to org.hibernate.boot.registry.internal.StandardServiceRegistryImpl 

這是我的積分級(但我不認爲這是問題的原因是安裝()的時候,我不應用集成到BootstrapServiceRegistryBuilder方法也失敗了):

package org.hibernate.tutorial.annotations; 

import org.hibernate.boot.Metadata; 
import org.hibernate.cfg.Configuration; 
import org.hibernate.engine.spi.SessionFactoryImplementor; 
import org.hibernate.event.service.spi.EventListenerRegistry; 
import org.hibernate.event.spi.EventType; 
import org.hibernate.integrator.spi.Integrator; 
import org.hibernate.service.spi.SessionFactoryServiceRegistry; 

public class MyEventListenerIntegrator implements Integrator { 

    public void integrate(
      Configuration configuration, 
      SessionFactoryImplementor sessionFactory, 
      SessionFactoryServiceRegistry serviceRegistry) { 
     // As you might expect, an EventListenerRegistry is the thing with which event listeners are registered It is a 
     // service so we look it up using the service registry 
     final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); 

     //  3) This form adds the specified listener(s) to the end of the listener chain 
     eventListenerRegistry.appendListeners(EventType.LOAD, new LoadListenerExample()); 
    } 

    @Override 
    public void disintegrate(SessionFactoryImplementor arg0, SessionFactoryServiceRegistry arg1) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void integrate(Metadata arg0, SessionFactoryImplementor arg1, SessionFactoryServiceRegistry arg2) { 
     // TODO Auto-generated method stub 

    } 
} 

最後我的hibernate.cfg.xml:

<?xml version='1.0' encoding='utf-8'?> 
<!-- 
    ~ Hibernate, Relational Persistence for Idiomatic Java 
    ~ 
    ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later. 
    ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. 
    --> 
<!DOCTYPE hibernate-configuration PUBLIC 
     "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 

<hibernate-configuration> 

    <session-factory> 

     <!-- Database connection settings --> 
     <property name="connection.driver_class">org.h2.Driver</property> 
     <property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property> 
     <property name="connection.username">sa</property> 
     <property name="connection.password"></property> 

     <!-- JDBC connection pool (use the built-in) --> 
     <property name="connection.pool_size">1</property> 

     <!-- SQL dialect --> 
     <property name="dialect">org.hibernate.dialect.H2Dialect</property> 

     <!-- Disable the second-level cache --> 
     <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> 

     <!-- Echo all executed SQL to stdout --> 
     <property name="show_sql">true</property> 

     <!-- Drop and re-create the database schema on startup --> 
     <property name="hbm2ddl.auto">create</property> 

     <!-- Names the annotated entity class --> 
     <mapping class="org.hibernate.tutorial.annotations.Event"/> 

    </session-factory> 

</hibernate-configuration> 

非常感謝您的幫助。

+0

你沒有離開堆棧跟蹤這麼辛苦是一定的,但我認爲問題是伴您行'StandardServiceRegistryBuilder.destroy(bootstrapServiceRegistry)'。 您正嘗試使用StandardServiceRegistryBuilder關閉類型不匹配的BootstrapServiceRegistry。 –

+0

有問題的行是:'sessionFactory = new MetadataSources(bootstrapServiceRegistry).buildMetadata()。buildSessionFactory();'。 stacktrace是'org.eclipse.debug.core.DebugException:com.sun.jdi.ClassNotLoadedException:在檢索數組的組件類型時未發生類型加載.'和異常的原因是'org.hibernate.HibernateException: 'hibernate.dialect'未設置時,對DialectResolutionInfo的訪問不能爲空。我想這是因爲我沒有在任何地方指出hibernate.cfg.xml文件。你也對'destroy'方法是正確的。 – rocotocloc

回答

3

好,解決了:

@Override 
protected void setUp() throws Exception { 
    // A SessionFactory is set up once for an application! 
    BootstrapServiceRegistry bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder().applyIntegrator(new MyEventListenerIntegrator()).build(); 

    final StandardServiceRegistry registry = new StandardServiceRegistryBuilder(bootstrapServiceRegistry) 
      .configure() // configures settings from hibernate.cfg.xml 
      .build(); 
    try { 
     sessionFactory = new MetadataSources(registry ).buildMetadata().buildSessionFactory(); 
    } 
    catch (Exception e) { 
     // The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory 
     // so destroy it manually. 
     StandardServiceRegistryBuilder.destroy(registry ); 
    } 
} 
+0

希望提到另一種選擇,即使用Hibernate支持的Java服務發現機制(http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html)來發現集成器和其他擴展點。 –

+0

感謝您的幫助,我會試一試。 – rocotocloc