I have an application in Java Spring using HSQLDB database.
For an evolution, i have to add a column to an existing table.
So, I have done what I have to do (adding the attribute in the entity class with the info) but when i deploy my new app in tomcat, the database is not updated and i can't start my app.
Is it possible to add the column automatically?
Here is the configuration of the database in the applicationContext.xml:
<bean id="myEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceDb" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
Thank you for your help.
Of course, if you using Hibernate, you can make use of auto-generation from object model.
But this way is not good for a production use.
I suggest you to use database migration tool. It provide you means for auto execution of your sql scripts in certain order.
Look at flyway, liquibase.
Thank you very much for your help.
This is all the actions I did to update the database structure with flyway. It may help someone, one day.
Add Flyway dependency to my pom.xml : http://flywaydb.org/documentation/api/
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>3.2.1</version>
</dependency>
Add the Flyway configuration to my application context:
<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
<property name="baselineOnMigrate" value="true" />
<property name="dataSource" ref="dataSourceDb"/>
</bean>
<bean id="persistenceUnitManager" depends-on="flyway"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="defaultDataSource" ref="dataSourceDb" />
</bean>
I have added the property baselineOnMigrate because I had an error, and the error message said that set this property to true will fix the problem.
Create a script under the folder src/main/resources/db/migration named V2__add_datatype_column.sql
ALTER TABLE PUBLICATION ADD COLUMN datatype varchar(6);
Build, it works.
Thanks a lot to retroq, Rich and Michael Pralow for your answers.
Related
I have a java application in which I'm using Spring and Hibernate frameworks. On my production environment, it would take too long (upto an hour) to start the application properly, as in, within 10 minutes. I could see the login page but if I try to login, it would just keep processing. Only after an hour or so, I would be able to login.
After some research I found that by default hibernate.temp.use_jdbc_metadata_defaults is set to true, in which case it takes time, so I set it to false. Now my application is starting up quickly in my local system when I point it to production db to test. Even in test environment it performs as expected. But when I rolled it out to production, it worked fine initially but now it again is taking too long to start up.
Any idea how to approach it now?
EDITED: adding more details:
initial startup time is huge. once it is up then pages would load fine. we are using postgres db and have multiple schemas. Please suggest what other details are needed
Below is session factory onfiguration:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mydb"/>
<property name="entityInterceptor" ref="nullToEmptyStringInterceptor" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.multiTenancy">SCHEMA</prop>
<prop key="hibernate.tenant_identifier_resolver">path_to.DataBaseResolver</prop>
<prop key="hibernate.multi_tenant_connection_provider">path_to.MultiTenantProvider</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>path_to_model_package</value>
</list>
</property>
</bean>
Below is entityManagerFactory configuration
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="mydb" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="persistenceUnitName" value="myPersistenceUnit" />
<property name="packagesToScan" >
<list>
<value>path_to_model_package</value>
</list>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<prop key="hibernate.jdbc.use_get_generated_keys" >true</prop>
</props>
</property>
</bean>
I don't think we can tell you what the problem is. It will be something to do what the applications is doing during startup, and we can only guess what that would be.
However ...
What you should do is to profile the application during startup, and use the profiling to identify where most of the time is being spent. Then look to see if you can work out what it its doing ... and optimize it.
It would also be work turning on GC logging to see if memory usage / garbage collection is part of the problem. Ditto for checking if database activity is a significant bottleneck.
Finally, an important step in finding the cause of this problem is likely to be understanding the internal architecture of the application. Especially if this is code that has been passed from developer to developer over a number of years.
As you did not posted full details of your problem, like hibernate, spring and other app configurations so suggesting you a solution is bit difficult. The following could be possibilities:
Somewhere there could be deadlock during application load time. For example, so batch job running in background before the container completely starts.
If your db schema is always checked to be updated after the container start and your db is having a large number of tables and columns with a lot of data inside then it would definitely take time before that application loading completes.
Check server configurations like if there is another instance of application running in parallel which is causing delay.
I have a question. I was playing around with JSF/ Spring/ Hibernate and HSQL.
I have a small test application for this purpose and for one feature I wanted to implement I needed a possiblity to persist some data. I didn't wanted to have a full fledged database, so I choose HSQL. Starting from this tutorial (http://devcrumb.com/hibernate/hibernate-jpa-spring-and-hsqldb) I build my application. I had some problems with datatypes and I have chosen to build my database from a script.
Like in the tuorial I had defined my datasource like this in my application.xml, except that I had changed the url property to use a file.
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:hsql://localhost/testdb</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="jpaData" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
Now, I have changed the datasource to something like this:
<jdbc:embedded-database id="dataSource" type="HSQL">
<jdbc:script location="classpath:embeddedDbStructure.sql" />
</jdbc:embedded-database>
Everything works fine so far.
My problem is, that this database is deleted when the server is shut down. Is there a possibility to use both? A script as base for the structure of my database but the db itself is written to a file on my filesystem so that it is available after a server restart? I know there are propably a few solutions to achieve this via some code, but is there a possibility to configure it that way?
Thanks in advance
Actually for your case, you are using the hsqldb in-memory mode, the spring is house a inmemory database indeed. To reuse the file database you need to update the hsqldb mode to use the "In-Process Mode" like "jdbc:hsqldb:file:testdb"
And a sample question is Embedded HSQLDB persist data to a file, you can refer to this.
We are currently using Spring 3 with hibernate 4.4 in our project.
A snippet of my database config xml looks as follows
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass">
<value>${jdbc.driver.className}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
<prop key="hibernate.current_session_context_class">managed</prop>
</props>
</property>
<property name="packagesToScan" value="com.sample.entity" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<tx:annotation-driven />
While we were testing our war , we came across this exception .
13:27:19,511 ERROR TransactionInterceptor:419 - Application exception overridden by rollback exception
org.springframework.beans.factory.BeanCreationNotAllowedException:
Error creating bean with name 'transactionManager': Singleton bean creation not allowed
while the singletons of this factory are in destruction (Do not request a bean from a
BeanFactory in a destroy method implementation!)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:212)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:248)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:100)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
I am unable to figure out if this is because of the destroy-method =close mentioned in the config file . I am also using the #Transactional annotation at both the Service layer and the database layer . Will this cause any issue?
We were trying to test a scenario where in multiple people (around 150) are all trying to access our application at the same time.
Kindly help me out.. Please do let me know, If more details are needed.
Thanks
As the spring doc says in Section 3.6.1.5
The order of startup and shutdown invocations can be important. If a "depends-on" relationship exists between any two objects, the dependent side will start after its dependency, and it will stop before its dependency. However, at times the direct dependencies are unknown. You may only know that objects of a certain type should start prior to objects of another type. In those cases, the SmartLifecycle interface defines another option, namely the getPhase() method as defined on its super-interface, Phased.
So you need the bean to implement the SmartLifeCycle, Javadoc for SmartLifeCycle Interface 1: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-lifecycle-processor.
Hope this helps !!
Context.xml
<jdbc:initialize-database data-source="dataSource" ignore-failures="ALL">
<jdbc:script location="classpath:scrubd.sql"/>
</jdbc:initialize-database>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbc.JDBCDriver"/>
<property name="url" value="jdbc:hsqldb:mem:mydb"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
depends-on="dataSource"
name="_sessFac">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="hibernate.cfg.xml.incDTD"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.shutdown">true</prop>
</props>
</property>
</bean>
When I am running my ant target on my unit tests, after spring gets initialized the first time, I get an out of memory error. Yet, when I populate my tables by simply naming my database import.sql and letting hibernate handle it, I do not get this out of memory error.
Why does this happen?
Also, it takes Spring about a second longer to load the data in the database than hibernate. Bonus points to anyone that can explain why.
StackTrace (from ant)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:2694)
at java.lang.String.<init>(String.java:234)
at java.lang.StringBuffer.toString(StringBuffer.java:561)
at org.apache.tools.ant.util.StringUtils.replace(StringUtils.java:92)
at org.apache.tools.ant.util.DOMElementWriter.encodedata(DOMElementWriter.java:501)
at org.apache.tools.ant.util.DOMElementWriter.write(DOMElementWriter.java:236)
at org.apache.tools.ant.util.DOMElementWriter.write(DOMElementWriter.java:221)
And the bean causing it has got to be my session factory, since I wouldn't call <jdbc:initialize-database/> a 'bean'.
I want to say based on the stack trace that it is reading the entirety of my sql script into a string, since it is quite large; ~38K lines.
Ended up just saying screw it, and letting hibernate populate my tables. The fact that I am now reading in a 20mB file when doing my unit tests, and I am still not getting an out of memory error with hibernate makes me think that if you want to populate your tables before doing unit tests on them, don't let spring do it. Live and learn.
I currently use spring for depency injection. Hibernate uses a postgres dialect for the normal run, but I want to use HSQL for the DBUnitils Databank-Testing.
My Spring-Configuration contains this:
<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="use_outer_join">${hibernate.use_outer_join}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.provider_class">${hibernate.cache.provider}</prop>
<prop key="hibernate.connection.pool_size">10</prop>
<prop key="hibernate.jdbc.batch_size">1000</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>de.dbruhn.relations.model.Relation</value>
<value>de.dbruhn.relations.model.RelationData</value>
<value>de.dbruhn.relations.model.RObject</value>
<value>de.dbruhn.relations.model.Type</value>
</list>
</property>
<property name="schemaUpdate" value="${hibernate.schemaUpdate}"/>
</bean>
The fields get replaced by maven resource-filtering.
The Spring-Configruation for DBUnitils contains this:
<bean id="dataSource" class="org.unitils.database.UnitilsDataSourceFactoryBean"/>
</beans>
and so overrides the dataSource from my run configuration with the UnitilsDataSource.
The Problem: I cant run the Tests using Postgres-Dialect against the HSQL-Test-Database because some commands dont work.
The only solution which came to my mind: Switching the resource-filter in maven, but I have to do this by hand (by provining a "-P TEST" on every maven call). So isn't there a possibilty to override the hibernate.dialect?
Thanks!
You normally don't need to specify the dialect at all, Hibernate will figure it out by looking at the underlying datasource. You only need to specify the dialect if you want to force Hibernate to use a specific one.
In your case, you should just be able to remove the dialect property completely, and it should work in postgres and hsql without config modification.
You should possibly look at using the PropertyPlaceHolderConfigurer in spring to change the config. That way you need only supply a different config file for the different environments, the spring xml stays the same.
And you can load the config file like this.