出于教育目的,我在純 Spring(沒有 Spring Boot 或 Spring Data JPA)中使用 JPA 設定了一個基本的 CRUD Web 應用程式,但遇到了一個奇怪的問題:Spring 不會為我的存盤庫轉換例外。根據 Spring 檔案(此處和此處),使用@Repository注釋標記存盤庫就足夠了,Spring 將自動為該存盤庫啟用例外翻譯。
但是,當我這樣做并觸發UNIQUE違反約束時,我仍然得到一個 JPA PersistenceException(ConstraintViolationException內部帶有 Hibernate )而不是 Spring DataIntegrityViolationException。
我使用了純 Java Spring 配置,我花了很長時間才意識到我應該將它與檔案中的 XML 配置進行比較。與純 Java 配置相比,XML 配置PersistenceExceptionTranslationPostProcessor在背景關系中添加了一個。當我用 手動添加它時@Bean,它起作用了,但現在我有一個問題。
我是否配置錯誤?Spring 檔案不需要為純 Java 配置手動注冊該后處理器。也許還有另一種注冊方式,比如@EnableXXX注釋?
這是我的配置摘要。
@Configuration
@ComponentScan("com.example.secured_crm")
public class SpringConfiguration {
// the problem is solved if I uncomment this
//@Bean
//public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
// return new PersistenceExceptionTranslationPostProcessor();
//}
}
@Configuration
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
public class DataSourceConfiguration {
@Value("${jdbc.driver}")
private String driverClass;
@Value("${jdbc.url}")
private String url;
// ...
@Value("${hibernate.debug}")
private String hibernateDebug;
@Bean
public DataSource dataSource() {
var dataSource = new ComboPooledDataSource();
// ...
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
var emFactory = new LocalContainerEntityManagerFactoryBean();
emFactory.setDataSource(dataSource());
emFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emFactory.setPackagesToScan("com.example.secured_crm.entities");
var properties = new Properties();
properties.setProperty("hibernate.dialect", hibernateDialect);
properties.setProperty("hibernate.show_sql", hibernateDebug);
properties.setProperty("hibernate.format_sql", "true");
emFactory.setJpaProperties(properties);
return emFactory;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
var txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
}
public interface UserRepository {
User findByName(String username);
List<User> findAll();
void save(User user);
boolean deleteById(int id);
User findById(int id);
}
@Repository
public class UserJpaRepository implements UserRepository {
@PersistenceContext
EntityManager em;
@Override
public void save(User user) {
if (user.getId() == null) {
em.persist(user);
} else {
em.merge(user);
}
}
// and so on...
}
順便說一句,當我嘗試在 中添加后處理器時DataSourceConfiguration,它禁用了@PropertySource效果。到目前為止,我對 Spring 的印象是它是一個大黑客......
uj5u.com熱心網友回復:
它需要手動注冊PersistenceExceptionTranslationPostProcessor才能使例外翻譯生效。
您提到的檔案尚未更新以顯示完整的 java 配置。應該提到注冊這個后處理器。(所以請隨時提供PR來更新檔案。)。
如果你從它的javadoc 中檢查,它已經提到PersistenceExceptionTranslationPostProcessor必須注冊:
因此,啟用自動例外轉換通常需要使用@Repository 注釋標記所有受影響的bean(例如存盤庫或DAO),以及將此后處理器定義為應用程式背景關系中的bean。
PS 如果你使用的是 spring-boot ,如果檢測到PersistenceExceptionTranslationPostProcessor在 class-path 中,默認會自動注冊,不需要手動注冊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/407755.html
標籤:
