Junit testing with in-memory hsqldb, hibernate and liquibase - spring

I'm trying to use an HSQLDB in order to run some integration test.
I use Spring.
Hibernate is used to set up the database schema.
Then I want to insert test data using liquibase.
My problem is that, while hibernate schema creation works fine, I'm getting :
liquibase.exception.DatabaseException: Error executing SQL INSERT INTO PUBLIC.OxAttributeType (id, "alias") VALUES ('1', 'varchar'): user lacks privilege or object not found: alias
When liquibase try to start it's insertion.
I think that it might be cause by the hsqldb beeing closed (and flushed) after hibernate schema creation, but I'm not sure.
Here is my configuration:
database.properties:
jdbc.driverClassName= org.hsqldb.jdbc.JDBCDriver
jdbc.url=jdbc:hsqldb:mem:oxandtestdatabase
jdbc.username: SA
jdbc.password:
Hibernate object:
#Entity
#Table(name = "oxattribute")
public class Oxattribute implements java.io.Serializable {
private Integer id;
private String alias;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "alias", nullable = false, length = 30)
public String getAlias() {
return this.alias;
}
}
Spring configuration:
<bean id="hibernateProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<!-- <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> -->
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:liquibase/testData.xml" />
</bean>
So Hibernate is working, I can see in the logs:
Hibernate: create table oxattribute (id integer generated by default as identity (start with 1), alias varchar(30) not null, deletable boolean not null, description varchar(255), idOxAttributeType integer not null, idOxObject integer not null, primary key (id))
But then when liquibase start insertions:
SEVERE 07/08/14 13:59: liquibase: classpath:liquibase/testData.xml: classpath:liquibase/testData.xml::insertMetadata::GCH: Change Set classpath:liquibase/testData.xml::insertMetadata::GCH failed. Error: Error executing SQL INSERT INTO PUBLIC.OxAttributeType (id, "alias") VALUES ('1', 'varchar'): user lacks privilege or object not found: alias
liquibase.exception.DatabaseException: Error executing SQL INSERT INTO PUBLIC.OxAttributeType (id, "alias") VALUES ('1', 'varchar'): user lacks privilege or object not found: alias
For information, my code was working fine on a mysql database.
Thank you for your help,
Guillaume

Change the name of the column used ("alias" is reserved term). You could try adding backticks "`".
#Column(name="`alias`").

Related

Exception Illegal Argument - unknown entity JPA - Additional package to scan for entities in application-context.xml is not taken into consideration

