I use Spring 4.3.3.RELEASE, Hibernate 5.2.2.Final, the database is MySQL.
I wanted to try strategy = GenerationType.TABLE. As I know for GenerationType.SEQUENCE I need sequences in the database to generate ids.
This is my entity.
#Entity(name = CommentTable.TABLE_NAME)
public class Comment {
private Integer id;
private String title;
private String message;
private LocalDateTime createdDateTime;
private Issue issue;
public Comment() {
}
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
#Column(name = CommentTable.COLUMN_ID, unique = true, nullable = false)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
//Other getters and setters.
}
Spring annotation configuration
#Configuration
#ComponentScan("com.ita.training.otm")
#ImportResource("classpath:/config.xml") // XML with DataSource bean
#EnableTransactionManagement
public class AppConfiguration {
}
Spring xml configuration
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.ita.training.otm.core.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>
<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/spring_test" />
<property name="username" value="user" />
<property name="password" value="1111" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven />
</beans>
When I run my application, I get
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emf' defined in class path resource [config.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1076)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:851)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at com.ita.training.otm.app.Main.main(Main.java:10)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:951)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:881)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)
... 11 more
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [hibernate_sequences]
at org.hibernate.tool.schema.internal.SchemaValidatorImpl.validateTable(SchemaValidatorImpl.java:125)
at org.hibernate.tool.schema.internal.SchemaValidatorImpl.performValidation(SchemaValidatorImpl.java:95)
at org.hibernate.tool.schema.internal.SchemaValidatorImpl.doValidation(SchemaValidatorImpl.java:62)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:184)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:65)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:307)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:490)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:878)
... 17 more
The exception is occured because you haven't mentioned generator in #GeneratedValue..Below is the example
#GeneratedValue(strategy=GenerationType.TABLE, generator="course")
#TableGenerator(
name="course",
table="GENERATOR_TABLE",
pkColumnName = "key",
valueColumnName = "next",
pkColumnValue="course",
allocationSize=30
)
private int id;
I solved it by using the property
spring:
jpa:
hibernate:
use-new-id-generator-mappings: false
I was using spring boot V2.5.9
With this setting the hibernate sequence is generated if missing.
Then also no need for the #GeneratedValue annotation.
I had to keep this project in runnable mode before I start working on my actual task, I have solved this exception and started my application with following steps:
Created a new database schema in my local MYSQL server. and added it to properties file.
Changed hibernate dialect to org.hibernate.dialect.MySQL5Dialect
Changed spring.jpa.hibernate.ddl-auto from "validate" to "create-drop" option
Restarted the Application.
Actual problem that I understood is, the existing database schema had tables, constraints and data which is not in sync with my current code.
My Goal is to make my application to Start and these steps helped me.
Related
I got the following exception in my first spring transaction exercise :
Exception in thread "main"
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactoryBean' defined in class path resource [spring.xml]:
Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit:default] Unable to build EntityManagerFactory at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1566) at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) at
org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:956) at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:747) at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) at
org.springframework.context.support.ClassPathXmlApplicationContext.<init(ClassPathXmlApplicationContext.java:139) at
org.springframework.context.support.ClassPathXmlApplicationContext.<init(ClassPathXmlApplicationContext.java:83) at
com.Main.main(Main.java:15)
Caused by:
javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build EntityManagerFactory at
org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:914) at
org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:889) at
org.springframework.orm.jpa.vendor.SpringHibernateEjbPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateEjbPersistenceProvider.java:51) at
org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343) at
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625) at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)
... 12 more
Caused by: org.hibernate.AnnotationException: Unknown mappedBy in: com.entity.Document.person, referenced property unknown: com.entity.Person.x at
org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:158) at
org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1586) at
org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1359) at
org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1724) at
org.hibernate.ejb.EntityManagerFactoryImpl.<init(EntityManagerFactoryImpl.java:84) at
org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904)
... 18 more
This is my Spring configuration file called spring.xml:
<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:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
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/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--SpringMVC-->
<context:component-scan base-package="com"/>
<aop:aspectj-autoproxy/>
<tx:annotation-driven/>
<!--<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class='true'/>-->
<!-- SpringTransaction-->
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.entity"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop><!--for product update-->
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:XE"/>
<property name="username" value="saba"/>
<property name="password" value="myjava123"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean"/>
</bean>
</beans>
And this my service that I used #Transactional annotation
#Service
#Transactional
public class PersonService<T> {
#PersistenceContext
private EntityManager entityManager;
public void register(T entity)
{
entityManager.persist(entity);
}
}
Why did this exception happen??
Actually, your problem has nothing to do with Spring or Transactions.
As your stacktrace shows, you have a problem somewhere with your Hibernate mapping:
...
caused by: org.hibernate.AnnotationException:
Unknown mappedBy in: com.entity.Document.person, referenced property unknown: com.entity.Person.x
...
I am having issues with setting up multi-tenancy support for my web application with a separate database approach using Spring + JPA + Hibernate.
I have tried the Hibernate way using my own implementations of CurrentTenantIdentifierResolver and AbstractMultiTenantConnectionProvider, and the Spring one using AbstractRoutingDataSource. I'll use the AbstractRoutingDataSource solution, that I named UserRoutingDataSource, to explain my problem.
What I am trying to achieve is the following :
I have a "master" database with all the data concerning the users and their databases
When a user logs in I save his database id in a session scoped bean named UserSession
My UserRoutingDataSource's targetDataSources needs to be filled with datasources representing all the databases of my master database's CustomDatabases table.
When a connection is needed, my UserRoutingDataSource's determineCurrentLookupKey needs to retrieve the database id from the user's UserSession instance.
In both cases (Hibernate way / Spring way) I end up with a circular reference exception. The issue arises when I try to autowire my CustomDatabasesDAO and my UserSession in UserRoutingDataSource.
This is the exception I get :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userEntityManagerFactory' defined in class path resource [MyApp/webapp/WEB-INF/config/applicationContext.xml]: Cannot resolve reference to bean 'userRoutingDataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userRoutingDataSource' defined in class path resource [MyApp/webapp/WEB-INF/config/applicationContext.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [myApp.java.data.dao.Global.CustomDatabasesDAO]: : Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1051)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:828)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:446)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:328)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4728)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5162)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userRoutingDataSource' defined in class path resource [MyApp/webapp/WEB-INF/config/applicationContext.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [myApp.java.data.dao.Global.CustomDatabasesDAO]: : Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 24 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:357)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 34 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:181)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:127)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1584)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:253)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:130)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findNamedEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:556)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:538)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:707)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:680)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
... 46 more
What I don't understand is why I get this exception when my CustomDatabasesDAO doesn't have a single reference to userEntityManagerFactory. The only relevant thing that I can think of in CustomDatabasesDAO is my call to the master database's entityManager :
#PersistenceContext(unitName = "masterEntityManagerFactory")
private EntityManager masterEntityManager;
For more context, here are my UserRoutingDataSource file and the relevant parts from my application context file.
UserRoutingDataSource
public class UserRoutingDataSource extends AbstractRoutingDataSource {
/*private CustomDatabasesDAO customDatabasesDAO;
#Autowired
public void setCustomDatabasesDAO(final CustomDatabasesDAO customDatabasesDAO)
{
this.customDatabasesDAO = customDatabasesDAO;
}*/
#Autowired
private UserSession session;
/*#Autowired
public void setUserSession(final UserSession session)
{
this.session = session;
}*/
#Autowired
public UserRoutingDataSource(CustomDatabasesDAO customDatabasesDAO) {
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
for(CustomDatabases database : customDatabasesDAO.findDatabasesByDeleted(0))
{
// All the information necessary for the datasource will eventually be retrieved from the database variable
DriverManagerDataSource datasource = new DriverManagerDataSource();
datasource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
datasource.setUrl("jdbc:sqlserver://localhost:1433;databaseName=" + database.getCdboAliasName() + ";");
datasource.setUsername("username");
datasource.setPassword("password");
targetDataSources.put(String.valueOf(database.getCdboDatabaseId()), datasource);
}
setTargetDataSources(targetDataSources);
}
#Override
protected Object determineCurrentLookupKey() {
return session.getCdboDatabaseId();
}
}
Application context
/*<!--<bean id="currentTenantIdentifierResolverImpl" class="myApp.java.config.CurrentTenantIdentifierResolverImpl" />
<bean id="multiTenantConnectionProvider" class="myApp.java.config.MultiTenantConnectionProvider" />-->*/
<bean id="masterDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://localhost:1433;databaseName=myDatabase;" />
<property name="username" value="sa" />
<property name="password" value="password" />
</bean>
<bean id="masterEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="masterDataSource" />
<property name="packagesToScan" value="myApp.java.data.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.use_outer_join">true</prop>
</props>
</property>
</bean>
<bean id="userRoutingDataSource" class="myApp.java.config.UserRoutingDataSource">
<property name="targetDataSources">
<map />
</property>
</bean>
<bean id="userEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="userRoutingDataSource" />
<property name="packagesToScan" value="myApp.java.data.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" />
<entry key="hibernate.show_sql" value="false" />
<entry key="hibernate.use_outer_join" value="true" />
/*<!--<entry key="hibernate.tenant_identifier_resolver" value-ref="currentTenantIdentifierResolverImpl" />
<entry key="hibernate.multi_tenant_connection_provider" value-ref="multiTenantConnectionProvider" />
<entry key="hibernate.multiTenancy" value="DATABASE" />-->*/
</map>
</property>
</bean>
<!-- Transaction managers -->
<tx:annotation-driven />
<bean id="masterTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="masterEntityManagerFactory" />
<qualifier value="master" />
</bean>
<bean id="userTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="userEntityManagerFactory" />
<qualifier value="user" />
</bean>
I have tried so many things that I am not sure if I still understand how dependency injection works. And I have no idea what I might be missing.
Thanks for you help.
SOLUTION :
I solved my issue thanks to Roman's answer. I also gave up on the idea of using my session scoped bean to determine my current lookup key and I use my Spring Security authentication instead. When a user logs in I do the following :
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
HashMap<String, Object> details = new HashMap<String, Object>();
details.put("databaseId", session.getCdboDatabaseId());
newAuth.setDetails(details);
SecurityContextHolder.getContext().setAuthentication(newAuth);
The important part being the setDetails(details) on my user's UsernamePasswordAuthenticationToken.
Here is the current state of my (working) configuration :
UserRoutingDataSource
#Component
public class UserRoutingDataSource extends AbstractRoutingDataSource {
#Autowired
public UserRoutingDataSource(CustomDatabasesDAO customDatabasesDAO) {
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
for(CustomDatabases database : customDatabasesDAO.findDatabasesByDeleted(0))
{
DriverManagerDataSource datasource = new DriverManagerDataSource();
datasource.setDriverClassName(database.getCdboDriverName());
datasource.setUrl("jdbc:sqlserver://"+database.getCdboServer()+":"+database.getCdboPort()+";databaseName="+database.getCdboAliasName() + ";");
datasource.setUsername(database.getCdboUserName());
datasource.setPassword(database.getCdboPassword());
targetDataSources.put(database.getCdboDatabaseId(), datasource);
}
/*
* This default datasource is necessary because for some reason (Hibernate, JPA related ?) the routing datasource
* calls the "determineCurrentLookupKey()" on startup which returned null ("default" now) because there is no Authentication at startup yet.
*/
targetDataSources.put("default", new DriverManagerDataSource());
setTargetDataSources(targetDataSources);
afterPropertiesSet();
}
#Override
protected Object determineCurrentLookupKey() {
UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getDetails() instanceof Map)
{
HashMap<String, Object> details = (HashMap<String, Object>) auth.getDetails();
return details.get("databaseId");
}
return "default";
}
}
Application context
<bean id="masterDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://localhost:1433;databaseName=myDatabase;" />
<property name="username" value="myUser" />
<property name="password" value="myPassword" />
</bean>
<bean id="masterEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="masterEntityManagerFactory" />
<property name="dataSource" ref="masterDataSource" />
<property name="packagesToScan" value="myApp.java.data.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.use_outer_join">true</prop>
</props>
</property>
</bean>
<bean id="userEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="userEntityManagerFactory" />
<property name="dataSource" ref="userRoutingDataSource" />
<property name="packagesToScan" value="myApp.java.data.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" />
<entry key="hibernate.show_sql" value="false" />
<entry key="hibernate.use_outer_join" value="true" />
</map>
</property>
</bean>
<!-- Transaction managers -->
<tx:annotation-driven />
<bean id="masterTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="masterEntityManagerFactory" />
<qualifier value="master" />
</bean>
<bean id="userTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="userEntityManagerFactory" />
<qualifier value="user" />
</bean>
Spring iterates over all EntityManagerFactorys inside of EntityManagerFactoryUtils.findEntityManagerFactory() to find out the factory with the property persistenceUnitName value equals to #PersistenceUnit's attribute unitName value. Only if no candidate has been found the bean with the name of unitName value will be used. Therefore userEntityManagerFactory gets instantiated during this process.
As a workaround you could try to make use of regular #Autowired instead of #PersistenceUnit in CustomDatabasesDAO class.
I was running my unit tests directly with the targetted Database which is : Oracle 10g and i was asked to run them under H2 Database.
So, after generating the differents SQL scripts and configured the H2 database (through XML config. with Spring), i realized that some of my tests failed whereas some of them passed...
I have the following view (a view of a view) which returns different columns :
CREATE OR REPLACE FORCE VIEW ##.VIEW_OLB_SAT_COVERAGE
(
SAT_CODE,
ORBITAL_POSITION,
COVERAGE_DOWN,
COVERAGE_UP
)
AS
SELECT DISTINCT sat_code,
orbital_position,
coverage_down,
coverage_up
FROM ##.VIEW_OLB_TXP_COVERAGE
ORDER BY sat_code ASC;
The view "VIEW_OLB_TXP_COVERAGE" is the following :
CREATE OR REPLACE FORCE VIEW ##.VIEW_OLB_TXP_COVERAGE
(
SAT_CODE,
ORBITAL_POSITION,
TXP_NO,
COVERAGE_DOWN,
COVERAGE_UP,
POLARIZATION_DOWN,
POLARIZATION_UP
)
AS
SELECT DISTINCT ##.OLB_AVAILABLE_TXP.SAT_CODE,
###.SAT_DEP.ORBIT_LOC / 3600 ORBITAL_POSITION,
##.OLB_AVAILABLE_TXP.TXP_NO,
###.TXP.CUR_DN_COVERAGE COVERAGE_DOWN,
###.TXP.CUR_UP_COVERAGE COVERAGE_UP,
###.TXP.TXP_DN_POL,
###.TXP.TXP_UP_POL
... The rest is omitted for clarity
The Hibernate entities are the following :
#Component(value = "viewOlbSatCoverage")
#Scope("prototype")
#Entity
#Table(name = "VIEW_OLB_SAT_COVERAGE", schema = "##")
public class ViewOlbSatCoverage implements Serializable {
private static final long serialVersionUID = -6728959649786852446L;
#Id
private ViewOlbSatCoverageId viewOlbSatCoverageId;
public ViewOlbSatCoverageId getViewOlbSatCoverageId() {
return viewOlbSatCoverageId;
}
public void setViewOlbSatCoverageId(ViewOlbSatCoverageId viewOlbSatCoverageId) {
this.viewOlbSatCoverageId = viewOlbSatCoverageId;
}
#Override
public String toString() {
return "ViewOlbSatCoverage : [viewOlbSatCoverageId=" + viewOlbSatCoverageId == null ? "null"
: viewOlbSatCoverageId.toString() + "]";
}
}
#Component(value = "viewOlbSatCoverageId")
#Scope("prototype")
#Embeddable
public class ViewOlbSatCoverageId implements Serializable {
private static final long serialVersionUID = 2822316442843031126L;
#Column(name = "COVERAGE_DOWN")
private String coverageDown;
#Column(name = "COVERAGE_UP")
private String coverageUp;
#Column(name = "SAT_CODE")
private String satCode;
#Column(name = "ORBITAL_POSITION")
private BigDecimal orbitalPosition;
public ViewOlbSatCoverageId() {
}
public ViewOlbSatCoverageId(String satCode, BigDecimal orbitalPosition, String coverageDown, String coverageUp) {
setSatCode(satCode);
setOrbitalPosition(orbitalPosition);
setCoverageDown(coverageDown);
setCoverageUp(coverageUp);
}
// Getters, setters omitted for clarity ...
}
As I mentionned, the targetted database is Oracle 10g and all works fine with it (when the app is running).
But when I run H2 database for unit testing purpose, the following method ( findDistinctAllOrbitalPositions) doesn't work :
#Repository
public class ViewOlbSatCoverageDaoImpl extends GenericDaoImpl<ViewOlbSatCoverage> implements ViewOlbSatCoverageDao {
public ViewOlbSatCoverageDaoImpl() {
setGenericClass(ViewOlbSatCoverage.class);
setDaoLogger(ViewOlbSatCoverageDaoImpl.class);
}
#Override
#SuppressWarnings("unchecked")
public List<BigDecimal> findDistinctAllOrbitalPositions() {
Query query = sessionFactory.getCurrentSession().createQuery(
"select distinct(viewOlbSatCoverageId.orbitalPosition) from " + genericClass.getSimpleName()
+ " order by viewOlbSatCoverageId.orbitalPosition asc"); // genericClass is ViewOlbSatCoverage
return query.list();
}
}
As you can see, i'm using HQL but also the Criteria API.
When i launch maven from command line :
mvn clean -Dtest=ViewOlbSatCoverageDaoImplTestCase test
It gives me the following :
Caused by: org.h2.jdbc.JdbcSQLException: Column "VIEWOLBSAT0_.ORBITAL_POSITION" not found; SQL state
ment:
select distinct viewolbsat0_.ORBITAL_POSITION as col_0_0_ from ##.VIEW_OLB_SAT_COVERAGE viewolbsat0_
order by viewolbsat0_.ORBITAL_POSITION asc [42122-190]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.expression.ExpressionColumn.optimize(ExpressionColumn.java:147)
at org.h2.expression.Alias.optimize(Alias.java:51)
at org.h2.command.dml.Select.prepare(Select.java:835)
at org.h2.command.Parser.prepareCommand(Parser.java:246)
at org.h2.engine.Session.prepareLocal(Session.java:460)
at org.h2.engine.Session.prepareCommand(Session.java:402)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1188)
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:72)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:276)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler.continueInvocation(Connec
tionProxyHandler.java:138)
... 64 more
Here is a sample of my applicationContext-test.xml :
<jdbc:embedded-database id="h2TestDataSource" type="H2"/>
<jdbc:initialize-database data-source="h2TestDataSource">
<jdbc:script location="classpath:com/eutelsat/olb/sql/create/views/VIEW_OLB_SAT_COVERAGE.sql" />
<jdbc:script location="classpath:com/eutelsat/olb/sql/create/views/VIEW_OLB_TXP_COVERAGE.sql" />
<!-- Other .sql files omitted for clarity -->
</jdbc:initialize-database>
<!-- Connection pool -->
<bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.h2.Driver" />
<property name="jdbcUrl" value="jdbc:h2:mem:h2TestDataSource;INIT=RUNSCRIPT FROM 'com/eutelsat/olb/sql/create/schemas/INIT.sql'" />
<property name="user" value="sa" />
<property name="password" value="" />
<property name="acquireIncrement" value="1" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="5" />
<property name="maxIdleTime" value="30" />
<property name="maxIdleTimeExcessConnections" value="10" />
<property name="numHelperThreads" value="3" />
<property name="unreturnedConnectionTimeout" value="0" />
</bean>
<!-- Session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="h2TestDataSource" />
<property name="packagesToScan" value="com.eutelsat.olb.server.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">none</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
<prop key="hibernate.use_outer_join">true</prop>
<prop key="hibernate.order_inserts">true</prop>
<prop key="hibernate.order_updates">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="format_sql">true</prop>
<prop key="hibernate.id.new_generator_mappings">true</prop>
</props>
</property>
</bean>
<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
I have read a lot of things but I can't find what the problem is (incorrect SQL script which needs to be adapted to fit in H2 database or maybe an H2 database config. with column alias matters ?).
NB : schemas have been obfuscated.
Thanks in advance for pointers.
I've found a solution to my problem.
The SQL scripts (some of them were omitted in the sample posted in SOF) which were declared in my "applicationContext-test.xml" file were not well ordered resulting in a view with a INVALID status.
-> Resulting in generated SQL query done by Hibernate complaining that some tables and / or columns were'nt found.
I've found the problem (and also the solution) thanks to the excellent H2 web server allowing me to view in memory data. In the SCHEMA_INFORMATION section, I saw VIEWS and when clicking on it, I saw STATUS = INVALID.
In order to add an H2 web server using Spring XML config, you can easily add this :
<bean id="h2Server" class="org.h2.tools.Server" factory-method="createTcpServer" init-method="start" destroy-method="stop" depends-on="h2WebServer">
<constructor-arg value="-tcp,-tcpAllowOthers,-tcpPort,9992"/>
</bean>
<bean id="h2WebServer" class="org.h2.tools.Server" factory-method="createWebServer" init-method="start" destroy-method="stop">
<constructor-arg value="-web,-webAllowOthers,-webPort,8882"/>
</bean>
Do not forget to add a depends-on attribute valued to "h2Server" (so : depends-on="h2Server") to you datasource bean, otherwise it will not work as expected !
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.
we're using spring, hibernate and hsql to persist a simple user entity. We always get the error "table not found". Do you have any idea what this could be? It seems like the table is not generated or the hsql database is not running at all.
Regards,
G.
#Entity
#Table (name="USER")
public class User {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
#Column(name="ID")
private Long id;
#Column(name="NAME", length = 100, nullable = false)
private String name;
public User(){}
//getters and setters ...
by this dao class:
package de.hsrm.mediathek;
import java.util.List;
public class UserDao implements IUserDao{
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(final HibernateTemplate hibernateTemplate){
this.hibernateTemplate = hibernateTemplate;
}
#Transactional
public void store(final User user){
hibernateTemplate.saveOrUpdate(user);
}
#Transactional
public void delete(final Long userId){
final User user = (User) hibernateTemplate.get(User.class, userId);
hibernateTemplate.delete(user);
}
#Transactional(readOnly = true)
public User findById(final Long userId){
return (User) hibernateTemplate.get(User.class, userId);
}
#Transactional(readOnly = true)
public List<User> findAll(){
return hibernateTemplate.find("from User");
}
}
Configuration 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:tx="http://www.springframework.org/schema/tx"
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">
<tx:annotation-driven/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:mediathekdb" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>de.hsrm.mediathek.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.hbm2dll.auto">create-drop</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.connection.pool_size">10</prop>
<prop
key="hibernate.cache.provider_class">
org.hibernate.cache.HashtableCacheProvider</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="userDao" class="de.hsrm.mediathek.UserDao">
<property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Interceptor for hibernate calls to be able to create and close sessions
<bean id="hibernateInterceptor"
class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
-->
</beans>
Error LOG:
Caused by: java.sql.SQLException: Table not found in statement [insert into User (ID, NAME) values (null, ?)]
at org.hsqldb.jdbc.Util.throwError(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.<init>(Unknown Source)
at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:528)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:95)
at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:30)
... 63 more
The problem is that the property "hbm2dll" is wrongly spelled. It should be "hbm2ddl":
It is:
<prop key="hibernate.hbm2dll.auto">create-drop</prop>
It should be:
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
It's also better to keep an eye on logs for any other errors, as I had a similar problem and found out that create table statement was failing for HSQLDB's DDL generated by Hibernate and Hibernate was silently swallowing it
2011-06-09 10:48:30,722 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaExport - Wrong data type: ALERT_ID in statement [create table ACCOUNT_ALERT (ALERT_ID numeric generated by default as identity (start with 1)]
Later when I changed the following
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="ALERT_ID")
private BigInteger alertId;
to
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name="ALERT_ID")
private BigInteger alertId;
it worked perfectly.
I'd suggest trying to run HSQLDB in server mode using:
java -classpath hsqldb.jar org.hsqldb.server.Server
Check that it's running using Database manager:
java -classpath hsqldb.jar org.hsqldb.util.DatabaseManagerSwing
Next, change your Hibernate URL, so it uses server mode HSQLDB:
<property name="url" value="jdbc:hsqldb:mediathekdb" />
I've had success using this method. It's possible that create-drop doesn't work properly when using a memory only instance.