UnknownServiceException:Hibernate 4中的ConnectionProvider

时间:2013-08-15 16:37:41

标签: spring hibernate-4.x

我刚刚将Spring Web应用程序从Hibernate 3.6升级到4.2,并根据我的需要完成了所有必要的更改。应用程序本身似乎运行良好,但有些测试通过Spring的应用程序上下文测试支持使用Hibernate,现在这些错误偶尔会失败:

Caused by: org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.service.jdbc.connections.spi.ConnectionProvider]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:126)
at org.hibernate.internal.AbstractSessionImpl.getJdbcConnectionAccess(AbstractSessionImpl.java:261)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.<init>(JdbcCoordinatorImpl.java:97)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.<init>(TransactionCoordinatorImpl.java:87)
at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:253)
at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1599)
at org.hibernate.internal.SessionFactoryImpl.openSession(SessionFactoryImpl.java:965)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:412)

当以默认文件系统顺序运行时,它们似乎运行得更可靠,但我现在以随机顺序运行它们以更容易地重现它。一旦发生此错误,之后的所有类似测试似乎都会失败。测试使用@DirtiesContext注释进行设置,因此Spring测试运行器应该为每个类重新创建一个新的ApplicationContext(以及SessionFactory和HSQLDB mem DB)。所以不应该从一个测试类泄漏到下一个测试类。

有什么想法吗?没有ConnectionProvider听起来像Hibernate要么仍在启动,要么正在关闭。

4 个答案:

答案 0 :(得分:2)

您应该只在应用程序中创建一次Session Factory对象,并且不应在整个应用程序中销毁。如果您尝试关闭曾经创建的会话工厂对象并希望使用相同的对象,那么您将获得上述异常 即。 创建会话时出错:org.hibernate.service.UnknownServiceException:请求未知服务[org.hibernate.engine.jdbc.connections.spi.ConnectionProvider] 因此,在上面的场景中,您应该创建hibernate util并定义如下字段:

import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {

private static Configuration configuration;
private static StandardServiceRegistry builder;
private static SessionFactory factory;

static {
try {
configuration = new Configuration().configure("/com/hibernate/hibernate.cfg.xml");
builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
factory = configuration.buildSessionFactory(builder);
} catch (HibernateException he) {
System.err.println("Error creating Session: " + he);
throw new ExceptionInInitializerError(he);
}
}

public static SessionFactory getSessionFactory() {
return factory;
}

public static void closeSessionFactory() {
if (factory != null) {
try {
StandardServiceRegistryBuilder.destroy(builder);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

答案 1 :(得分:1)

我们现在已经通过测试了。这实际上是我们的事务处理泄漏到非事务性测试中的问题。我们的事务支持扩展了Spring的TransactionAspectSupport,而对于Hibernate 3,它通常无用地在非事务性测试中工作。在Hibernate 4中,当它尝试使用关闭的会话工厂创建事务时,它现在以迂回方式失败。

我们修改了测试的设置方式,这样除非我们进行交易测试,否则它根本不会尝试做任何事务性的事情,现在他们很快就过去了。

道德:使用单身人士的一个危险就是它很容易在测试中泄漏东西。

答案 2 :(得分:1)

之前发生过这样的事情。当我将数据库的IP从127.0.0.1更改为192.168.1.27(在我的网络中我的计算机的IP,它可以在windows中执行ip config或在linux中执行ifconfig)时解决了。它可能不是一个永久的解决方案,但它会躲过一劫。

答案 3 :(得分:0)

Hibernate中的Session对象不是线程安全的,除非您同步对Session对象的访问,否则不应在不同的线程中使用相同的会话。

如果你真的想要使用那个技巧,那么我想告诉你,每次交易完成后清除和关闭会话。或者只使用openSession(),这样您的程序就能运行并执行。