I\'m using Spring annotations to manage my transactions like so:
@Transactional(readOnly = true)
public class AlertServiceImpl implements AlertService {
In your scenario your DAO will execute without transaction, most probably with auto-commit.
If you want to avoid this kind of mistake in future and require all your services to run in transaction you can protect DAO layer with following @Transactional
annotation:
@Transactional(propagation = MANDATORY)
public class HibernateAlertDAO extends HibernateDaoSupport implements AlertDAO {
...
}
This annotation will require service layer to declare transaction and will throw exception otherwise.
According to the documentation (Spring docs) it's just metadata to give an indication that the method or interface can be configured by something that is 'transactionally aware' (i.e. <tx:annotation-driven/>
).
With just tx:annotation-driven and no @Transactional
attribute I believe you get the "default" transactionality applied:
Assuming you're using the <tx:annotation-driven />
to drive it via a transaction manager then missing out the @Transactional
attribute means you can't apply such properties as readOnly, isolation, propagation, rollbackFor, noRollbackFor etc.
I believe that MVC is slightly different - the Hibernate session is tied directly to the MVC request - i.e. when the request is received the transaction starts.
Back to your example, the code for getSession() in HibernateDAOSupport is as follows:
protected final Session getSession()
throws DataAccessResourceFailureException, IllegalStateException
{
return getSession(this.hibernateTemplate.isAllowCreate());
}
Which in turn calls to:
/**
* Obtain a Hibernate Session, either from the current transaction or
* a new one. The latter is only allowed if "allowCreate" is true.
*.......
*/
protected final Session getSession()
throws DataAccessResourceFailureException, IllegalStateException {
return getSession(this.hibernateTemplate.isAllowCreate());
}
which ultimately calls to :
/**
* ....
* @param allowCreate whether a non-transactional Session should be created
* when no transactional Session can be found for the current thread
* ....
*/
private static Session doGetSession(
SessionFactory sessionFactory, Interceptor entityInterceptor,
SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
Fundamentally, a Transaction:Session is tied 1:1 AFAIK, and the only way to run without a transaction is by using say JBoss which has a 'baked in' persistence layer which provides the transactionality for you (under the covers). Even if you call getQuery()
after getSession()
you still effectively have a transaction occurring as it's a JDBC/Hibernate connection.
Nothing would happen if you not put the @transactional Annotation Basically @Transactional is not mandatory to put on the top of method signature it is just use to inform compiler when your transactional is read only=true (only for the data retrieval purpose) and when it is read only=false(only for the insert update delete operations)
Without the annotation, you lose the advantages of the transactions like the rollbacks.
With the @Transactional annotation you are doing more than one database operation, like many inserts and one fails, all the operations in the transaction can rollback to give consistency to your data.
That is also why it's recommended to put the annotation in the services not in the DAOs.