My Spring application leaks database connections whereas I use the default Roo configuration - spring

I am encountering an serious issue with my application. It leaks database connections whereas I use the default Spring Roo datasource configuration as follows:
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="true" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="1800000" />
<property name="numTestsPerEvictionRun" value="3" />
<property name="minEvictableIdleTimeMillis" value="1800000" />
<property name="validationQuery" value="SELECT 1" />
<property name="maxActive" value="2"/>
<property name="logAbandoned" value="true"/>
<property name="removeAbandoned" value="true"/>
</bean>
Here is the controller method that causes the leak:
#RequestMapping(value = "getMessages", method = RequestMethod.GET, produces = "application/json")
#ResponseBody
public DeferredResult<List<Message>> getMessages(#RequestParam final Long senderId) {
// TODO: check that recipientId was not changed by malicious user!!
final Long recipientId = memberService.retrieveCurrentMember().getId();
final String messageRequestKey = new StringBuilder().append(senderId).append(":").append(recipientId).toString();
final DeferredResult<List<Message>> deferredResult = new DeferredResult<List<Message>>(null, Collections.emptyList());
messageRequests.put(messageRequestKey, deferredResult);
deferredResult.onCompletion(new Runnable() {
#Override
public void run() {
messageRequests.remove(messageRequestKey);
}
});
List<Message> unReadMessages = messageService.findUnreadMessages(senderId, recipientId);
if (!unReadMessages.isEmpty()) {
deferredResult.setResult(unReadMessages);
}
return deferredResult;
}
It appears that connections are not returned to the pool by the above method (which is polled continuously by ajax).
Can anyone please help?
EDIT:
Hibernate config:
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database -->
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.use_sql_comments" value="true"/>
<property name="hibernate.connection.release_mode" value="after_transaction"/>
</properties>
</persistence-unit>
Hibernate version:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.8.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.8.Final</version>
<exclusions>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>

I'm not sure if you are using hibernate? If so take a look at the setting hibernate.connection.release_mode . We had this issue and putting it to after_transaction solved all our connection issues.
EDIT
Our config:
<beans:bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<beans:property name="dataSource" ref="mvcDatasource" />
<beans:property name="persistenceUnitName" value="mvcPersistenceUnit" />
<beans:property name="persistenceProvider">
<beans:bean class="org.hibernate.ejb.HibernatePersistence" />
</beans:property>
<!-- Fix Hibernate not properly connected with spring -->
<beans:property name="jpaVendorAdapter">
<beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</beans:property>
<beans:property name="jpaPropertyMap">
<beans:map>
<!-- Connection release fix -->
<beans:entry key="hibernate.connection.release_mode" value="after_transaction" />
<beans:entry key="hibernate.dialect" value="${hibernate.dialect}" />
...
</beans:map>
</beans:property>
</beans:bean>

Related

Spring 4 Hikari Connection Pool ClassCastException

I wish to use Hikari Connection Pool in my Spring 4 application. The database is Google Cloud SQL Postgres database.
I have the following dependency in pom.xml:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.1.1</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.3.1</version>
</dependency>
In my applicationContext.xml, I have:
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="springHikariCP" />
<property name="connectionTestQuery" value="SELECT 1" />
<property name="dataSourceClassName" value="org.postgresql.Driver" />
<property name="maximumPoolSize" value="10" />
<property name="idleTimeout" value="30000" />
<property name="dataSourceProperties">
<props>
<prop key="url">jdbc:postgresql://google/mydatabase?cloudSqlInstance=projectId:regionName:myInstance&socketFactory=com.google.cloud.sql.postgres.SocketFactory</prop>
<prop key="user">postgres</prop>
<prop key="password">mypassword</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref="hikariConfig" />
</bean>
But I'm getting the following exception:
Caused by: java.lang.ClassCastException: Cannot cast org.postgresql.Driver to javax.sql.DataSource
at java.lang.Class.cast(Class.java:3369)
at com.zaxxer.hikari.util.UtilityElf.createInstance(UtilityElf.java:102)
What could be going wrong?
The org.postgresql.jdbc.Driver is not a javax.sql.DataSource, it is a java.sql.Driver, so it doesn't work for the property dataSourceClassName as that property expects a javax.sql.DataSource class name.
If you want to use the driver (and not a DataSource), then you should use the property driverClassName.
So:
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="springHikariCP" />
<property name="connectionTestQuery" value="SELECT 1" />
<property name="driverClassName" value="org.postgresql.Driver" />
...
Use Hikari recommended datasource for PostgreSQL: org.postgresql.ds.PGSimpleDataSource
<property name="dataSourceClassName" value="org.postgresql.ds.PGSimpleDataSource" />
Database Driver DataSource class
PostgreSQL pgjdbc-ng com.impossibl.postgres.jdbc.PGDataSource
PostgreSQL PostgreSQL org.postgresql.ds.PGSimpleDataSource