I am working on a Spring application which has a persistence unit configured in the application-context.xml. I need to add an additional package in in order to use new entities.
Even though this part of the persistence.xml file looks like below, my entities from the additional package are not seen by the application and I get an exception saying that the entity is unknown.
<bean id="transactionManager_students" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryStudents" />
<qualifier value="clientTransaction" />
</bean>
<bean id="entityManagerFactoryStudents"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="datasource_College" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<property name="packagesToScan">
<list>
<value>com.load.model</value>
<value>com.students.entity</value>
</list>
</property>
<property name="persistenceUnitName" value="unit_stud" />
<property name="jpaProperties">
<props>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.hbm2ddl.auto">none</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>  
I also have to mention that I annotated the entities with #Entity and in the class where I am operating on the entities I have this ( the row with em.persist(student) is giving me the error )
#PersistenceContext(unitName = "unit_stud")
public EntityManager em;
public Student student;
#Transactional(value = "clientTransaction", propagation = Propagation.REQUIRED)
public long persistStudentObject() {
long studentId = 0;
try
{
logger.debug("Start Persisting...");
em.persist(student);
// unique ID
studentId = student.getId();
logger.debug("Persisting OK...");
}
catch (PersistenceException persistenceException)
{
logger.error("PersistenceException occur", persistenceException);
}
}
return studentId ;
}
The entity:
package com.students.entity;
#Entity
#Table(name = "STUDENTS", schema = "DEMO", catalog = "")
public class Student{
private long id;
private String firstname;
private String name;
private String streetnumber;
private String zipcodecity;
Can anyone help me? I do not know what to do in order to make my entities visible.

how to update many-to-many collection (lazy-loading) in hibernate/spring?

I have three tables and two classes.there are many-to-many relationship between the two tables/classes.
OYS_USER -->Many-to-Many with 'oys_lesson'
OYS_LESSON-->Many-to-Many with 'oys_user'
OYS_LESSON_STUDENT-->relationship
in User.class
#ManyToMany(cascade= CascadeType.ALL,fetch=FetchType.LAZY)
#JoinTable(name="oys_lesson_student",
joinColumns = { #JoinColumn(name="student_id",referencedColumnName="id")},
inverseJoinColumns = {#JoinColumn(name="lesson_id",referencedColumnName="id") })
#Fetch(FetchMode.SUBSELECT)
private Set<Lesson> studentLessons;
in Lesson.class
#ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
#JoinTable(name = "oys_lesson_student", joinColumns = { #JoinColumn(name = "lesson_id", referencedColumnName = "id") }, inverseJoinColumns = { #JoinColumn(name = "student_id", referencedColumnName = "id") })
#Fetch(FetchMode.SUBSELECT)
private Set<User> lessonStudents;
I updated collection with below codes:
#Override
public void addLessonToStudent(Lesson lesson) {
// TODO Auto-generated method stub
String username = SecurityContextHolder.getContext()
.getAuthentication().getName();
Criteria criteria = openSession().createCriteria(User.class)
.add(Restrictions.eq("username", username));
User user=(User) criteria.uniqueResult();
log.info("'"+lesson.getLessonName()+"' lesson added to '"+user.getUsername()+"'");
/*user.getStudentLessons().add(lesson);
updateUser(user);
*/
lesson.getLessonStudents().add(user);
updateLesson(lesson);
} catch (HibernateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void updateLesson(Lesson lesson) {
log.info(lesson.getLessonName()+" updated.");
openSession().update(lesson);
}
When I added current user to lesson's collection (or lesson to current user's collection).
update/insert query does not appear in hibernate statistics(console-log).
So a record can not be added to any collection.
Basically,I want to add new object to many to many collection.What am I doing wrong?
I use hibernate 4.3.5.Final (to get rid of lazy loading exception)
I use org.springframework.orm.hibernate4.support.OpenSessionInViewFilter for rid of lazy loading exception).
I tried CascadeType.EAGER with FetchType.JOIN.But did not change the results.update/insert query does not appear in hibernate statistics(console-log).
I use below properties for hibernate in application-context.xml(spring-hibernate-configuration):
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory
</prop>
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
<prop key="use_sql_comments">true</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
<prop key="hibernate.connection.autocommit">true</prop>
<prop key="net.sf.ehcache.configurationResourceName">/myehcache.xml</prop>
</props>
</property>
and spring txManager:
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager" />
<!-- Transaction Manager is defined -->
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
I use spring/security,hibernate 4.3.5.Final,jpa2.1,jsf2.2. Thanks in advance.
You are almost there.
Firstly, you need to decide which site of your reletionship is 'in control'. Is the user or is it the lesson. And yo define the join table only on one of them so for example:
- you leave the user as it is
- on lesson you changed
#ManyToMany(mappedBy="studentLessons" ...)
Then, you need to add the reletionship manually to both sites of the relationship (in reality adding to the one in charge of mapping is typically enought).
so
user.getUserLesseson().add(lesson);
lesson.getLessonStudents().add(user);
if both are issued inside transaction it will result in the insert

Spring: change EntityManager dynamically

for some reason the database (ugly!) that I should use contains all the tables twice; every table are duplicated into these modes: DB1_<table> and DB2_<table>.
The structures of these databases are the same!
The application that I am realizing uses Spring + Hibernate and should permit to the users to change the database on runtime; this mean that a user can start the application using database DB1 and after some minutes change to DB2, return to DB1 and so on.
I have tried to extend DefaultNamingStrategy for every databases:
// I have create also DB2
public class DB1 extends DefaultNamingStrategy {
private static final long serialVersionUID = 676544180324515651L;
#Override
public String tableName(String tableName) {
return "DB1_" + tableName;
}
}
and set the naming strategy through the property hibernate.ejb.naming_strategy of jpa dinamically but for a reason that I can't understand I can change the naming strategy only once, and all next callings trown an Exception.
Someone know why?
Configuration of entityManagerFactory:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="it.perfectquiz.entity" />
<property name="persistenceProviderClass" value="org.hibernate.jpa.HibernatePersistenceProvider" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
How I try to change naming strategy:
XmlWebApplicationContext context = (XmlWebApplicationContext) ContextLoader.getCurrentWebApplicationContext();
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();
GenericBeanDefinition entityManager = (GenericBeanDefinition) beanFactory.getBeanDefinition("entityManagerFactory");
ManagedProperties jpaProperties = (ManagedProperties) entityManager.getPropertyValues().get("jpaProperties");
TypedStringValue namingStrategy = (TypedStringValue) jpaProperties.get(new TypedStringValue("hibernate.ejb.naming_strategy"));
// only for test!
String newNaming;
if (namingStrategy.getValue().equals(DB1.class.getCanonicalName()))
newNaming = DB2.class.getCanonicalName();
else
newNaming = DB1.class.getCanonicalName();
// only for test!
namingStrategy.setValue(newNaming);
beanFactory.registerBeanDefinition("entityManagerFactory", entityManager);
Thanks,
Regards

Pageable sorting problems with Spring JPA

I'm haccing an issue with Spring JPA regarding sorting and paginating. Currently I'm receiving this warning:
WARN [NamedQuery] (NamedQuery.java:65) - Finder method public abstract org.springframework.data.domain.Page loc.starterkit.business.entities.application.repository.ApplicationRepository.findByNameLike(java.lang.String,org.springframework.data.domain.Pageable)
is backed by a NamedQuery but contains a Pageable parameter! Sorting delivered via this Pageable will not be applied!
My JPA interface code looks like this:
public interface ApplicationRepository extends PagingAndSortingRepository<Application,Long>{
Page<Application> findByNameLike(String name, Pageable pageable);
}
My entity factory configuration:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
<property name="packagesToScan" value="loc.starterkit.business"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceUnitName" value="general" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.connection.charSet">${hibernate.connection.charSet}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>
<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
</props>
</property>
</bean>
I don't know why I cannot use sorting in pageable methods in this case . Any ideas?
EDIT:
My Application Entity
#Entity
#Table(name="APPLICATION")
public class Application {
#Id
#Column(name="ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name="NAME")
private String name;
#Column(name="DESCRIPTION")
private String description;
public Application() {
super();
}
.... (getters and setters here)
}
Changing PagingAndSortingRepository to JPARepository seems to throw same warning. BUT, after some tests, I've found out that this WARN means nothing. Things seems to work nicely:
Hibernate:
/* select
count(*)
from
Application as generatedAlias0
where
generatedAlias0.name like :param0 */ select
count(*) as col_0_0_
from
APPLICATION applicatio0_
where
applicatio0_.NAME like ?
Hibernate:
/* select
generatedAlias0
from
Application as generatedAlias0
where
generatedAlias0.name like :param0
order by
generatedAlias0.name asc */ select
applicatio0_.ID as ID0_,
applicatio0_.DESCRIPTION as DESCRIPT2_0_,
applicatio0_.NAME as NAME0_
from
APPLICATION applicatio0_
where
applicatio0_.NAME like ?
order by
applicatio0_.NAME asc limit ?
So I think that this WARN means nothing but I want to know why it's being issued

Unitils - Dbunit ExpectedDataSet fail / blocked

I'm creating a web application with Spring 3.1.0.RELEASE and JPA 2 with Hibernate Provider.
I'm doing the test with junit 4.10 , dbunit 2.4.8, unitils 3.3, hsqldb 2.2.8.
I try to test the service layer, a create operation. In my DAO i have this method:
#Override
#Transactional
public void createQuestion(Question question) {
logger.debug("createQuestion");
entityManager.persist(question);
logger.info("New question created [id] {}", question.getId());
}
My QuestionServiceTest test class :
#SpringApplicationContext("test-applicationContext.xml")
public class QuestionServiceTest extends UnitilsJUnit4 {
#SpringBeanByName
private QuestionService questionService;
#SpringBeanByName
private ThemeService themeService;
#Test
#DataSet("QuestionServiceTest.testCreateQuestion.xml")
#ExpectedDataSet("QuestionServiceTest.testCreateQuestion-result.xml")
public void testCreateQuestion() {
final Question newQuestion = new Question();
newQuestion.setCountryCode("FR");
newQuestion.setEmail("test#mytest.com");
newQuestion.setFirstName("FirstTest");
newQuestion.setLastName("LastTest");
newQuestion.setOriginalLang(LanguageEnum.FR);
newQuestion.setOriginalQuestion("This is the original question");
final Calendar calendar = Calendar.getInstance();
calendar.set(2012, 5, 12);
newQuestion.setCreationDate(calendar.getTime());
final Theme theme = themeService.findThemeById(new Integer(1));
newQuestion.setTheme(theme);
questionService.createQuestion(newQuestion);
}
}
I use the property hibernate.hbm2ddl.auto = create-drop for generate the schema, the question table is:
create table question (
id integer generated by default as identity (start with 1),
country_code varchar(10) not null,
creation_date timestamp not null,
email varchar(255) not null,
firstname varchar(100) not null,
lastname varchar(100) not null,
original_lang varchar(255) not null,
original_question clob not null,
theme_id integer not null,
primary key (id)
)
theme_id is a foreign key to table theme.
When i launch the test with ExpectedDataSet, the insert works but the test never finish.
The test block on :
DEBUG: org.dbunit.database.AbstractResultSetTable - Query: select
"ID", "COUNTRY_CODE", "CREATION_DATE", "EMAIL", "FIRSTNAME",
"LASTNAME", "ORIGINAL_LANG", "ORIGINAL_QUESTION", "THEME_ID" from
"PUBLIC"."QUESTION" order by "ID"
This is the last line on debug.
My unitils.properties is :
# Defaults and other keys with explanations can be found there: http://unitils.org/unitils-default.properties
database.driverClassName=org.hsqldb.jdbcDriver
database.url=jdbc:hsqldb:mem:testOpen
database.userName=sa
database.password=
database.dialect=hsqldb
# This schema is the initial schema when a new session is started in HSQLDB, don't change it or test won't works !
database.schemaNames=PUBLIC
dbUnit.datasetresolver.prefixWithPackageName=false
dbUnit.datasetresolver.pathPrefix=dataSets
My persistence.xml :
<persistence-unit name="OpenTestPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:testOpen" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
</properties>
</persistence-unit>
What should I do? I already try previous release of dbunit or unitils but it doesn't change anything. Expected Dataset is really cool feature.
Thanks.
I had the same issue and failed to solve it. Then I gave a try to
spring-test-dbunit
and this lib run smoothly.

Resources