Search code examples
javaspringhibernatehibernate-mapping

Hibernate - Error at child level does not rollback parent insertion into database


Ok so I have a one to many relationship between user and account and one to one between account and account_details. When an error occurs during the insert of an user at the level of account_details the account does not get inserted but a record for user does. Similarly if the error occurs at the level of the account a user account is inserted. EntityManager is supposed to handle rollbacks for the transactions but it is not the case. Strangely when I update a user account and add accounts to it, a failure at the level of the added accounts rolls back any updates to the user model.

persistence xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="userPersistenceUnit" transaction-type="RESOURCE_LOCAL" >
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <class>com.urbanbuz.model.User</class>
    <class>com.urbanbuz.model.Account</class>
    <class>com.urbanbuz.model.AccountDetails</class>
</persistence-unit>
</persistence> 

UserDAO:

@Repository("userDao")
@Transactional(propagation = Propagation.REQUIRED)
public class UserDAO {
@PersistenceContext
private EntityManager entityManager;

public EntityManager getEntityManager() {
    return entityManager;
}

public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

public void insert(User user) {
    entityManager.persist(user);
}

public void update(User user) {
    entityManager.merge(user);
}
}

Calling the method to insert user:

@Service
public class UserService {
private UserDAO userDAO;

public UserDAO getUserDao() {
    return userDAO;
}

@Autowired
public void setUserDao(UserDAO userDAO) {
    this.userDAO = userDAO;
}

// summary of method, much code was omitted 
public boolean addUser(User user) {
    // add new user and user accounts
    Set<Account> accounts = new HashSet<Account>();

    Account a = new Account();  
    a.setUser(user);

    AccountDetails ad = new AccountDetails();
    ad.setAccount(a);

    a.setAccountDetails(ad);

    accounts.add(a);

    user.setAccount(accounts);

    try {
        getUserDao().insert(user);
    }
    catch(Exception e) {
    }
}
}

Relationship defined as follows:

at user model level:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="user")
private Set<Account> accounts;  

at account model level:

@ManyToOne
@JoinColumn(name = "user_id") 
public User getUser() {  
    return user;  
}  

Solution

  • In case anyone faces the same problem - I changed the table type from MyISAM to InnoDB that supports the implemented rollback.