Entity Manager null everytime on running Junit tests - java

I am new to Spring and JPA. I developed a project using Spring4 , spring scheduler and JPA and now I want to test my code using Junit test cases. I started with testing my DAO methods. Here is the source code:
This class does the triggering task for the scheduler
public class TriggerTask {
#Autowired
private TriggerDaoBean triggerDaoBean;
public void executeDailyTask() {
try{
List<User> users=triggerDaoBean.getClients();
if (null != users && users.size()>0){
//do some task
}
}catch(Exception e){
}
}}
The DAO bean is :
#Stateless
public class TriggerDaoBean implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext
private EntityManager em;
public List<User> getUsers() {
List<User> userList = new ArrayList<User>();
Query query = em.createQuery(
"SELECT user FROM USER user");
userList = (List<User>)query.getResultList();
if (null != userList && userList.size() > 0) {
return userList;
} else {
return null;
}
}
....
}
I wrote the below test case:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/spring-quartz-test.xml" })
#TransactionConfiguration(defaultRollback=true)
#Transactional
public class TriggerTest {
#Autowired
TriggerDaoBean triggerDaoBean;
#Test
public void getUserListTest() {
triggerDaoBean.getUsers();
}
}
The content of spring-quartz-test.xml is as follows:
<bean id="triggerTask" class="com.test.service.TriggerTask">
<property name="triggerDaoBean" ref="triggerDaoBean"/>
</bean>
<bean id="triggerDaoBean"
class="com.test.service.TriggerDaoBean">
</bean>
<bean id="runsrJobDaily" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="triggerTask" />
<property name="targetMethod" value="executeDailyTask" />
</bean>
And the persistence.xml is as follows:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="forge-default" transaction-type="JTA" >
<description>Forge Persistence Unit</description>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MySqlDS</jta-data-source>
<class>com.test.persistence.entity.User</class>
<properties>
<!-- <property name="hibernate.hbm2ddl.auto" value="create-drop"/> -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<!--
<property name="hibernate.ejb.cfgfile" value="modified.hibernate.cfg.xml"/>
-->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.transaction.flush_before_completion" value="true"/>
</properties>
</persistence-unit>
</persistence>
java:/MySqlDS is the JNDI name of datasource.
Everytime I run my test, NullPointerException comes for the EntityManager.
Am I doing something wrong?

I'm my case, you need to append two annotations on your test class.
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = SpringBootApplicationClass.class)

You have to define your entityManager in spring, I do not see the entityManager in the code you posted, you can do it in this way
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="example" />
</bean>
<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Be aware that your are defining your transaction type as JTA in persistence.xml, really do you need global transactions? if not, delete transaction-type="JTA" in persistence.xml
Another thing, for test purposes would be better to use a test database like H2. You can define it in test spring context inside src/test/resources
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence-test.xml"/>
<property name="persistenceUnitName" value="example-test" />
<property name="dataSource" ref="dataSourceTest"/>
</bean>
<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="dataSourceTest" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="org.h2.tools.Server-WebServer" class="org.h2.tools.Server"
factory-method="createWebServer" init-method="start" lazy-init="true">
<constructor-arg value="-web,-webAllowOthers,-webPort,11111" />
</bean>
this way you can control the database state, each test will create a database in memory, you can define an import.sql in src/test/resource in order to fill your tables with test data. You have to add de h2 dependency in pom.xml
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.174</version>
<scope>test</scope>
</dependency>

Related

spring boot database insert not working

I have a problem with my spring boot configuration in xml I created this configuration :
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="false"/>
<property name="database" value="ORACLE"/>
</bean>
<bean id="dataSource" primary="true" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:20300:test"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="entityManagerFactory" primary="true" 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="model.entity"/>
<property name="persistenceUnitName" value="msPersistenceUnit" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="controllerService"
class="...impl.ControllerServiceImpl">
<property name="entityManager" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
<constructor-arg index="0" ref="entityManagerFactory" />
</bean>
And I had the java code like this :
public void setEntityManager(final HibernateEntityManagerFactory entityManager) {
final RepositoryFactorySupport factorySupport = new JpaRepositoryFactory(entityManager.createEntityManager());
controlRepository = factorySupport.getRepository(ObjControlRepository.class);
}
when i'm using find method it's ok, but when I'm doing a save, there are not exception but the value it's not insert.
Thank your for your help.
[Edit]
To save I'm using :
/**
* The Interface ObjControlRepository.
*/
public interface ObjControlRepository extends CrudRepository<ObjControl, String> {
}
And I'm calling the method like that :
controlRepository.save(newValue);
You should try to explicitly set the hibernate.hbm2ddl.auto variable to auto. This will prevent your application to release previous data when you start your application.
You can learn more about the hibernate.hbm2ddl.auto variable here.
You should use transactions and commit the transaction in order to save an entity.
So Use #Transactionl annotation on your service layer, like this:
#Transactional
public class ControllerServiceImpl {
...
}
As ControllerServiceImpl is already declared as a bean in spring configuration file, Spring will take care about committing the transaction once you save an entity.