No qualifying bean of type 'java.lang.Class<org.springframework.data.repository.Repository<?, ?>>' available

I use spring data jpa (using CrudRepository interface) in my project and have declared my repository interface like this :
/**
* Repository implementation {#link CrudRepository} for {#link Client} entity
* #author rsone.
*/
public interface ClientRepository extends CrudRepository<Client, Integer> {
}
And have my hibernate config like bellow :
<tx:annotation-driven transaction-manager="hibernateTransactionManager" />
<context:component-scan base-package="com.rsone.mga.*" />
<jpa:repositories base-package="com.rsone.mga.repository" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="hibernateTransactionManager"/>
<bean id="datasource" parent="abstractDataSource">
<property name="dataSourceName" value="mgaDS" />
<property name="driverClass" value="${database.mga.jdbc.driver}" />
<property name="jdbcUrl" value="${database.mga.jdbc.url}" />
<property name="user" value="${database.mga.jdbc.user}" />
<property name="password" value="${database.mga.jdbc.pass}" />
<property name="preferredTestQuery" value="SELECT 1 FROM DUAL" />
</bean> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
<property name="fetchSize" value="5000" />
<property name="cacheQueries" value="true" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
</props>
</property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<!-- spring based scanning for entity classes>-->
<property name="packagesToScan" value="com.scor.mga.db"/>
</bean>
<!-- Enables the Hibernate #Transactional programming model -->
<tx:annotation-driven transaction-manager="hibernateTransactionManager" />
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<!--<property name="generateDdl" value="true"/>-->
<property name="database" value="SQL_SERVER"/>
</bean>
But When I try to run my project it give me that error (knowing that the base package of my repositories is com.rsone.mga.repository) :
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.Class<org.springframework.data.repository.Repository<?, ?>>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1466)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1097)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1059)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
Edit
I use version 1.11.0.RELEASE of spring-data-jpa:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.11.0.RELEASE</version>
</dependency>
I had the same problem in my maven project.
So this below is not working
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
together with
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>1.5.4.RELEASE</version>
</dependency>
Solution
It was solved by updating to the newest Spring boot release :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
Doing this already solved the problem.
It looks like the spring data tags are not backwards compatible with previous versions (other than the managed version).
So I would also recommend removing the version tag from the spring-data-cassandra dependency. Apparently Spring boot 1.5.1.RELEASE manages spring-data-cassandra 1.5.0.RELEASE.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
</dependency>
It doesn't seem to be an error in your configuration files.
It look like you have an #Autowired on a field of type java.lang.Class<org.springframework.data.repository.Repository<?, ?>> in one of the beans that are scanned.

java.lang.ClassNotFoundException: org.eclipse.persistence.internal.jpa.rs.metadata.model.Link not found

