2013-03-01 12 views
5

Mamy aplikację, która używa kontenera Spring na serwerze, który używa encji EJB3 i Hibernate do utrzymywania danych w bazie danych PostgreSQL.Czy Spring/JPA/Hibernate może używać prostego sterownika zgodnego ze standardem JDBC?

Chciałbym dodać inne połączenie do oddzielnej bazy danych za pomocą oddzielnego EntityManager, ale dostawca DBMS (Trifox Vortex) nie ma sterownika typu DataSource.

Czy menedżer EntryManager może używać prostego sterownika zgodnego ze standardem JDBC do implementacji komponentów EJB3 w JPA?

Czy muszę mieć konkretny dialekt hibernacji dla DBMS, z którym się łączę?

Na co warto, oto definicja XML z naszej obecnej Entity dyrektor fabryki wiosną:

<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> 

UPDATE/progress: 21/3/13

Po wiele do-ing i współpracując z Dostawcą, udało mi się przekonać ich sterownik JDBC do pracy z prostym programem testowym Javy.

Niestety, ich sterownik JDBC oczywiście nie jest wystarczające dla Hibernate, aby uzyskać wystarczająco dużo informacji, jak wiosna nie stworzyć EntityManagerFactory z następującym Stack Trace:

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 

więc wygląda na to może muszę napisać własna podklasa dialektu. Ktoś dał mi wskazówki, od czego zacząć, lub do jakiego istniejącego podklasy należy przedłużyć?

Odpowiedz

3

ten powinien działać (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> 
+0

Dzięki za odpowiedź. Postaram się przygotować przykład, by przetestować twoją teorię, zanim oddam nagrodę, ale jeśli nie wygląda na to, że dotrę tam przed upływem terminu, dam ci to i tak. Twoje zdrowie. – DuncanKinnear

+0

masz jakieś resutle? :) –

+0

Dałem ci nagrodę, ponieważ kod, który podałeś, z pewnością dał mi znacznie więcej, niż się spodziewałem. Na tym etapie widzę (ze śladu stosu), że Spring wywołuje hibernację, która tworzy proste źródło danych sterownika, ale w tej chwili sam sterownik rzuca błąd na nazwę użytkownika i hasło, więc myślę, że jesteśmy prawie tu. – DuncanKinnear

0

Hibernate można używać pula połączeń innych niż źródła danych. Więc możesz użyć c3p0 lub proxool lub dbcp lub nawet własnej puli połączeń. Hibernate ma wbudowaną pulę połączeń, ale jest przeznaczona tylko do testowania/prototypowania; pozwoliłoby to po prostu przekazać nazwę kierowcy, adres URL, nazwę użytkownika, hasło i skonfigurować (bardzo) proste łączenie.

Istnieje kilka różnych opcji, aby to osiągnąć. Po pierwsze, Hibernate zawsze obsługuje uzyskiwanie i zwalnianie połączeń za pośrednictwem ujednoliconej umowy: org.hibernate.engine.jdbc.connections.spi.ConnectionProvider. Tak więc jedną z opcji jest przekazanie własnej implementacji ConnectionProvider.

Inną opcją jest przekazanie sterownika, adresu URL, nazwy użytkownika, hasła i opcji ConnectionProvider do użycia. Dla sterownika, adresu URL, nazwy użytkownika i hasła zarówno Hibernate, jak i JPA definiują mechanizmy do tego. W przypadku JPA można użyć opcji persistence.xml lub ustawień , javax.persistence.jdbc.url, i javax.persistence.jdbc.password. Jeśli chodzi o ConnectionProvider, domyślnie Hibernate wybierze wersję nieobsługiwaną, nie przeznaczoną do produkcji. Ale aby powiedzieć Hibernate'owi inny do użycia, użyłbyś ustawienia hibernate.connection.provider_class. Hibernate ma wbudowaną obsługę integracji z c3p0 i proxool jako pule połączeń back-end (Hibernate skonfiguruje i zarządza pulą c3p0/proxool dla ciebie i użyje tej puli do zarządzania połączeniami).

Jak wskazuje inna odpowiedź, inną opcją jest użycie opakowania DataSource wokół sterownika i informacji o połączeniu.

Niestety, nie znam Springa, więc nie znam wszystkich specyficznych dla Spring sposobów określania ustawień persistence.xml lub JPA lub Hibernate.

Powiązane problemy