If you do want your DAOs to throw Spring DataAccessExceptions there are two simple things to do.
- Add the @Repository annotation to your DAO impl.
- Add a PersistenceExceptionTranslationPostProcessor bean to your Spring setup.
What this does is tell Spring to wrap an interceptor around your DAO bean that handles the exception translation.
Looking at the UserDaoImpl from the past article...
@Repository
public class UserDaoImpl extends AbstractHibernateDao<User> implements UserDao {
public UserDaoImpl(SessionFactory sessionFactory) {
super(User.class, sessionFactory);
}
...
}
Then in your Spring application context.xml you simply add one line...
Now, this pattern I present is somewhat old school. There is all this fancy component scanning stuff you can do with the Spring 2.5 XML namespaces. Honestly the amount of voodoo that goes on there freaks me out a bit. You can study that on your own if you'd like. A good place to start is here.
4 comments:
Ray, I can't get this to work as is because it's complaining about a missing no arg constructor. The aop proxy and cglib guys are crashing the party. I think it's because I'm using @Transactional in the abstract class:
@Transactional(readOnly = true)
protected List[E] list(final Criteria criteria) {
@SuppressWarnings("unchecked")
final List[E] result = criteria.list();
if (CollectionUtils.isEmpty(result))
return (Collections.emptyList());
return (result);
}
So I had to resort to setters. I'm not too keen on having to use the @PostConstruct annotation because the jar it's in isn't so easily located.
import javax.annotation.PostConstruct;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao extends AbstractHibernateDao[User] {
private final transient Logger log = LoggerFactory.getLogger(getClass());
/**
*/
@PostConstruct
public void init() {
this.log.debug("called");
super.setEntityClass(User.class);
}
/**
* (non-Javadoc)
*
* @see edu.berkeley.ist.waitlist.db_new.dao.api.AbstractHibernateDao#setSessionFactory(org.hibernate.SessionFactory)
*/
@Override
@Autowired
public void setSessionFactory(final SessionFactory sessionFactory) {
this.log.debug("called");
super.setSessionFactory(sessionFactory);
}
}
Suggestions, ideas?
Hmm, couple questions...
Do you have the AbstractHibernateDao or its subclasses annotated as Transactional?
Are you forcing the use of cglib here?
Sorry, I forgot to spell that out. Correct, the abstract class is using the @Transactional annotation, and I'm thinking now that that's not a good idea. I'm thinking that the annotations should be in the service layer class, not the dao. Does that sound right?
Yep, that's exactly what I was getting at.
Post a Comment