hibernate and spring dao - java

I have two tables Parent and Child.
Child table references to Parent table.
In application configuration of spring dao. Can't I give configuration of only child?
like below.
<bean id="ChildDAOSpringTarget" class="project.dao.spring.ChildDAOSpring">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<bean id="ChildDAO"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager" />
</property>
<property name="target">
<ref local="ChildDAOSpringTarget" />
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly
</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly
</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly
</prop>
<prop key="store*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Do I have to have add this kind of configuration and classes for Parent even?

I don't config relation between parent and child table in applicationContext.xml but I set the relation in modelXXX.hbm.xml file or you can use hibernate tools to generate model link

In hibernate, parent-child relationship has been defined in hbm file or it will be annotation based. And in application configuration file, you have to define database connection's properties, session factory, bean mapping etc.

Yep as mentioned above... Check here for one to many tutorial which is likely what you are trying to do.
http://www.mkyong.com/hibernate/hibernate-one-to-many-relationship-example/
The child becomes a collection of the parent and is accessed as such.
Spring doesn't need to reference the child - instead you reference the children through the parent like so:
parent.getChildren().[...]

Related

Java and HSQLDB, how to add column automatically after update

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.

Spring 3 and hibernate 4.X facing a transaction Manager Exception in destroy-method

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 !!

hibernate4.LocalSessionFactoryBean cannot be cast to org.hibernate.cfg.Configuration

It seems to be a common problem but I am not able to resolve it.
my Spring 3.1.1 configuration is
<bean id="sessionFactoryEditSolution" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="editSolutions-pool"/>
<property name="mappingResources">
<list>
<value>/editsolutions.hibernate.cfg.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
<prop key="net.sf.ehcache.configurationResourceName">/ehcache.xml</prop>
<prop key="hibernate.max_fetch_depth">6</prop>
<prop key="hibernate.default_schema">dbo</prop>
</props>
</property>
</bean>
And this how I am trying to get the configuration object
Configuration editSolutionsConfiguration = `(Configuration)AppContext.getBean("&sessionFactoryEditSolution");`
Initially I have Hibernate 3 for my application but to integrate it with Spring 3.1.1 I have upgraded it to Hibernate 4 .That's why I have to keep hibernate3.jar in my lib folder to support few hibernate 3 specific code lines.
A couple of notes:
you can't work with two versions of hibernate on the classpath. Your old code should be updated
&x returns the factory bean, it doesn't return the produced object. Even without the ampersand, this would return the SessionFactory, rather than Configuration.
with spring you don't need Configuration actually, it is handled behind the scene
we are working with hibernate 3 and spring 3.1. 3.1.1 might be different, but either keep the lower versions of both, or upgrade both (including code)

Setting spring bean property value using ref-bean

I am trying to set a property value using spring.
<bean id="velocityPropsBean" class="com.test.CustomProperties" abstract="false" singleton="true" lazy-init="false" autowire="default" dependency-check="default">
<property name="properties">
<props>
<prop key="resource.loader">file</prop>
<prop key="file.resource.loader.cache">true</prop>
<prop key="file.resource.loader.class">org.apache.velocity.runtime.resource.loader.FileResourceLoader</prop>
<prop key="file.resource.loader.path">NEED TO INSERT VALUE AT STARTUP</prop>
</props>
</property>
</bean>
<bean id="velocityResourcePath" class="java.lang.String" factory-bean="velocityHelper" factory-method="getLoaderPath"/>
Now what i need to do is insert the result from getLoaderPath into file.resource.loader.path. The value of getLoaderPath changes so it has to be loaded at server startup.
Any thoughts how i can inset the velocityResourcePath value to the property?
Using Spring 3, you can skip the middle stage, and invoke the factory directly using SpringEL:
<prop key="file.resource.loader.path">#{ velocityHelper.loaderPath }</prop>
or perhaps
<prop key="file.resource.loader.path">#{ velocityHelper.getLoaderPath() }</prop>
This would let you remove the velocityResourcePath bean.
Below code might help you.
<import resource="classpath:/DaoContext.xml"/>
<bean id="ClientMasterDao" class="dao.hibernate.impl.ClientMasterImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="ClientMasterServices" class="client.ClientMasterServices">
<property name="clientDao" ref="ClientMasterDao"/>
</bean>

Java: DBunitils + Spring: Different Hibernate-Dialect

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.

Categories