I am trying to fetch data from database using hibernate annotation but it is not working as my expected. I have a two table Employee and Department. the java code is as below :
Employee class
#Entity
#Table(name = "EMPLOYEE")
public class EmployeeBO {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "EMPID")
private int empId;
#Column(name = "EMPNAME")
private String empName;
#Column(name = "SALARY")
private int empSalary;
#Column(name = "EMPADDRESS")
private String empAddress;
#Column(name = "EMPAGE")
private int empAge;
#Column(name = "DEPTID")
private Integer deptId;
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="DEPTID", nullable = true, insertable = false, updatable = false)
private DepartmentBO departmentBO;
// getter and setter
}
Department class :
#Entity
#Table(name = "DEPARTMENT")
public class DepartmentBO {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "DEPTID")
private int deptid;
#Column(name = "DEPTNAME")
private String deptName;
// getter and setter.
}
spring-servlet.xml file :
<?xml version="1.0" encoding="UTF-8"?>
<!--?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:mvc="http://www.springframework.org/schema/mvc" 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/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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.web"></context:component-scan>
<context:property-placeholder location="file:D:/EasyProp/db.properties" ignore-unresolvable="false"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="basicDataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driver.classname}" />
<property name="url" value="${driver.url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<!-- <property name="initialSize" value="10"/> -->
<!-- <property name="maxActive" value="25"/> -->
<!-- <property name="maxIdle" value="25"/> -->
<!-- <aop:scoped-proxy/> -->
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
<!-- <bean id="dbUtil" class="com.web.utility.OnLoadStartUp" init-method="initialize">
<property name="dataSource" ref="basicDataSource" />
</bean> -->
<!-- <bean id="loadOnStartUp" class="com.web.utility.LoadOnStartUp">
<property name="baseService" ref="baseService"></property>
</bean> -->
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="basicDataSource" />
<property name="annotatedClasses">
<list>
<value>com.web.bo.EmployeeBO</value>
<value>com.web.bo.DepartmentBO</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hmb2ddl.auto">validate</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.jdbc.fetch_size">10</prop>
<prop key="hibernate.jdbc.batch_size">25</prop>
<prop key="hibernate.jdbc.batch_versioned_data">true</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.default_batch_fetch_size">8</prop>
<prop key="hibernate.order_updates">true</prop>
<prop key="hibernate.connection.release_mode">on_close</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
<prop key="hibernate.bytecode.provider">javassist</prop>
</props>
</property>
</bean>
</beans>
when i trying to fetch all data from employee and department table but it only returns the data from employee table my code for hit hql query as below :
List<EmployeeBO> empList = null;
empList = sessionFactory.getCurrentSession().createQuery("From "+employeeBO.getClass().getName()).list();
above query is hit as below on database.
select employeebo0_.EMPID as EMPID0_, employeebo0_.DEPTID as DEPTID0_, employeebo0_.EMPADDRESS as EMPADDRESS0_, employeebo0_.EMPAGE as EMPAGE0_, employeebo0_.EMPNAME as EMPNAME0_, employeebo0_.SALARY as SALARY0_ from EMPLOYEE employeebo0_
But i want all data of the employee table and department table using Eager fetching.
It works as expected. The EmployeeBO contains a DepartmentBO. The DepartmentBO will automatically be filled the moment you access it.
This is not true, if the Hibernate session containing the EmployeeBO has ended. Then the EmployeeBO is transient and hibernate will not fetch the missing object.
To enforce filling the DepartmentBO, you can add a fetch clause to your hql code. But that is not lazy fetching any more.
The HQL
from EmployeeBO join fetch EmployeeBO.department
should do the job (replace the EmployeeBO with the actual entity name).
See here in the hibernate docs: https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html and for the fetching strategies here https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html#performance-fetching
From the comments, you actually want eager fetching on the relationship, so you need to declare the fetchtype to be eager:
#ManyToOne(fetch=FetchType.EAGER)
should fix it. Adding another doc here: https://docs.oracle.com/javaee/6/api/javax/persistence/ManyToOne.html
There are two ways to do this:
1) use EAGER fetch type
2) call getDepartmentBO() on each employee after you get the employee
I think you have missed the anotation for lazy loading.
You have to use (fetch=FetchType.LAZY) on a association which you want to lazy load
Hibernate by default has Lazy loading. i.e. it would not fetch the data of another table. In you case if you want the data of department table, you will have to call getter of departmentBO if you are in hibernate session. Note: it will fire another query. else you can also use
Hibernate.initialize(entity.getdepartmentBO())
If you want by default to get the department data. use the following code
#ManyToOne(fetch=FetchType.EAGER)
Related
Whenever I on click submit button with some value, I want to select some columns from database and show it on my jsp page. The form is successfully submitted but I'm getting this error:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.psc.Entity.CandidateappearagainstadvtcodeEntity
So I think whatever data the repository is returning is not mapped with Entity. Please suggest, how to resolve this issue?
Controller:
#RequestMapping(value = "/getCandidateDetails", method = RequestMethod.POST)
public String getCandidateDetails(Model model,#RequestParam("studentmasterid") String studentmasterid){
System.out.println(studentmasterid);
List<CandidateappearagainstadvtcodeEntity> candidates=candidateappearagainstadvtcodeEntityRepository.findBystudentmasterid(studentmasterid);
return "payments";
}
Model looks like this:
#Entity
#Table(name = "CANDIDATEAPPEARAGAINSTADVTCODE", schema = "PSCNEPALCOMMERCIALDATABASEU1", catalog = "")
public class CandidateappearagainstadvtcodeEntity {
private long id;
private String advertisementcode;
private Integer ageonlastdateday;
private Integer ageonlastdatemonth;
private Integer ageonlastdateyear;
private String applicationnumber;
private String attendancestatus;
private String candidatefirstname;
private String dateofbirthinnepali;
private String documentverificationstatus;
private String examinationcenterid;
private String examresultsstatus;
private String fathername;
private Long firstcoding;
private String studentmasterid;
//getters setters//
Repository:
public interface CandidateappearagainstadvtcodeEntityRepository extends JpaRepository<CandidateappearagainstadvtcodeEntity,Long> {
#Query("select c.studentmasterid,c.advertisementcode,c.candidatefirstname from CandidateappearagainstadvtcodeEntity c where c.studentmasterid=?1")
List<CandidateappearagainstadvtcodeEntity> findBystudentmasterid(String masterId);
}
ApplicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.psc"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/db.properties</value>
</property>
</bean>
<!-- BoneCP configuration -->
<bean id="mainDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriodInMinutes" value="60"/>
<property name="idleMaxAgeInMinutes" value="240"/>
<property name="maxConnectionsPerPartition" value="30"/>
<property name="minConnectionsPerPartition" value="10"/>
<property name="partitionCount" value="3"/>
<property name="acquireIncrement" value="5"/>
<property name="statementsCacheSize" value="100"/>
<property name="releaseHelperThreads" value="3"/>
</bean>
<!-- SPRING - JPA -->
<jpa:repositories
base-package="com.psc" />
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory"
ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="mainDataSource" />
<property name="packagesToScan" value="com.psc"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="showSql" value="false"/>
<property name="databasePlatform" value="org.hibernate.dialect.Oracle12cDialect"/>
<property name="database" value="ORACLE"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</prop>
</props>
</property>
</bean>
</beans>
A JPA repository usually returns the domain model. From the docs
Spring Data Repositories usually return the domain model when using query methods. However, sometimes, you may need to alter the view of that model for various reasons. In this section, you will learn how to define projections to serve up simplified and reduced views of resources.
Your repository method findBystudentmasterid will be returning a list Object[] hence the ClassCastException.If you want to get specific columns try Projections.
Chekout the docs and this answer on how to use projections.
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 { ... }
I'm using a Hibernate SessionFactory and the auto-table-creation option, but when I want to start Tomcat, the database is not started and the following error messages appear in the console:
2015-10-14 23:07:26 DEBUG SQL:104 - create table TEACHER (ID bigint not null, firstName varchar(255), lastName varchar(255),
primary key (ID), unique (ID))
2015-10-14 23:07:26 ERROR SchemaExport:426 - HHH000389: Unsuccessful: create table TEACHER (ID bigint not null, firstName
varchar(255), lastName varchar(255), primary key (ID), unique (ID))
2015-10-14 23:07:26 ERROR SchemaExport:427 - ORA-00902: invalid datatype
This is my config:
<?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: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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="com.sante.gestion" />
<context:annotation-config />
<context:spring-configured />
<!-- DataSource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:XE" />
<property name="username" value="gestion" />
<property name="password" value="gestion" />
</bean>
<!-- Session Factory Declaration -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.sante.gestion.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<!-- Transaction Manager is defined -->
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager" />
</beans>
And this is my object model:
#Entity(name = "COURSE")
public class Course implements Serializable {
private static final long serialVersionUID = 8736444902161357518L;
#Id
#Basic(optional = false)
#Column(name = "ID", unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "COURSE_SEQ")
#SequenceGenerator(name = "COURSE_SEQ",
sequenceName = "COURSE_SEQ",
initialValue = 1,
allocationSize = 999999999)
#Type(type = "java.lang.Long")
private Long id;
#Column
private String name;
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.