A little background: I'm using Spring and Hibernate to create a really simple domain/dao/service structure. I'm also using Autowiring to inject all my beans into their happy places.
While refactoring, I recently got the all-too-popular error message "could not initialize proxy - no Session" when trying to access a FetchType.LAZY property on my hibernate object. It goes something like this:
public class Person {
...
#ManyToOne(cascade = {}, fetch = FetchType.LAZY)
#JoinColumn(name = "pet_id", nullable = false)
public Pet getPet() {
return pet;
}
...
}
I used to have a PersonService bean that accessed the Pet property, and had no trouble doing so. However, I recently refactored the code so that instead of the PersonService looking at the Pet, a PersonHelper looks at it. While my helper bean can see the PersonDao, can make a call to get the person, it cannot access the Pet as my session is closed.
So, I think that I'm unclear as to when I loose my hibernate session. All the configs look fine, and the DAO is getting injected into my helper, just like it used to get injected into my service. I'm not sure why my service could get the Pet just fine, but my helper cannot.
Any help with understand this "SessionFactory mystery" is well appreciated. I realize this might be a complicated subject, so links to some good reading material would rock.
I've since changed the code to FetchType.EAGER (working fine), but this riddle is burning a whole in my brain :).
Per requests, here is a (simplified) look into my config:
<bean id="personSvc" class="org.comp.service.impl.PersonServiceImpl" />
<bean id="personHelper" class="org.comp.service.helper.PersonHelper" />
<bean id="personDao" class="org.comp.dao.hibernate.HibPersonDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
...
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="packagesToScan" value="org.comp.domain"/>
<property name="schemaUpdate" value="true" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider
</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">/hibernate-ehcache.xml</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
DAO is autowired into the helper:
#Autowired
private PersonDao personDao;
Without seeing the code/context config for PersonService, I can only guess as to why it worked before the refactoring. If you're using a HibernateInterceptor to wrap session management around your DAO methods, then the session is closed immediately after the method has finished, unless it was opened beforehand (such as by a OpenSessionInViewFilter).
My guess is that the scope of the HibernateInterceptor may have changed during refactoring so that the session is now closed immediately after the data is fetched. You may want to look at extending the scope of HibernateInterceptor to cover your service/business methods, so that the session is kept around long enough for lazy fetching to work, or, alternatively, use the OpenSessionInViewFilter, which ensures the session is always available.
OSIV is always a must-read be it you are writing a web-based application or not.
I use the #Transactional tag in my Spring beans' methods (at the service layer) and let Spring to manage the session for me that way (Spring handles Hibernate's session per thread by default).
Related
I have the following Spring/Hibernate configs:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="jndiDataSource" />
<property name="annotatedClasses">
<list>
...
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
I am extensively using spring transaction annotations to control transaction propagation methods throughout my code base. It is all working great.
I have a need to perform an update that will affect many rows at once and I want to blend it in with the rest of my transaction logic. The last thing I want to do is to bull in a china shop and load all objects into memory and loop through them changing them one at a time.
I am trying something like:
#Autowired
private SessionFactory sessionFactory;
...
String hql = "UPDATE TABLE_NAME SET COLUMN_LIST WHERE ID IN :list";
// I see the transaction and get an error when I try to start a new one.
Transaction trans = sessionFactory.getCurrentSession().getTransaction();
Query query = sessionFactory.getCurrentSession().createSQLQuery(hql);
query.setParameterList("list", listOfIds);
success = (query.executeUpdate() == listOfIds.size());
I have tried dropping this into a method with its own transaction instructions, but am not seeing any evidence that it is being executed (other than a lack of errors).
What is the recommended way to include custom Hibernate SQL into Spring managed transactions?
Thanks a lot.
I have an existing Project working fine, but now I have to implement a Backup System that is executed exery day and dumps the Database to a File. I want to solve this using a ScheduledTask, but this means that there is another Thread using Hibernate.
My Question: How exactly can I make Hibernate Thread safe?
I have the following code-(snippets):
In applicationContext.xml
<bean id="myEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dbDataSource" />
<property name="packagesToScan" value="redb.main.core.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop>
<!-- <prop key="hibernate.enable_lazy_load_no_trans">true</prop> -->
</props>
</property>
</bean>
<!-- Transaction Management -->
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
So I can get the EntityManager by
#PersistenceContext
protected EntityManager entityManager;
But if i understood it correctly, every Thread needs its own EntityManager from the EntityManagerFactory.
How can I create a new EntityManager in an other class?
I have no persistence.xml. Do I have to create it?
He-he. Welcome in the hell.
The main problem, that spring tries to do that with an aspect-based solution. Although this is buggy (or undebuggable), in trivial cases it can work.
The general answer to your question is that the EntityManagerFactory can be a global, static object in your software, although I were stoned if I simply used that.
By default, the spring aop "weaves" your application on deployment, finds all of the database entity classes by their annotations, and wraps their methods to provide always an existing entitymanager. This is the theory. But it is not the practice.
The practice is that you have very little control over what exactly will happen.
What I did: there is a servlet filter named org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter, which can open an entitymanager for every request, and flush/close that on need. Yes, its name is about "views", but soon its name is its first bug: practically we had to call it as "requesttransactionfilter" or such. It hasn't anything with the MVC views to do, it is working on the http request entities coming from your servlet container.
If you don't like to use servlet filters in a spring application, there is a also a spring interceptor named OpenEntityManagerInViewInterceptor with the very similar functionality, too.
Programmatically, you can generate an EntityManager from an EntityManagerFactory by its createEntityManager() method.
Happy googling! You are on the begin of a long way.
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.
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.
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.