This is the first question I have posted here, so apologies in advance if I have violated any conventions or etiquette. I can't seem to get rid of the following exception:
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:915)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:257)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 79 more
Caused by: org.hibernate.HibernateException: Errors in named queries: User.findByUserNameAndPassword
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:426)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1872)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:906)
The entity on which I have my named query looks like this:
#Entity
#Table(name="USERS")
#NamedQueries
({
#NamedQuery(name="User.findByUserNameAndPassword", query="SELECT u FROM User u WHERE u.username = :username AND u.password = :password")
})
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name="USERS_ID_GENERATOR", sequenceName="PERSONAL.GLOBALSEQUENCE")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="USERS_ID_GENERATOR")
private long id;
private String notes;
#Column(name="PASSWORD")
private String password;
#Column(name="USERNAME")
private String username;
...
and I am executing (or trying to!) this query in a
UserServiceImpl class
like this:
#Transactional(readOnly=true)
public User authenticate(String userName, String password) {
List<User> usersList = em.createQuery("User.findByUserNameAndPassword", User.class).setParameter("username", userName).setParameter("password", password).getResultList();
User firstUserFromList = usersList.get(0);
return firstUserFromList;
}
I have tried a lot of things but have been stuck on this for a while now. Any help or guidance will be really appreciated.
Cheers,
My applicationContext.xml file looks like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd">
<context:component-scan base-package="com.transience.sandbox" />
<mvc:annotation-driven />
<tx:annotation-driven />
<mvc:resources mapping="/static_resources/**" location="/static_resources/" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /></property>
<property name="packagesToScan" value="com.transience.sandbox.domain"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<jee:jndi-lookup id="dataSource" jndi-name="oracleXEDS"/>
<jpa:repositories base-package="com.transience.sandbox.domain" entity-manager-factory-ref="emf" transaction-manager-ref="transactionManager"/>
</beans>
And I am using Spring (core, webmvc, context, orm, jdbc, tx) 3.1, Hibernate 3.6.8, Spring-data-jpa 1.2.0, Weblogic 12c, and OracleXE. And Maven.
Try using em.createNamedQuery() instead of em.createQuery().
Few initial observations :
You have defined entity as USER which is a reserved word in Oracle. Therefore query SELECT u FROM User u ... might create issue when it gets converted into the native query.
Try looking into the generated query by setting appropriate logging level & execute it. Also try to avoid using reserved words/keywords & specify more meaningful conventions.
Related
I am developing a java Spring Hibernate application with mssql database. But i am not able to establish connection with mssql database.
[Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBCException: Could not open connection]
my applicationContext.xml is given below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- Enable autowire -->
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.adapt.smileboard"></context:component-scan>
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:resources mapping="/resources/**" location="/resources/"></mvc:resources>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.jdbc.sqlserver.SQLServerDriver" ></property>
<property name="url" value="jdbc:sqlserver://localhost:1433;databaseName=test;" ></property>
<property name="username" value="user" ></property>
<property name="password" value="pwd" ></property>
</bean>
<!-- Session Factory Declaration -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" ></property>
<property name="packagesToScan" value="com.adapt.smileboard.entity" ></property>
<property name="hibernateProperties">
<props>
<!-- SQL Dialect -->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!-- Your required Database Name -->
<prop key="hibernate.default_schema">smileBoardDB</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
<prop key="format_sql">true</prop>
<prop key="use_sql_comments">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" ></property>
</bean>
</beans>`
You are using a Microsoft SQL Server driver and MySQL dialect.
Use org.hibernate.dialect.SQLServerDialect for Microsoft SQL Server.
Refer this.
I have this exception :
org.hibernate.MappingException: persistent class not known:
java.lang.Long
I'm using Hibernate 5.1.0.Final and spring-orm 4.2.4.RELEASE
My spring configuration file (spring.xml) :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/ecollection" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="hibernateAnnotatedSessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.ecollection.model.Adresse</value>
<value>com.ecollection.model.Utilisateur</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="utilisateurDao" class="com.ecollection.dao.UtilisateurDaoImpl">
<property name="sessionFactory" ref="hibernateAnnotatedSessionFactory" />
</bean>
<bean id="adresseDao" class="com.ecollection.dao.AdresseDaoImpl">
<property name="sessionFactory" ref="hibernateAnnotatedSessionFactory" />
</bean>
And I have two MySQL tables, User and Address.
User = Id, Name and Firstname
Address = Id, Street, City and UserId
for UserId in my Address entitybean, I'm doing this :
#OneToOne
#JoinColumn(name="id")
public Long getIdUtilisateur() {
return idUtilisateur;
}
You can not use a non entity as a target for OneToOne or JoinColumn, as you did here:
#OneToOne
#JoinColumn(name="id")
public Long getIdUtilisateur() {
return idUtilisateur;
}
Instead you can use this approach for mapping Utilisateur and Address relationship:
#OneToOne
#JoinColumn(name="id")
public Utilisateur getUtilisateur() {
return utilisateur;
}
Of course, Utilisateur should be an entity:
#Entity
public class Utilisateur { ... }
Hi I'm having a problem setting up hibernate on spring. I was able to make it work but it creates a lot of session on the database. From What i have notice it creates session for every bean on my spring.xml. Since I have 6 beans declared I also have 6 session on the database on application start Here is my code
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
xmlns:tx="http://www.springframework.org/schema/tx"
>
<!-- Uncomment and add your base-package here: <context:component-scan base-package="org.springframework.samples.service"/> -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:" />
<property name="username" value="Use" />
<property name="password" value="Pass" />
</bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<!-- <prop key="hibernate.current_session_context_class">managed</prop> -->
<prop key="hibernate.show_sql">true</prop>
<prop key="format_sql">true</prop>
</props>
</property>
</bean>
<bean id="PDao" class="com.PDaoImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
<bean id="PService" class="com.PServiceImpl">
<property name="pDao" ref="PDao" />
</bean>
<bean id="MNDao" class="com.MNDaoImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
<bean id="MNService" class="com.MNServiceImpl">
<property name="MNDao" ref="MNDao" />
</bean>
<bean id="SWDao" class="com.SWDaoImpl">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</bean>
<bean id="SWService" class="com.SWServiceImpl">
<property name="SWDao" ref="SWDao" />
</bean>
You need to use transactionManager to manage session for you.
Add the following lines of code to your spring.xml
....
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="yourSessionFactory" />
</bean>
....
Then you have to annotate your service impl classes #Transactional("transactionManager") to make transactionManager managing transactions through session
#Transactional("transactionManager")
public class PServiceImpl implements PServiceImpl{
....
Just an advice you can replace XML config for the DI by annotations to make it easy
in spring.xml, remove all your beans declarations (xxservice and xxxdao) and replace them by: <context:component-scan base-package="put here the package where your services and daos are lacated" />
your service must look like this :
#Service
#Transactional("transactionManager")
public class XXXServiceImpl implements XXXService{
#Autowired
private XXXDAO xxxDAO;
...
}
And your dao must look like :
#Repository
public class XXXDAOImpl implements XXXDAO {
#Autowired
private SessionFactory sessionFactory;
...
}
One more thing, add the tx schema in your file config header, your spring.xml should look like this :
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
I've just started my journey with Spring, so I'm a newbie.
I'm trying to write tests to DAO.
When I run tests the stack trace returns:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private pl.com.tt.persistence.TestEntityDaoJPA pl.com.tt.tests.TestPersistenceDAO.testEntityDaoJPA; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [pl.com.tt.persistence.TestEntityDaoJPA] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
It looks like I shouldn't use #Autowired above TestEntityDAO implementation. When I delete #Autowire annotation stack trace returns error with invocation method testEntityDaoJPA.getAll(sql).
This is my test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class TestPersistenceDAO extends AbstractTransactionalJUnit4SpringContextTests{
#Autowired
private TestEntityDaoJPA testEntityDaoJPA;
#Test
public void testDAO(){
String sql = "SELECT r FROM TestEntity r WHERE ROWNUM<200";
testEntityDaoJPA.getAll(sql);
}
}
My DAO class:
#Component
public class TestEntityDaoJPA implements TestEntityDao {
#Autowired
#PersistenceContext private EntityManager em;
#Transactional
public List<TestEntity> getAll(String sql){
TypedQuery<TestEntity> q = em.createQuery(sql, TestEntity.class );
List<TestEntity> result = q.getResultList();
return result;
}
}
XML context file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="pl.com.tt.tests" />
<context:annotation-config/>
<tx:annotation-driven/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url"
value="jdbc:oracle:thin:#192.168.80.128:1521:orcl" />
<property name="username" value="findfnorg" />
<property name="password" value="findfnorg" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="pl.com.tt.tests" />
<property name="persistenceProviderClass"
value="org.hibernate.ejb.HibernatePersistence" />
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
Your package is not scanned by spring.
You indicate:
<context:component-scan base-package="pl.com.tt.tests" />
But TestEntityDaoJPA is in pl.com.tt.persistence. So this package is not scanned and no bean is created.
Try to change to:
<context:component-scan base-package="pl.com.tt.tests,pl.com.tt.persistence" />
I have a Spring Batch application that has a Spring context configuration that normally each batch job would reference. This way each batch job uses the same entity manager.
batch-context.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- ... -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="myPersistenceUnit" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="com.example.domain" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class"> org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">100</prop>
<prop key="hibernate.jbc.batch_size">1000</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.use_sql_comments">false</prop>
</props>
</property>
</bean>
<!-- ... -->
</beans>
Now in my specific batch job context (call it ExampleBatch.xml) I want to add another package to scan to the already defined entityManagerFactory bean. Is this possible?
ExampleBatch.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">
<!-- ... -->
<import resource="classpath:batch-context.xml" />
<bean id="entityManagerFactoryWithExtraPackages"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
parent="entityManagerFactory">
<!-- How do I override the packagesToScan property on the already defined entityManagerFactory bean?-->
<property
name="packagesToScan"
value ="com.example.domain,com.example.domain.abstraction"
/>
</bean>
<!-- ... -->
</beans>
The way I have it right now will not work because it complains that "No unique bean of type [javax.persistence.EntityManagerFactory] is defined: expected single bean but found 2"
Is trying to override the "packagesToScan" property the right approach to take in this scenario? Is there a better way to accomplish this behavior?
Edit:
I was able to accomplish what I needed using the property-override functionality. Below is the updated ExampleBatch.xml that I went with
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">
<!-- ... -->
<import resource="classpath:batch-context.xml" />
<context:property-override properties-ref="entityManagerOverride"/>
<bean id="entityManagerOverride"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<util:properties>
<prop key="entityManagerFactory.packagesToScan">com.example.domain,com.example.batch.module.domain</prop>
</util:properties>
</property>
</bean>
<!-- ... -->
</beans>
So far Spring does not yell at me that this is an invalid configuration. Have yet to determine if this is in fact producing the desired outcome.
Edit 2:
The property-override method does not appear to be sufficient. It is a valid configuration but after inspecting the entity manager at runtime like this:
for (EntityType<?> entity : manager.getMetamodel().getEntities()) {
String name = entity.getName();
System.out.println(name);
}
It only contains entities from the com.example.domain package.
Does anyone have any other ideas?
The way you have it now, you really define two separate beans - one called entityManagerFactory and the other one entityManagerFactoryWithExtraPackages.
There are several ways to solve your very request:
Just get rid of one of the beans - merge the definitions into one.
I only guess it's not an option for you, otherwise you wouldn't ask.
Define the entityManagerFactory as abstract, then you end up having one bean anyway.
Use the property override mechanism. This fits the scenarios, where you are not in control of the 'top' bean and despite that you want to re-configure (literally override the values of the properties of) beans defined there.
Just replace this:
<property
name="packagesToScan"
value ="com.example.domain,com.example.domain.abstraction"/>
with this:
<property name="packagesToScan">
<array>
<value>com.example.domain</value>
<value>com.example.domain.abstraction</value>
</array>
</property>
If it fits your packages organization, you may try
<property name="packagesToScan" value="com.example.domain.*" />
In your batch-context.xml, so your ExampleBatch.xml doesn't have anymore to "override" the parent.
Another way to dig is using placeholder; in batch-context.xml, you would use :
<property name="packagesToScan" value="${packageList}" />
while in ExampleBatch.xml you would declare the placeholder with the appropriate value, as explained for example here : http://www.mkyong.com/spring/spring-propertyplaceholderconfigurer-example/