Spring fails to choose between multiple TransactionManager beans

I migrating my spring batch processes from a command line application to a spring boot webapp including the spring-batch-admin-manager (version 1.3.0).
My old command-line app worked with two JPA databases and two TransactionManager instances. I remember it has been a hell of configuration to get that running. I expected things to get more comfortable, when starting with Spring Boot, but now things seem to be even worse:
Spring is unable to choose the right TransactionManager instance for transactions.
On application startup Spring is visiting one of my classes to execute a #PostConstruct annotated code block, from where a transactional method should be called.
#PostConstruct
public void init() {
eventType = eventTypeBo.findByLabel("Sport"); // <-- Calling transactional method
//...
}
From here the error is thrown. Have a look at the stacktrace:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined:
expected single matching bean but found 2: transactionManager,osm.transactionManager
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:313)
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:337)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:252)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy89.findByLabel(Unknown Source)
at com.company.model.service.impl.EventTypeBo.findByLabel(EventTypeBo.java:43)
at com.company.batch.article.utils.converter.SomeConverter.init(SomeConverter.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
//...
As you can see from the error log my TransactionManagers are named "transactionManager" and "osm.transactionManager". Transactions are configured accordingly:
<!-- DATABASE 1 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- DATABASE 2 -->
<bean id="osm.transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="osm.entityManagerFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="osm.transactionManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="osmServiceOperation"
expression="execution(* com.qompa.osm.service.spec..*Service.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="osmServiceOperation" />
</aop:config>
I am using two different GenericDao implementions to distinguish between PersistenceContexts when accessing data:
public class OsmGenericDao<T> implements IGenericDao<T> {
#PersistenceContext(unitName = "osm.entityManagerFactory")
protected EntityManager em;
//...
}
public class GenericDao<T> implements IGenericDao<T> {
#PersistenceContext(unitName = "entityManagerFactory")
protected EntityManager em;
//...
}
Everything seems to be fproperly configured: But still it fails!
EDIT: As far as I can follow Spring's TransactionAspectSupport tries to determine the transactionmanager via a qualifier (determineTransactionManager). Because the findByLabel's #Transactional annotation has no qualifier it tries to determine the correct bean with help of DefaultListableBeanFactory"s getBean method, where two beans of the same type are found that can't be further distinguished.
There must be a way to tell Spring to choose the transactionManager according to the persistence context!
Any ideas?
Here's my working configuration with 2 persistence contexts:
<!-- METADATA -->
<!-- Metadata connection pool -->
<bean id="scprMetadataDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"
value="..." />
<property name="jdbcUrl"
value="..." />
<property name="user"
value="..." />
<property name="password"
value="..." />
<property name="maxPoolSize"
value="..." />
<property name="minPoolSize"
value="..." />
</bean>
<!-- Metadata entity manager factory -->
<bean id="scprMetadataEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="H2" />
</bean>
</property>
</bean>
<!-- Metadata transaction manager -->
<bean id="scprMetadataTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="scprMetadataEntityManagerFactory" />
</bean>
<!-- DOMAIN -->
<!-- Domain connection pool -->
<bean id="scprDomainDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"
value="..." />
<property name="jdbcUrl"
value="..." />
<property name="user"
value="..." />
<property name="password"
value="..." />
<property name="maxPoolSize"
value="..." />
<property name="minPoolSize"
value="..." />
</bean>
<!-- Domain entity manager factory -->
<bean id="scprDomainEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="SQL_SERVER" />
</bean>
</property>
</bean>
<!-- Domain transaction manager -->
<bean id="scprDomainTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="scprDomainEntityManagerFactory" />
</bean>
Other config (missing in your question):
<persistence-unit name="scpr_metadata" transaction-type="RESOURCE_LOCAL">
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>...</class>
<class>...</class>
<class>...</class>
</persistence-unit>
<persistence-unit name="scpr_domain" transaction-type="RESOURCE_LOCAL">
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>...</class>
<class>...</class>
<class>...</class>
</persistence-unit>
And in my java class:
#Repository
public final class MetadataRepositoryImpl implements MetadataRepository {
#PersistenceContext(unitName = "scpr_metadata")
private EntityManager em;
And:
#Repository
public final class DomainRepositoryImpl implements DomainRepository {
#PersistenceContext(unitName = "scpr_domain")
private EntityManager em;
Hope this helps you.

Using non-Spring Hibernate JPA DAO classes in a Spring application

I have a Maven project with a Hibernate JPA persistence layer that I would like to incorporate into some Spring applications (one a web application, and one a command line tool), but I am unsure how to configure this. The persistence module includes model classes, DAO classes, and the persistence.xml file. I have configured Spring's EntityManagerFactory to use the existing persistence.xml, but instantiating the DAO classes always results in a NullPointerException, as they seem to be unable to locate the persistence unit by name. Is it possible to use Hibernate JPA classes created outside Spring's context in a Spring application?
persistence.xml
<persistence-unit name="myapp" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.show_sql" value="false" />
</properties>
</persistence-unit>
application-context.xml
<bean id="allProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:config/db.properties</value>
<value>classpath:config/log4j.properties</value>
</list>
</property>
</bean>
<context:component-scan base-package="com.company.app" />
<context:annotation-config />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="persistenceUnitName" value="myapp"/>
<property name="dataSource" ref="datasource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="${hibernate.dialect}" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="datasource" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
</bean>
UserDao.java
public class UserDao extends AbstractDao<User> {
public UserDao() {
super("myapp");
}
// CRUD methods
AbstractDao.java
public abstract class AbstractDao<T extends DataObject> {
private EntityManagerFactory emf;
private final static Logger log = LoggerFactory.getLogger(AbstractDao.class);
private final Map<String, Map<String, String>> connectionDictionaries =
new HashMap<String, Map<String, String>>();
public AbstractDao(String dataSourceName) {
try {
setUpDataSource(dataSourceName);
} catch (IOException e) {
log.error("Unable to load: ", AbstractDataConstants.DB_PROPERTIES_FILE);
e.printStackTrace();
}
}
...
// Other methods

Persistence Injection fails, NPE

I'm trying to inject an EntityManager into my Tomcat 7 application.
I have a class that manages my queries (service.PresentatieDao), in which I have this code:
private EntityManager em;
#PersistenceContext
public void setEntityManager(EntityManager em) {
this.em = em;
}
In my applicationContext.xml I have this line:
<bean name = "presentatieDao" class="service.PresentatieDao"/>
And finally in my dispatcher-servlet.xml I have this code (copy paste with edits to point correctly):
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource" p:basename="messages" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/Project2-DB"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>domein</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="database" value="MYSQL"/>
</bean>
</property>
</bean>
<bean id="transactionManager"
class=" org.springframework.orm.jpa.JpaTransactionManager ">
<constructor-arg ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
And in my controller:
#Autowired
private PresentatieDao presentatieDao;
I have gotten all types of errors about my mapping, which I have solved.
Now I get a NullPointerException at this line in my PresentatieDao:
return em.createQuery("select p from Presentatie p").getResultList();
the em is null in this case. Any ideas what might be wrong here?
Ok i checked Spring docummentation.It should work like this
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" />
<bean name = "presentatieDao" class="service.PresentatieDaoImpl"/>
<bean class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven />
and
public class PresentatieDaoImpl implements PresentatieDao {
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this. entityManager = entityManager;
}
public Collection loadProductsByCategory(String category) {
return entityManager.createQuery("from Product p where p.category = :category")
.setParameter("category", category).getResultList();
}
}
for more:
https://spring.io/blog/2006/08/07/using-jpa-in-spring-without-referencing-spring
you can also check:
http://doanduyhai.wordpress.com/2011/11/21/spring-persistencecontext-explained/

Multiple Entity Manager issue in Spring when using more than one datasource

I have two entity managers in my applicationContext.xml which corresponds to two different databases. I can easily query database1 with entityManager1, but when I try to access database2 with entityManager2, I am not getting any results. I am using Spring+Hibernate+JPA.
Here is my ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans default-autowire="byName"
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="INFORMIX" />
<property name="showSql" value="true" />
</bean>
</property>
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="PU1" />
</bean>
<bean id="entityManagerFactory2"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource2" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="INFORMIX" />
<property name="showSql" value="true" />
</bean>
</property>
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="PU2" />
</bean>
<!-- Data Sources -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
<property name="url"
value="jdbc:db2://HOST_NAME:PORT_NO/DB_NAME:INFORMIXSERVER=SERVER_NAME;DELIMIDENT=y;" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="minIdle" value="2" />
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
<property name="url"
value="jdbc:db2://HOST_NAME:PORT_NO/DB_NAME2:INFORMIXSERVER=SERVER_NAME;DELIMIDENT=y;" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="minIdle" value="2" />
</bean>
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
lazy-init="false">
<property name="targetObject" ref="dataSource" />
<property name="targetMethod" value="addConnectionProperty" />
<property name="arguments">
<list>
<value>characterEncoding</value>
<value>UTF-8</value>
</list>
</property>
</bean>
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
lazy-init="false">
<property name="targetObject" ref="dataSource2" />
<property name="targetMethod" value="addConnectionProperty" />
<property name="arguments">
<list>
<value>characterEncoding</value>
<value>UTF-8</value>
</list>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
scope="prototype">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
<value>classpath*:META-INF/persistence2.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="localDataSource" value-ref="dataSource" />
<entry key="dataSource2" value-ref="dataSource2" />
</map>
</property>
<property name="defaultDataSource" ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory2" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<tx:annotation-driven transaction-manager="transactionManager2" />
<!-- MORE Action and DAO beans -->
</beans>
This is my service layer code which works fine with enityManager1:
#Transactional
public class StatesDAO implements IStatesDAO {
private EntityManager em;
#PersistenceContext(unitName = "PU1")
public void setEntityManager(EntityManager em) {
this.em = em;
}
private EntityManager getEntityManager() {
return em;
}
#SuppressWarnings("unchecked")
public List<States> findAll() {
logger.info("finding all States instances");
try {
final String queryString = "select model from States model";
Query query = getEntityManager().createQuery(queryString);
return query.getResultList();
} catch (RuntimeException re) {
throw re;
}
}
}
My two persitence.xml files look like this:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
<persistence-unit name="PU1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.jpa.entity.States</class>
</persistence-unit>
</persistence>
and
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
<persistence-unit name="PU2" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.jpa.other.entity.States</class>
</persistence-unit>
</persistence>
If I change my service layer (as shown below), I get no results. Basically the size of the list is zero:
#Transactional
public class StatesDAO implements IStatesDAO {
private EntityManager em;
#PersistenceContext(unitName = "PU2")
public void setEntityManager(EntityManager em) {
this.em = em;
}
private EntityManager getEntityManager() {
return em;
}
#SuppressWarnings("unchecked")
public List<com.jpa.other.entity.States> findAll() {
logger.info("finding all States instances");
try {
final String queryString = "select model from States model";
Query query = getEntityManager().createQuery(queryString);
return query.getResultList();
} catch (RuntimeException re) {
throw re;
}
}
}
So basically you can see is that I have two entities(States) with exactly same structure and in order to differentiate from each other I have put them into separate packages
According to my knowledge I am not doing anything crazy here but still it doesn't seem to be working. How is this problem caused and how can I solve this?
Follow-up: One thing I forgot to mention is that even though there are two different databases but the database server name is same. I don't know if this could be a useful information.So thought of sharing it.
This is the exception I am getting now:
16:24:44,732 INFO [STDOUT] Hibernate: select state0_.state as col_0_0_ from states state0_
16:24:44,753 WARN [JDBCExceptionReporter] SQL Warning: 36106, SQLState: 01I01
16:24:44,753 WARN [JDBCExceptionReporter] IDS SQL Warning: SQLCODE=36106, SQLSTATE=01I01, SQLERRMC=0;819;informix;;IDS/NT32;1;1;0;819;0;, DRIVER=4.7.85
I've hit the same exact issue, but with multiple Hibernate session factories: 2 DBs with the same structure, I didn't want to have 2 identical sets of DAOs, etc. While my experience was with Hibernate, I suspect you could use the same solution: Spring's AbstractRoutingDataSource. It allows you to configure your app to determine at runtime which data source to use, based on a value set on the ThreadLocal. See http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/ for an introduction. What ends up happening is that the dataSource ref in your factory will point not at a hard-coded dataSource bean, but at the AbstractRoutingDataSource. To set the toggle per-thread, use an #Aspect to determine which DB to hit.

Categories