【问题标题】:Can Spring/JPA/Hibernate use simple JDBC-compliant driver?Spring/JPA/Hibernate 可以使用简单的 JDBC 兼容驱动程序吗?
【发布时间】:2013-02-15 12:46:52
【问题描述】:

我们有一个在服务器上使用 Spring 容器的应用程序,该容器使用 EJB3 实体和 Hibernate 将数据持久保存在 PostgreSQL 数据库中。

我想使用单独的 EntityManager 添加另一个到单独数据库的连接,但 DBMS (Trifox Vortex) 的供应商没有 DataSource 类型的驱动程序。

Hibernate EntityManager 能否使用简单的 JDBC 兼容驱动程序来实现实体的 EJB3 JPA 持久性?

我是否需要为我要连接的 DBMS 提供特定的 Hibernate 方言?

不管怎样,这里是我们当前在 Spring 中的 Entity Manager Factory 的 XML 定义:

  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="UniWorks-EntityPersistenceUnit"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaDialect">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
    </property>
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="${db.showsql}"/>
        <property name="generateDdl" value="${db.generate}"/>
        <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect"/>
      </bean>
    </property>
    <property name="jpaProperties">
      <props>
        <prop key="hibernate.hbm2ddl.auto">${db.hbm2ddl}</prop>
      </props>
    </property>
  </bean>

更新/进展: 21/3/13

在与供应商反复讨论之后,我设法让他们的 JDBC 驱动程序与一个简单的 Java 测试程序一起工作。

不幸的是,他们的 JDBC 驱动程序显然不足以让 Hibernate 获得足够的信息,因为 Spring 无法使用以下堆栈跟踪创建 EntityManagerFactory:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in URL [bundle://222.0:0/META-INF/spring/cobol.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: UniWorks-CobolPersistenceUnit] Unable to build EntityManagerFactory
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)[59:org.springframework.context:3.1.1.RELEASE]
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:69)[90:org.springframework.osgi.core:1.2.1]
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:355)[90:org.springframework.osgi.core:1.2.1]
    at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)[90:org.springframework.osgi.core:1.2.1]
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)[90:org.springframework.osgi.core:1.2.1]
    at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)[91:org.springframework.osgi.extender:1.2.1]
    at java.lang.Thread.run(Thread.java:662)[:1.6.0_24]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: UniWorks-CobolPersistenceUnit] Unable to build EntityManagerFactory
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:132)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268)[64:org.springframework.orm:3.1.1.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)[64:org.springframework.orm:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)[58:org.springframework.beans:3.1.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)[58:org.springframework.beans:3.1.1.RELEASE]
    ... 14 more
Caused by: org.hibernate.HibernateException: Unable to access java.sql.DatabaseMetaData to determine appropriate Dialect to use
    at org.hibernate.dialect.resolver.DialectFactory.determineDialect(DialectFactory.java:141)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.hibernate.dialect.resolver.DialectFactory.buildDialect(DialectFactory.java:97)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:117)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.hibernate.cfg.Configuration.buildSettingsInternal(Configuration.java:2119)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:2115)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1339)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)[80:com.springsource.org.hibernate:3.3.2.GA]
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669)[80:com.springsource.org.hibernate:3.3.2.GA]
    ... 19 more
Caused by: java.sql.SQLException: getDatabaseMajorVersion: Not supported by VORTEXjdbc.
    at vortex.sql.vortexDbMetaData.getDatabaseMajorVersion(vortexDbMetaData.java:362)
    at org.hibernate.dialect.resolver.DialectFactory.determineDialect(DialectFactory.java:131)[80:com.springsource.org.hibernate:3.3.2.GA]
    ... 26 more

所以看起来我可能不得不编写自己的方言子类。任何人都给我任何关于从哪里开始寻找的指示,或者要扩展哪些现有的子类?

【问题讨论】:

    标签: java spring hibernate jdbc entitymanager


    【解决方案1】:

    Hibernate 可以使用数据源以外的连接池。所以你可以使用 c3p0 或 proxool 或 dbcp 甚至你自己的连接池。 Hibernate 确实有一个内置的连接池,尽管它只用于测试/原型设计;它允许你只传递驱动程序名称、url、用户名、密码,它会设置一些(非常)简单的池。

    有几个不同的选项可以实现这一点。首先,Hibernate 总是通过统一的合约来处理连接的获取和释放:org.hibernate.engine.jdbc.connections.spi.ConnectionProvider。因此,一种选择是传入您自己的 ConnectionProvider 实现。

    另一个选项是传入驱动程序、url、用户名、密码和要使用的 ConnectionProvider。对于驱动程序、url、用户名和密码,Hibernate 和 JPA 都定义了执行此操作的机制。对于 JPA,您可以使用 persistence.xml 或设置 javax.persistence.jdbc.driverjavax.persistence.jdbc.urljavax.persistence.jdbc.userjavax.persistence.jdbc.password。至于 ConnectionProvider,默认情况下,Hibernate 将选择不受支持的、不打算用于生产的那个。但是要告诉 Hibernate 使用不同的方法,您可以使用 hibernate.connection.provider_class 设置。 Hibernate 内置支持与 c3p0 和 proxool 作为后端连接池集成(Hibernate 将为您设置和管理 c3p0/proxool 池,并使用该池进行连接管理)。

    正如另一个答案指出的那样,另一种选择是在驱动程序和连接信息周围使用 DataSource 包装器。

    抱歉,我不了解 Spring,所以我不知道所有特定于 Spring 的方法来指定 persistence.xml 或 JPA 设置或 Hibernate 设置。

    【讨论】:

      【解决方案2】:

      这应该可以工作(SimpleDriverDataSource + org.springframework.orm.jpa.vendor.Database.DEFAULT):

         <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
              <property name="driverClass" value="org.h2.Driver"/> <!-- put your driver here -->
              <property name="url" value="jdbc:h2:mem:test"/> <!-- put your jdbc url here -->
              <property name="username" value="sa"/>
              <property name="password" value=""/>
          </bean>
      
                  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
              <property name="dataSource" ref="dataSource"/>
              <property name="persistenceUnitName" value="TestPersistenceUnit"/>
              <property name="jpaDialect">
                  <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
              </property>
              <property name="jpaVendorAdapter">
                  <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                      <property name="showSql" value="false"/>
                      <property name="database" value="DEFAULT"/>
                  </bean>
              </property>
          </bean>
      

      【讨论】:

      • 感谢您的回答。在我提供赏金之前,我将尝试建立一个可行的示例来测试你的理论,但如果看起来我不会在截止日期之前到达那里,我无论如何都会给你。干杯。
      • 我给了你赏金,因为你提供的代码确实让我比我预期的要走得更远。在这个阶段,我可以看到(从堆栈跟踪)Spring 正在调用 hibernate,它正在创建简单的驱动程序数据源,但目前实际的驱动程序本身正在引发关于用户名和密码的错误,所以我认为我们是快到了。
      • 谢谢。也许您可以提供一些堆栈跟踪和您的数据源设置? (在我的代码中使用 H2 数据库的默认用户和密码)
      • 我已经解决了用户/密码错误(JDBC URL 不正确),现在我遇到了许可问题。只是等待供应商提供适当的评估许可证。干杯。
      • 您可能需要实现自定义 Dialet 类(例如这里 - docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/dialect/…)并注册它(docs.jboss.org/hibernate/orm/3.3/reference/en/html/…
      猜你喜欢
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      • 2019-01-10
      相关资源
      最近更新 更多