Skip to content

Latest commit

 

History

History
134 lines (89 loc) · 3.16 KB

File metadata and controls

134 lines (89 loc) · 3.16 KB

💡 What It Means

When you use the <repositories> element in XML or @EnableJpaRepositories in Java config:

🔁 It automatically applies exception translation to any bean annotated with @Repository.


🧱 Why Is That Important?

JPA throws provider-specific exceptions (e.g., javax.persistence.PersistenceException), which are not consistent across different providers (like Hibernate, EclipseLink, etc.).

Spring wraps those into a consistent hierarchy: ➡️ org.springframework.dao.DataAccessException and its subclasses.

So regardless of whether you use Hibernate or another JPA provider, you always catch Spring exceptions like:

  • DataIntegrityViolationException
  • EmptyResultDataAccessException
  • OptimisticLockingFailureException

🧩 How It Works?

Behind the scenes, Spring uses a proxy (AOP) to intercept calls to your @Repository methods and translate any caught exception into one of Spring’s standard exceptions.

Example:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

If save() throws a javax.persistence.EntityExistsException, Spring will catch it and rethrow it as a DataIntegrityViolationException.


✅ Benefit

You get cleaner, portable, and consistent error handling without having to write vendor-specific code.


✅ Scenario

You try to insert a record with a duplicate primary key, which causes a database integrity violation.


🧩 Entity

@Entity
public class User {
    @Id
    private Long id;

    private String email;

    // getters and setters
}

🧩 Repository

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

🧩 Service Layer

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void insertDuplicateUser() {
        User user1 = new User();
        user1.setId(1L);
        user1.setEmail("a@example.com");

        User user2 = new User();
        user2.setId(1L);  // Duplicate ID
        user2.setEmail("b@example.com");

        userRepository.save(user1);
        userRepository.save(user2);  // This will throw exception
    }
}

🧩 Exception Handling in Controller (or caller)

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/test")
    public String test() {
        try {
            userService.insertDuplicateUser();
        } catch (DataAccessException e) {
            return "Spring translated exception: " + e.getClass().getSimpleName();
        }
        return "Success";
    }
}

🧠 What Happens Behind the Scenes?

  • JPA throws a javax.persistence.PersistenceException (or more specifically, EntityExistsException or a SQL exception).
  • Because the repository is annotated with @Repository, and @EnableJpaRepositories is active,
  • Spring catches the JPA exception and wraps it into DataIntegrityViolationException (a subclass of DataAccessException).
  • You can now handle it in a consistent, Spring-style way — independent of your JPA provider.