简体   繁体   中英

Spring Boot - caling transactional method from non-transactional cause update

I'm wondering about a case, which I encountered recently. Suppose we have a service method as follows:

@Override
public User addUser(UUID organizationId, User user) {
    Organization organization = organizationRepository.findById(organizationId).orElseThrow(IllegalArgumentException::new);
    user.setOrganization(organization);
    organization.getUsers().add(user);
    invitationService.deleteByUserEmail(user.getEmail());
    return user;
}

Organization is provided by a repository method:

@Repository
public interface OrganizationRepository extends JpaRepository<Organization, UUID> {

    Optional<Organization> findById(UUID id);
}

Adding of users works only because invitationService.deleteByUserEmail(user.getEmail()); is present. The entire method belongs to another service and looks as follows:

@Override
@Transactional
public void deleteByUserEmail(String userEmail) {
    invitationRepository.deleteByUserEmail(userEmail);
}

I am not sure if I correctly understand why adding a user works. According to Hibernate Docs, automatic updates occur only, when an entity is in managed state and the update takes place in a single transaction. If my reasoning is correct there are the following steps which occur:

  1. When a request comes and hits the controller, an entity manager (hibernate session) is attached to the current thread. (?)
  2. A controller method which handles the request, calls organizationService.addUser method
  3. Organization is fetched by findById method which is by default transactional and readonly (according to SimpleJpaRepository implementation). This transaction closes after this, but the entity manager bound to it is still running and organization entity remains managed.
  4. The updates occur
  5. invitationService.deleteByUserEmail(user.getEmail()); is called. Because it's transactional method a transaction is started. Deletion occurs, and a transaction is committed and flushes all changes into the database, even the changes made in organization entity.

Is it possible despite of addUser method is non-transactional ?

On one of you configuration classes you may have special filters registered which basically keep the session / entitymanager opened for the life of an entire request:

org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter

or

org.springframework.orm.hibernate5.support.OpenSessionInViewFilter

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM