The issue I am having is that I use Spring to manage and load hibernate for my web application. I am currently using OpenSessionInViewFilter. This works as intended when I am viewing the application, but not so well when I am trying to access hibernate from non-view related activities such as a Quartz task or some Runnable thread I create to help with some tasks. This causes the Lazy initialize exception and no session available exceptions to occur.
Here is how I currently use Spring to manage Hibernate
<bean id="mainDataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
[..DB config..]
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="mainDataSource"/>
</property>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
<property name="dataSource"><ref local="mainDataSource"/></property>
</bean>
I then configure DAO objects which extend HibernateDaoSupport and inject them into service classes
<bean id="myDAO"
class="package.myDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="mySvcTarget" class="package.myService">
<property name="myDAO"><ref bean="myDAO"/></property>
</bean>
<bean id="myService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="txManager"/>
</property>
<property name="target">
<ref bean="mySvcTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
So then in my application, myService is injected into my controller classes so I use that to get access to my DAO's. For my situation though it appears I need to access my DAO's (or service preferably) some other way and manually open and close my hibernate sessions since my service classes only seem to be open during view session. I am not exactly sure the best way to do this. All the hibernate configurations are there already in Spring so I'm assuming its just a matter or calling them somehow.
First of all those additional services that you're using (non-views) should be visible by Spring. The simplest way to do it is to use #Service annotation. And to make it work you can add <context:component-scan base-package="your.package"> in your configuration.
After this, if Spring sees your service as a bean, it should be enough to use #Transactional annotation to have Hibernate session in it.
Related
I have a service method that calls a DAO method. The service method is annotated as #Transactional, the DAO method is not. At runtime the following error occurs:
No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
When I make the DAO method #Transactional as well, it works fine.
How can I fix this without touching the DAO? (Most methods are in a super-class DAO which I don't have access to.)
I'm using hibernate-core-3.6.8 and spring-orm-4.1.6.RELEASE
The DAOs are annotated as #Repository, the services as #Service
My applicationContext.xml looks like this (I just provided the important parts - let me know if you need more):
<bean id="contextApplicationContextProvider" class="at.spardat.deploysolution.process.context.ApplicationContextProvider"/>
<tx:annotation-driven/>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<util:properties id="hibernateProperties" location="classpath:hibernate.properties"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
p:dataSource-ref="dataSource" p:hibernateProperties-ref="hibernateProperties">
<qualifier value="default"/>
<property name="mappingLocations">
<list>
<value>classpath:....hbm.xml</value>
</list>
</property>
<property name="lobHandler" ref="defaultLobHandler"/>
</bean>
<bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" lazy-init="true"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"/>
<bean id="dataFieldMaxValueIncrementer" class="org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer"
p:dataSource-ref="dataSource" p:incrementerName="TB_OID_SEQUENCE" p:columnName="OID_VALUE">
<qualifier value="default"/>
</bean>
Can you change
hibernate.current_session_context_class=thread
in your hibernate properties file
Thanks
I was working on an spring application before which uses HibernateTransactionManager for transactions with queries/updates using jdbc template and works fine as well.
Below was the code used
<bean id="sybaseDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="MySybaseDS"/>
<property name="lookupOnStartup" value="false"/>
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="sybaseDataSource" />
<property name="mappingResources">
<list>..........</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.SybaseAnywhereDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
I am creating a new application and confused now whether to use the HibernateTransactionManager or JpaTransactionManager or both(possible?).
The application will use both HibernateTemplate and JdbcTemplate(for bulk updates) for database operations and need to be transactional.
I mean, can/should I use HibernateTransactionManager for transactions with jdbctemplate and HibernateTemplate database operations? Will there be any performance bottleneck of using one transaction manager over another?
The short answer is that it will work. See also this thread for a description of the low-level details.
If the application is JPA based (an entity manager factory is configured), then the JpaTransactionManager should be used.
This transaction manager binds an entity manager to the thread during the duration of the transaction.
The HibernateTransactionManager is for applications that don't use JPA but use instead use Hibernate directly (a session factory is configured).
This transaction manager binds a hibernate session to the thread instead of an entity manager.
They do basically the same, it's just one handles a Session while the other handles an EntityManager. Their choice is simply dictated by the fact that JPA is used or not.
Both transaction managers are compatible with the JdbcTemplate, according to their respective javadocs.
There are no performance consequences of using one transaction manager versus the other.
Internally the entity manager uses a Hibernate session, so the end result is the same: a hibernate session is binded to the thread directly or indirectly during the duration of the transaction.
Looking for some advice before I start a minor project...
I have a Java EE project which uses Spring 3 and Hibernate 3.6 to access a database, in which I've created quite a few APIs to access the database. There are several other applications that need to use these APIs (backed by the same database), so I'd like to break them out into distributable JARs.
Problem is - I can't figure out a good way to distribute a library that is backed by Hibernate. I use annotations, not config files for Hibernate. Each API has a singleton which, in my application, is setup as a Spring bean and consumes a SessionFactory. The Spring bean (copied below) has a few configuration items.
So, my questions are:
I would like to decouple the library from Spring (so the other applications don't necessarily have to use Spring). Is that realistic?
What is the best way to take a DataSource instance (the common
denominator for each application), turn it into a SessionFactory and
pass it to the singleton?
Is there a way to encapsulate the few hibernateProperties items from the bean below, so they're in the library rather than in a config file?
The singletons use the Spring transaction manager with the #Transactional annotation. Obviously that's coupled with Spring, so I suppose I'd have to remove it if I want to make this Spring-agnostic? Should I switch to programmatic transaction management?
So that's the story - does this sound doable?
Spring config:
<jee:jndi-lookup id="dataSource" jndi-name="oracleDatabase" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.company.data.DataManagerSingleton</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.default_schema">schema_name</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
</props>
</property>
<property name="packagesToScan">
<value>com.company.data</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<qualifier value="ec" />
</bean>
Thanks.
What is this error about? "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here".
My spring config file looks something like this.
<bean id="jndiDataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:/devDS</value>
</property>
</bean>
<bean id="stsaDBFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="jndiDataSource" />
<property name="annotatedClasses">
<list>
<value>xx.yy.zz.User</value>
<value>xx.yy.UserResponse</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbmddl.auto">create</prop>
</props>
</property>
</bean>
<!-- ################################### Aspects ################################################## -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="stsaDBFactory" />
</property>
</bean>
All the DAO test passes when i test them outside of the container using junit. When I deploy it in jBoss as a portal app,I get this exception. Also it works fine if i remove the portal specific configuration and make it a simple web app and deploy it on jboss.Any idea?
You have defined a TransactionManager in your spring config but you are trying to execute a hibernate query in a method that is not transactional. Try adding #Transactional to your method or class.
I got around this problem by specifying the current_session_context_class in hibernate config to be "thread", as per the simple configuration shown in the hibernate configuration documentation.
But it recommends that its not safe for production usage.
Trying to add the following in your hibernate config should also help:
<property name="current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</property>
Check out http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/architecture.html#architecture-current-session for more details.
I would like to have multiple Hibernate SessionFactories in a spring application, all of them with identical configurations except for the DataSource. Ideally, I would acquire a particular SessionFactory by name. I need to be able to do this based on runtime state, and it isn't possible to determine which session factories I will need at application startup time. Basically, I need a SessionFactoryTemplate or something like it.
Is this possible? How do I go about doing it?
You might define an abstract bean and use bean inheritance. This means you'll have a bean definition that works as a template and you may have multiple beans just copying the attributes set by the parent bean.
Here's an example:
<bean id="abstractSessionFactory" abstract="true"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>
<bean id="mySessionFactory" parent="abstractSessionFactory">
<property name="dataSource" ref="myDataSource"/>
...
</bean>
<bean id="mySessionFactory2" parent="abstractSessionFactory">
<property name="dataSource" ref="myDataSource2"/>
...
</bean>
Using the attribute 'abstract' you ensure that bean won't be instantiated and it will be used just as a template.
More info here: link text
Are you sure you need multiple SessionFactories? If all the mappings/configurations are the same and you just have multiple identical databases (e.g. in a multi-tenant app?), then how about having a single SessionFactory that connects to a DataSource which dynamically supplies the appropriate database connection?
See this question for more details:
And this blog post on Dynamic DataSource Routing in Spring.
I have no idea what your current bean definition looks like now, but wouldn't you just ... define a second SessionFactory?
<bean id="mySessionFactory1"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource1"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>
<bean id="mySessionFactory2"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource2"/>
...
</bean>
You could then simply just wire your DAOs up with one sessionFactory vs the other:
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="sessionFactory" ref="mySessionFactory1"/>
</bean>
<bean id="myCompanyDao" class="product.ProductDaoImpl">
<property name="sessionFactory" ref="mySessionFactory2"/>
</bean>
I don't know of an easy solution for your problem using Spring.
However, you could be able to use Hibernate Interceptors, provided that your particular databases/data-sources can be reached through one master/admin database connection. This blog post explains how in detail, but the gist of it is to dynamically replace table names in SQL statements that Hibernate generates, with qualified names identifying different databases. This is relatively easy to understand and maintain, and works well in my company's multi-tenant set-up.
Apart from that, you can try writing your own TransactionManager, using the HibernateTransactionManager as a starting point, adding support for working with multiple session factories. However, this would mean you having to really dive into Spring ORM support internals, and that is something I tried, but then scrapped in favor of the first approach. I'm sure it can be done with moderate effort, but the previous solution was already doing the job for us.