I am trying to inject EntityManager in a OSGi bundle but I am getting an error-
[EL Severe]: 2016-07-29 08:34:19.029--ServerSession(1711371450)--java.lang.NoClassDefFoundError: org/eclipse/persistence/internal/jpa/rs/metadata/model/Link
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.getDeclaredMethods(Unknown Source)
at org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getDeclaredMethods(PrivilegedAccessHelper.java:339)
at org.eclipse.persistence.internal.jpa.metadata.listeners.EntityListenerMetadata.getDeclaredMethods(EntityListenerMetadata.java:249)
at org.eclipse.persistence.internal.jpa.metadata.listeners.EntityClassListenerMetadata.process(EntityClassListenerMetadata.java:89)
at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.processListeners(EntityAccessor.java:1226)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor.addEntityListeners(MetadataProcessor.java:140)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:634)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getAbstractSession(EntityManagerFactoryDelegate.java:205)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:305)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:337)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:310)
at sun.reflect.GeneratedMethodAccessor39.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.aries.jpa.container.impl.QuiesceEMFHandler.invoke(QuiesceEMFHandler.java:55)
at com.sun.proxy.$Proxy37.createEntityManager(Unknown Source)
at org.apache.aries.jpa.container.context.transaction.impl.JTAEntityManagerHandler.getPersistenceContext(JTAEntityManagerHandler.java:125)
at org.apache.aries.jpa.container.context.transaction.impl.JTAEntityManagerHandler.invoke(JTAEntityManagerHandler.java:187)
at com.sun.proxy.$Proxy38.contains(Unknown Source)
at icom.leader.application.entitymanager.EventDao.insert(EventDao.java:33)
at icom.leader.application.entitymanager.EventDao.doExecute(EventDao.java:28)
at org.apache.karaf.shell.console.AbstractAction.execute(AbstractAction.java:34)
at org.apache.karaf.shell.console.OsgiCommandSupport.execute(OsgiCommandSupport.java:41)
at org.apache.karaf.shell.commands.basic.AbstractCommand.execute(AbstractCommand.java:34)
at org.apache.karaf.shell.compat.CommandTracker$1.execute(CommandTracker.java:109)
at org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:67)
at org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:87)
at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:480)
at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:406)
at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108)
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:182)
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:119)
at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:94)
at org.apache.karaf.shell.impl.console.ConsoleSessionImpl.run(ConsoleSessionImpl.java:268)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: org.eclipse.persistence.internal.jpa.rs.metadata.model.Link not found by com.knorrbremse.icom.leader.application [313]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1558)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:79)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1998)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 37 more
what could be the problem ?
below are my files -
pom.xml :
<dependency>
<groupId>com.knorrbremse.icom</groupId>
<version>2.0.0-SNAPSHOT</version>
<artifactId>icom.leader.platfrom</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.eclipse.persistence/eclipselink -->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1200-jdbc41</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>4.0.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.transaction/jta -->
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
</dependency>
blueprint.xml :
<blueprint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.2.0"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"
default-activation="eager">
<bean id="icomOffboardDataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="url"
value="jdbc:postgresql://localhost:5432/enetity_manager" />
<property name="username" value="postgres" />
<property name="password" value="kbroot" />
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="initialSize" value="10" />
<property name="maxTotal" value="50" />
<property name="maxIdle" value="20" />
</bean>
<bean id="icomOffboardXADataSource" class="org.apache.commons.dbcp2.managed.BasicManagedDataSource"
destroy-method="close">
<property name="url"
value="jdbc:postgresql://localhost:5432/enetity_manager" />
<property name="username" value="postgres" />
<property name="password" value="kbroot" />
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="initialSize" value="10" />
<property name="maxTotal" value="50" />
<property name="maxIdle" value="20" />
<property name="transactionManager" ref="transactionManager" />
</bean>
<service ref="icomOffboardXADataSource" interface="javax.sql.DataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/icomOffboardXADataSource" />
<entry key="icom.isXa" value="true" />
</service-properties>
</service>
<service ref="icomOffboardDataSource" interface="javax.sql.DataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/icomOffboardDataSource" />
<entry key="icom.isXa" value="false" />
</service-properties>
</service>
<bean id="eventDao" class="icom.leader.application.entitymanager.EventDao">
</bean>
<service ref="eventDao" interface="icom.leader.application.entityif.EventDaoIF" />
<bean id="entityManagerService" class="icom.leader.application.entitymanager.EntityManagerService">
<jpa:context unitname="icomentitymanager" property="entityManager" />
<tx:transaction method="*" value="Required" />
</bean>
<service ref="entityManagerService" interface="icom.leader.entitymanager.EntityManagerIf" />
<reference id="entityManager" activation="eager" availability="mandatory"
interface="icom.leader.entitymanager.EntityManagerIf">
<reference-listener bind-method="bindDBManagerService"
unbind-method="unbindDBManagerService">
<ref component-id="eventDao" />
</reference-listener>
</reference>
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
<command name="leader-test/create-sample-data1">
<action class="icom.leader.application.entitymanager.EventDao">
</action>
</command>
</command-bundle>
<reference id="transactionManager" interface="javax.transaction.TransactionManager" />
persistance.xml :
<persistence-unit name="icomentitymanager" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/icomOffboardXADataSource)
</jta-data-source>
<non-jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/icomOffboardDataSource)
</non-jta-data-source>
<class>icom.leader.application.entitymanager.Event</class>
<class>icom.leader.platform.entities.VehicleType</class>
<class>icom.leader.platform.entities.Vehicle</class>
<!-- <mapping-file>META-INF/leader_orm.xml</mapping-file> -->
<properties>
<property name="eclipselink.ddl-generation" value="create-tables" />
<property name="eclipselink.weaving" value="true"/>
<property name="eclipselink.target-database" value="PostgreSQL"/>
<property name="eclipselink.target-server"
value="org.apache.aries.jpa.eclipselink.adapter.platform.OSGiTSServer"/>
<!--<property name="eclipselink.ddl-generation" value="none"/>-->
<!--<property name="eclipselink.ddl-generation.output-mode" value="database"/>-->
<!-- for file creation -->
<property name="eclipselink.ddl-generation" value="create-tables"/>
<property name="eclipselink.ddl-generation.output-mode" value="sql-script"/>
<property name="eclipselink.application-location" value="data/tmp/"/>
<property name="eclipselink.create-ddl-jdbc-file-name" value="application_schema.sql"/>
</properties>
</persistence-unit>
Implementation file :
public class EventDao extends OsgiCommandSupport implements EventDaoIF {
private static EntityManager entityManager;
#Override
protected Object doExecute() throws Exception {
insert();
return ".. done";
}
void insert(){
if (entityManager.contains(Event.class)){
System.out.println("true");
} else {
System.out.println("false");
}
}
public void bindDBManagerService(EntityManagerIf entityManager, Map props) {
EventDao.entityManager=entityManager.getEntityManager();
}
public void unbindDBManagerService(EntityManagerIf entityManager, Map props){
EventDao.entityManager=entityManager.getEntityManager();
}
when I am trying to use any method of entityManager then it gives the above error.
I guess it happens from conflict jars, you should be using one or the other not both, if not try versions above 2.6.0. I would guess these two libraries are likely the same used in different contexts
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.6.0</version>
</dependency>
or
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
<version>2.6.0</version>
</dependency>

Error using OneToOne/ManyToOne with JPA and Multiple Data Sources

I've managed to configure JPA with multiple datasources, but I get the following error when bringing up my server (Websphere liberty):
org.hibernate.AnnotationException: #OneToOne or #ManyToOne onxxx.AccountBalance.currency references an unknown entity: xxx.Currency
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(T oOneFkSecondPass.java:109)
at org.hibernate.cfg.Configuration.processEndOfQueue( Configuration.java:1521)
at org.hibernate.cfg.Configuration.processFkSecondPas sInOrder(Configuration.java:1446)
at org.hibernate.cfg.Configuration.secondPassCompile( Configuration.java:1351)
at org.hibernate.cfg.Configuration.buildSessionFactor y(Configuration.java:1733)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>( EntityManagerFactoryImpl.java:94)
at org.hibernate.ejb.Ejb3Configuration.buildEntityMan agerFactory(Ejb3Configuration.java:905)
The application deploys correctly if all the DAO are declared in the same database, but it fails if I move any of them to a second database. Is it possible to used JPA bags (OneToOne, ManyToOne, ManyToMany) with multiple data sources?
Relevant parts of the configuration:
Context:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/xxxwas"
cache="true" resource-ref="true" lookup-on-startup="false"
proxy-interface="javax.sql.DataSource" />
<bean id="h2dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url"
value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT=3" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
<tx:jta-transaction-manager />
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit .DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath:META-INF/persistence.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="h2" value-ref="h2dataSource" />
<entry key="mysql" value-ref="dataSource" />
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="dataSource" />
</bean>
<bean id="integrationEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="integrationEntityManagerFactoryPU" />
<property name="jtaDataSource" ref="h2dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.Hibernat eJpaVendorAdapter">
<!-- <property name="showSql" value="true" /> -->
<property name="database" value="H2" />
<!-- <property name="generateDdl" value="true" /> -->
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="databaseEntityManagerFactoryPU" />
<property name="jtaDataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.Hibernat eJpaVendorAdapter">
<!-- <property name="showSql" value="true" /> -->
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<jpa:repositories base-package="xxx.impl.repository.integration"
query-lookup-strategy="create-if-not-found"
entity-manager-factory-ref="integrationEntityManagerFactory">
</jpa:repositories>
<!-- Configures Spring Data JPA and sets the base package of my DAOs. -->
<jpa:repositories base-package="xxx.impl.repository"
query-lookup-strategy="create-if-not-found"
entity-manager-factory-ref="entityManagerFactory">
</jpa:repositories>
Server.xml
<dataSource id="xxxwas" jndiName="jdbc/xxxwas" supplementalJDBCTrace="true" type="javax.sql.XADataSource">
<jdbcDriver javax.sql.ConnectionPoolDataSource="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" javax.sql.DataSource="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" javax.sql.XADataSource="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" libraryRef="MySQLLib"/>
<properties databaseName="xxx" password="xxx" portNumber="3306" serverName="localhost" user="root"/>
</dataSource>
Web.xml
<resource-ref>
<res-ref-name>jdbc/xxxwas</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="databaseEntityManagerFactoryPU" transaction-type="JTA">
<class>xxx.impl.bo.AccountBalance</class>
<!-- WORKS IF DEFINED HERE -->
<!-- <class>xxx.impl.bo.Currency</class> -->
<properties>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
<!-- <property name="hibernate.current_session_context_class"value="thread" /> -->
<!--<prop key="hibernate.transaction.flush_before_completion">false</prop>-->
<!--<prop key="hibernate.transaction.auto_close_session">true</prop>-->
<!--<prop key="hibernate.current_session_context_class">thread</prop>-->
<!--<prop key="javax.persistence.transactionType">JTA</prop>-->
<!--<prop key="hibernate.connection.release_mode">auto</prop>-->
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="net.sf.ehcache.configurationResourceName" value="ehcache_database.xml"/>
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>
<!-- <property name="hibernate.archive.autodetection" value="class, hbm"/> -->
<!-- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> -->
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
<property name="hibernate.use_sql_comments" value="true"/>
<property name="hibernate.generate_statistics" value="true"/>
</properties>
</persistence-unit>
<persistence-unit name="integrationEntityManagerFactoryPU" transaction-type="JTA">
<!-- DOES NOT WORK IF DEFINED HERE -->
<class>xxx.impl.bo.Currency</class>
<properties>
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
<property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
</persistence-unit>
</persistence>
I know its too late, but I had the same probleme.
I'm working on Oracle database, the same database with two schemas (users)
My solution was to give the first user access to all tables in the second user schema.
After that, on JPA Entity annotation, precise the schema for each entity.
This way, hibernate generate SQL queries with schema :
select field1, field2 from USER1.Table1 INNER JOIN USER2.TABLE2 ON .....
It work this way because user1 have access to user2 tables with a grant, but the two schemas must be in the same database, otherwise you have to create a dblink and a synonym.

org.springframework.orm.hibernate4 not found

I'm try to get sessionFactory bean in my Jtest then it's throws this exception:
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.orm.hibernate4.LocalSessionFactoryBean] for bean with name 'sessionFactory' defined in class path resource [Spring.hibernate.xml]; nested exception is java.lang.ClassNotFoundException: org.springframework.orm.hibernate4.LocalSessionFactoryBean
my JtestCode:
#Test
public void test(){
ApplicationContext ac=new ClassPathXmlApplicationContext(new String[]{"classpath:Spring.xml","classpath:Spring.hibernate.xml"});
SessionFactory session=(SessionFactory) ac.getBean("sessionFactory");
if(session==null){
System.out.println("it's null");
}
}
Here is my Spring.hibernate.xml:
<!-- JNDI方式配置数据源 -->
<!-- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="${jndiName}"></property> </bean> -->
<!-- 配置数据源 -->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_username}" />
<property name="password" value="${jdbc_password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="0" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="20" />
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="20" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="0" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
<!-- <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->
<property name="validationQuery" value="${validationQuery}" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="true" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="25200000" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="1800" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" />
<!-- 监控数据库 -->
<!-- <property name="filters" value="stat" /> -->
<property name="filters" value="mergeStat" />
</bean>
<!-- 配置hibernate session工厂 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
</props>
</property>
Did I forget to add jar or which jar that include org.springframework.orm.hibernate4.LocalSessionFactoryBean? .I need someone help
Do you have org.springframework.orm-N.N.N.jar in your classpath?
Have a good look at the error message, make sure there aren't other Spring or external libraries as pre-requisites -- which would cause an indirect ClassNotFoundError.

Resources