Wednesday, April 8, 2009

Attaching detached objects

Iam reading a list and processing each element.
For example I get list of Memberships. Each Membership has a user. Each User has an Address.
If I get list of Memberships in one session. Then try to access address from the user in another session we will get the famous 'no session exception'
We need to attach the user created in the first session to the second one.

session2.update(user);
system.out.printf("user City :"+ user.address().getCity);
so session1 creates memberships.
user.address is invoked by session2.
before we invoke the command, we need to attach user to the session2.
session2.update(user) will do the trick.

Friday, April 3, 2009

Hibernate Transactions with Annotations

The current session is maintained in the SessionFactory throughout the call if it has the @Transactional annotation.

Here are the steps for setting the Transactions

Pass the sessionFactory to the transactionManager.

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>


Add the tx namespace to context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

.
.
.

<tx:annotation-driven />


Place the annotations above the methods you are going to use the sessionFactory.

@Transactional
public Product getProductById(final long id) {
final Session session = sessionFactory.getCurrentSession();
final Product product = (Product) session.get(Product.class, id);
return product;
}



Here are some points to remember:
1. If you want a method to be transactional.
2. The classes that use transactional annotation should use not use constructor autowire. - It will give bean creation exceptions. I have used setter injection autowire byType.
3. If a class is calling a method that needs transaction, The public method needs to be transactional. So you cannot call from outside, a non-transactional public method and then delegate to a transactional method.
4. How do you check if the hibernate transactions are working?
Insert in the method : sessionFactory.getCurrentSession()
If the transactions are not set correctly, you will get errors.
5. If the transaction is going to run a batch job, flush and clear the session at batches of 20 - 30.


final Session session = sessionFactory.getCurrentSession();
int count = 0;
for (final EipCharge charge : eipCharges) {
// Do the stuff .....
.....
if (count % 20 == 0) {
session.flush();
session.clear();
}
count++;
}