我们有一个应用程序在服务器上使用Spring容器,该容器使用EJB3实体和Hibernate将数据保存在PostgreSQL数据库中。
我想使用单独的EntityManager将另一个连接添加到单独的数据库,但DBMS(Trifox Vortex)的供应商没有DataSource
类型的驱动程序。
Hibernate EntityManager是否可以使用简单的JDBC兼容驱动程序来实现实体的EJB3 JPA持久性?
我是否需要为我正在连接的DBMS使用特定的Hibernate方言?
对于它的价值,这里是我们当前的Spring实体经理工厂的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
所以看起来我可能要编写自己的方言子类。有人给我任何指示,从哪里开始寻找,或者扩展现有的子类?
答案 0 :(得分:3)
这应该有效(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>
答案 1 :(得分:0)
Hibernate可以使用DataSource以外的连接池。所以你可以使用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.driver
,javax.persistence.jdbc.url
,javax.persistence.jdbc.user
和javax.persistence.jdbc.password
。就ConnectionProvider而言,默认情况下,Hibernate将选择不受支持的,非生产性的。但要告诉Hibernate使用不同的一个,您可以使用hibernate.connection.provider_class
设置。 Hibernate内置支持与c3p0和proxool集成作为后端连接池(Hibernate将为您设置和管理c3p0 / proxool池并使用该池进行连接管理)。
正如另一个答案所指出的,另一个选择是在驱动程序和连接信息周围使用DataSource包装。
抱歉,我不知道Spring所以我不知道所有特定于Spring的方法来指定persistence.xml或JPA设置或Hibernate设置。