views:

50

answers:

2

I've encountered a problem I don't really understand - unless a method working with the DAO is annotated as @Transactional, the underlying database doesn't get updated. My app runs on JPA/Hibernate, Spring and Wicket. Why is that?

DAO:

@Repository(value = "userDao")
public class UserDaoJpa implements UserDao {
    @PersistenceContext
    private EntityManager em;

    public User findById(Long id) {
        return em.find(User.class, id);
    }

    public List findAll() {
        Query query = em.createQuery("select e from User e");
        return query.getResultList();
    }

    public User create(User user) {
        em.persist(user);
        return user;        
    }

    public User update(User user) {
        return em.merge(user);
    }

    public void delete(User user) {
        user = em.merge(user);
        em.remove(user);
    }
}

Service:

@Service(value = "userManager")
public class UserManagerImpl implements UserManager {
    @Autowired
    UserDao dao;

    public void setUserDao(UserDao dao) {
        this.dao = dao;
    }

    public List getUsers() {
        return dao.findAll();
    }

    public User getUser(String userId) {
        return dao.findById(Long.valueOf(userId));
    }

    public void saveUser(User user) {
        dao.update(user);
    }

    @Transactional
    public void removeUser(User user) {
        dao.delete(user);
    }
}

In case I leave out the @Transactional annotation, the database doesn't get updated.

A: 

Try to flush and commit.

foret
+2  A: 

Well thats normal: Every database manipulation in the CRUD Scheme needs it's transaction boundaries. Without those boundaries, nothing gets actually written in the DB. A Transaction is a collection of DB Manipulations (inserts, Updates) whoich have all to be successfull or the whole action gets undone by the DB. That's why you have to tell Hibernate when a Transaction starts and ends, so hibernate can tell which actions have to be regardes as Units of Work. Without transaction boundaries the final commit to the database never happens.

hope that helped

smeg4brains
oh, that makes sense. so are usually the transaction boundaries marked on the layer above the service layer, where i group a couple of service layer calls together?
John Manak
nah normally you apply the boundaries on the service layer, but if you like you can also define a additional @Transcational on the layer above and the lower layer transactional methods will partake in the upper transaction. check google for transaction isolation for some examples...
smeg4brains
Chapter 11 of the Hibernate Docs is good starting point to learn that stuff. http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html
smeg4brains