Java 为什么在此代码段中Hibernate会话获取失败?

Java 为什么在此代码段中Hibernate会话获取失败?,java,hibernate,Java,Hibernate,我正在试验Hibernate4.1.2 编写了以下类以帮助我使用新的ServiceRegistry方法获取会话 ===================================================== package com.debaself.samples; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfigu

我正在试验Hibernate4.1.2

编写了以下类以帮助我使用新的ServiceRegistry方法获取会话

=====================================================

package com.debaself.samples;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;


public class SessionFetch {

private static SessionFactory sessionFactory = null;

public SessionFactory getSessionFactory(){

if(sessionFactory == null){
         Configuration cfg = new    AnnotationConfiguration().addResource("hibernate.cfg.xml").configure();

ServiceRegistry serviceRegistry = new     ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
        sessionFactory = cfg.buildSessionFactory(serviceRegistry);
    }

    return sessionFactory ;
}

public Session getSession(){
    return getSessionFactory().openSession();
}
}
public class SessionFetchTest {

    @Test 
    public void getSessionFactoryTest(){
        SessionFetch fetch = new SessionFetch();
        SessionFactory factory = fetch.getSessionFactory();

        assertNotNull(factory);
        assert(!factory.isClosed());
        factory.close();
    }

    @Test
    public void getSessionTest(){
        SessionFetch fetch = new SessionFetch();
        Session session = fetch.getSession();

        assert(session.isOpen());
        assert(session.isConnected());      
    }
}
==============================================================================

现在我写了一个测试

===============================================

package com.debaself.samples;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;


public class SessionFetch {

private static SessionFactory sessionFactory = null;

public SessionFactory getSessionFactory(){

if(sessionFactory == null){
         Configuration cfg = new    AnnotationConfiguration().addResource("hibernate.cfg.xml").configure();

ServiceRegistry serviceRegistry = new     ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
        sessionFactory = cfg.buildSessionFactory(serviceRegistry);
    }

    return sessionFactory ;
}

public Session getSession(){
    return getSessionFactory().openSession();
}
}
public class SessionFetchTest {

    @Test 
    public void getSessionFactoryTest(){
        SessionFetch fetch = new SessionFetch();
        SessionFactory factory = fetch.getSessionFactory();

        assertNotNull(factory);
        assert(!factory.isClosed());
        factory.close();
    }

    @Test
    public void getSessionTest(){
        SessionFetch fetch = new SessionFetch();
        Session session = fetch.getSession();

        assert(session.isOpen());
        assert(session.isConnected());      
    }
}
==================================================

package com.debaself.samples;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;


public class SessionFetch {

private static SessionFactory sessionFactory = null;

public SessionFactory getSessionFactory(){

if(sessionFactory == null){
         Configuration cfg = new    AnnotationConfiguration().addResource("hibernate.cfg.xml").configure();

ServiceRegistry serviceRegistry = new     ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
        sessionFactory = cfg.buildSessionFactory(serviceRegistry);
    }

    return sessionFactory ;
}

public Session getSession(){
    return getSessionFactory().openSession();
}
}
public class SessionFetchTest {

    @Test 
    public void getSessionFactoryTest(){
        SessionFetch fetch = new SessionFetch();
        SessionFactory factory = fetch.getSessionFactory();

        assertNotNull(factory);
        assert(!factory.isClosed());
        factory.close();
    }

    @Test
    public void getSessionTest(){
        SessionFetch fetch = new SessionFetch();
        Session session = fetch.getSession();

        assert(session.isOpen());
        assert(session.isConnected());      
    }
}
奇怪的是

当我单独运行测试方法时,两个测试都成功了。但是当我一次性运行它们时,getSessionTest()总是会失败并抛出UnknownServiceException



有人能解释一下这种行为吗?

正如我在评论中所说,工厂已经关闭了。也许可以在
@AfterClass
部分关闭它

正如我在评论中所说,工厂已经关闭。也许可以在
@AfterClass
部分关闭它

您的直接问题已经得到了回答,但请注意,您的代码还存在其他问题。单元测试应该是可执行的,没有相互依赖性,但您的代码并非如此。您可以跨测试重用同一会话。您还可以重用工厂,甚至在一次测试中关闭它。此外,测试可能在多个线程中运行,并且您的代码不是线程安全的(出厂参考不会正确共享)。

您的直接问题已经得到回答,但请注意,您的代码还存在其他问题。单元测试应该是可执行的,没有相互依赖性,但您的代码并非如此。您可以跨测试重用同一会话。您还可以重用工厂,甚至在一次测试中关闭它。此外,测试可能在多个线程中运行,并且您的代码不是线程安全的(工厂引用将不会正确共享)。

我的第一个猜测是它与SessionFactory类型的静态成员有关,但我仍然没有对此的明确答案。我猜是因为您在第一次测试中关闭了会话工厂…哈哈。。这很有趣,同时也很愚蠢:)谢谢MikeMy我的第一个猜测是与SessionFactory类型的静态成员有关,但我仍然没有一个明确的答案。我猜是因为你在第一次测试中关闭了session factory…哈哈。。这既有趣又愚蠢:)谢谢MikeAs,你会发现我并没有试图用这些测试构建一些高容量的应用程序。我们的目标是使用新的ServiceRegistry模型简单地探索会话创建,测试是最简单、最快速的实现方式,仅此而已。尽管我将高度赞赏任何关于如何避免用于缓存工厂的静态模式的见解。因为我确信我们不会每次都创建工厂。还有一点-会话不会在测试中被重用,工厂需要被重用以避免开销。如有任何意见,我们将不胜感激。谢谢。好吧,只要你足够小心,你就可以重新使用工厂。这当然不包括关闭它。你基本上有一个懒惰的初始化单体。最好让它急切地初始化和最终。此外,您可能希望确保每个测试都有一个新的会话,这可以通过在
tearDown
中关闭会话来完成。您的评论仍然没有明确说明我们是否应该重新创建工厂。你是说我们应该更喜欢重新创建工厂而不是重复使用它吗?你可以重复使用工厂,是的。我可能也会这么做。它只需要创建一次,并作为一个全局单体保存。正如你所看到的,我并没有试图用这些测试构建一些高容量的应用程序。我们的目标是使用新的ServiceRegistry模型简单地探索会话创建,测试是最简单、最快速的实现方式,仅此而已。尽管我将高度赞赏任何关于如何避免用于缓存工厂的静态模式的见解。因为我确信我们不会每次都创建工厂。还有一点-会话不会在测试中被重用,工厂需要被重用以避免开销。如有任何意见,我们将不胜感激。谢谢。好吧,只要你足够小心,你就可以重新使用工厂。这当然不包括关闭它。你基本上有一个懒惰的初始化单体。最好让它急切地初始化和最终。此外,您可能希望确保每个测试都有一个新的会话,这可以通过在
tearDown
中关闭会话来完成。您的评论仍然没有明确说明我们是否应该重新创建工厂。你是说我们应该更喜欢重新创建工厂而不是重复使用它吗?你可以重复使用工厂,是的。我可能也会这么做。它的意思是创建一次并作为一个全局单例保存。