Search code examples
javamysqlhibernatejbosstransactions

Hibernate and EJB: how to correctly use @TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)?


I have the following code that I am expecting to persist all or none of the entities in the method.

However, it is behaving that some entities are created and others are not - i.e. the whole transaction is not being rolled back.

Why is this so?

Note - I am running my code as an EAR file in JBOSS EAP server

  @TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
  public void createCompanyStatuses(String client, CompanyStatusPostDTO companyStatusPostDTO) {
    
            EntityManager entityManager = null;
    
            try {
    
                CompanyStatus companyStatus = new CompanyStatus();
                companyStatus.setCompanyLabel(candidateMaskedStatusPostDTO.getCompanyLabel());
    
                entityManager = entityManagement.createEntityManager(client);
                entityManager.persist(companyStatus);
    
                for(Integer employeeStatusId: companyStatusPostDTO.getEmployeeStatuses()){
    
                    CompanyStatusEmployeeStatus companyStatusEmployeeStatus = new CompanyStatusEmployeeStatus();
                    companyStatusEmployeeStatus.setEmployeeId(employeeStatusId);
                    companyStatusEmployeeStatus.setCompanyId(companyStatus.getCompanyId()); //todo - how will get this?
                    entityManager.persist(CompanyStatusEmployeeStatus);
                }
    
            } catch(Exception e){
                log.error("An exception has occurred in inserting data into the table" + e.getMessage(), e);
            } finally {
                entityManagement.closeEntityManager(client, entityManager);
            }
    }

Solution

  • Answer valid for Hibernate.

    TransactionAttributeType.REQUIRES_NEW is not supported.

    It is hard to implement rollback on java object. Imagine scenario when:

    1. Transaction started
    2. Object created and saved
    3. Subtransaction started
    4. Object modified
    5. Subtransaction rolled back.

    You expect object to be in state it was before subtransaction started, so you need to trace information about modification of that object inside subtransaction and ability to roll those modification back.

    Alternatively you could reload state from DB, but you need to track which object belong to which transaction.

    I assume developers just decided that it is too much effort for little gain.