detached vs attached entity in JPA

detached vs attached entity in JPA

  • 1.  Detached Entity :
    • A detached entity is an entity instance that was once associated with a persistence context (like an EntityManager in JPA), but is no longer actively managed.
    • When an entity is detached, it means it was previously managed (attached) by an EntityManager, but the persistence context that tracked it has been closed, the transaction has ended, or the entity has been explicitly detached.
  • 2.  Attached Entity :
    • An attached entity, on the other hand, is actively managed within a persistence context.
    • When an entity is attached, it means it is associated with an EntityManager or a persistence context that tracks its state.
    • Changes made to attached entities are automatically synchronized with the database upon transaction commit or flush.

detached vs attached entity in JPA

Example in Java

Let’s demonstrate the concept of detached and attached entities using a simple Java example with Spring Data JPA:

Entity Class (User.java)
java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String email;

    // Constructors, getters, and setters
}

Service Class (UserService.java)
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Transactional
    public void updateUserEmail(Long userId, String newEmail) {
        // Fetch the user entity by ID (attached entity)
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            // Modify the entity state
            user.setEmail(newEmail);
            // At this point, 'user' is still managed (attached) by the EntityManager

            // Any changes made to 'user' will be automatically synchronized with the database upon transaction commit
        }

        // 'user' becomes detached once the transaction ends or if it's explicitly detached
    }
}

Explanation of the Example

  • updateUserEmail Method : This method fetches a User entity by its ID using userRepository.findById(userId).orElse(null).
  • Attached Entity : Initially, the fetched User entity (user) is attached because it’s managed within the current transactional context (@Transactional).
  • Detached Entity : After the transaction completes (end of updateUserEmail method), the user entity becomes detached. It is no longer managed by the EntityManager and changes to it will not be automatically synchronized with the database.
  • Transaction Management : The @Transactional annotation ensures that the User entity remains attached and any changes made to it are synchronized with the database upon transaction commit.