我有一个Spring MVC应用程序,它使用Spring Data JPA作为我的JPA提供者来持久化Hibernate。我有一个数据库表,在列上有一个唯一的约束,因此为什么保存相应的实体可能会导致唯一的约束冲突。我想检测这是否发生在我的服务层中,以便我可以向用户呈现有意义的错误消息。以下是我的服务方法。
@Service
public class IndustryServiceImpl implements IndustryService {
@Autowired
private IndustryRepository industryRepository;
@Override
@Transactional
public void add(Collection<Industry> industries) {
this.industryRepository.save(industries);
this.industryRepository.flush();
}
}
我的Spring Data JPA存储库看起来像这样:
@Repository
public interface IndustryRepository extends JpaRepository<Industry, Integer> { }
现在,当发生唯一的约束冲突时,我得到以下异常(为简洁起见而缩短):
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
...
org.hibernate.exception.ConstraintViolationException: could not execute statement
...
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "industry_name_unique_index"
Detail: Key (name)=(SomeValue) already exists.
...
如您所见,“main”异常属于javax.persistence.PersistenceException
类型,这是一个非常普遍的异常。理想情况下,我希望捕获一个异常,该异常告诉我错误是由于唯一的约束违规造成的。因此我有几个问题:
javax.persistence.PersistenceException
类型,还是因为Spring异常转换没有启动?我可以配置Spring以提供不太常见的异常吗,例如DuplicateKeyException?e.getCause()
更好的方法来检测更具体的错误吗?我可以很容易地做到这一点,但这对我来说似乎不对,原因有二;首先,代码对我来说似乎更“脆弱”,其次,我还必须检查JPA提供程序特定的异常,因为嵌套异常的类型是org.hibernate.exception.ConstraintViolationException
。如果可能,我希望我的服务不知道我使用的是哪个JPA提供程序。以下是我的持久性配置,以防万一。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = { "com.example.company.repository", "com.example.account.repository" })
public class PersistenceConfig {
@Autowired
private LocalValidatorFactoryBean validator;
@Value("${jndi.data.source}")
private String dataSourceName;
@Bean
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
return dsLookup.getDataSource(this.dataSourceName);
}
@Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
vendorAdapter.setDatabase(Database.POSTGRESQL);
vendorAdapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
String[] packagesToScan = new String[] { "com.example.company.entity", "com.example.account.entity" };
factory.setPackagesToScan(packagesToScan);
factory.setDataSource(this.dataSource());
factory.setValidationMode(ValidationMode.NONE); // Prevents errors when using custom validators when persisting
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(this.entityManagerFactory());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
提前感谢您!
Spring允许通过@存储库
注释透明地应用异常转换。后处理器自动查找所有异常转换器(PersistenceExceptionTranslator接口的实现),并通知所有标记有@Repository注释的bean,以便发现的转换器可以拦截并对抛出的异常应用适当的转换。
总之:您可以基于普通持久性技术的API和注释来实现DAOs,同时仍然受益于Spring管理的事务、依赖注入和到Spring自定义异常层次结构的透明异常转换(如果需要)。
'
<!-- Exception translation bean post processor -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="myProductDao" class="product.ProductDaoImpl"/>
'
直接从这里拿走。
还有,你可以看看这个。
嗯。
我有一个用户创建屏幕,它记录了各种用户详细信息以及名字和手机号码。我有一个对应的用户表,其中名字和手机号码构成一个复合唯一键。此表中还定义了其他完整性约束。 当在创建用户屏幕上输入违反此约束的用户数据时,需要向用户显示“用户友好”错误消息。 当这种违反发生时,我从MySQL数据库中得到的异常是: 有两个选项可以显示有意义的消息(例如:“错误:给定手机号码的用户名已存在,请更改其中一个”)。 选项1
我想用插页。。请务必更新。。对两列具有唯一约束的表的语法。这可能吗? mytable对col1和col2有单独的唯一约束。 我可以写: 然而,这不起作用: 错误:冲突时,更新是否需要推理规范或约束名称 这也不起作用: 错误:不存在与冲突规范匹配的唯一或排除约束 这种语法似乎是为两列上的单一复合唯一约束而设计的,而不是两个约束。 如果违反了其中一个唯一约束,有没有办法进行条件更新?这个问题是如何在博
问题内容: 当违反唯一约束时,将引发a。但是可能有多种原因抛出异常。我如何才能发现违反了唯一约束? 问题答案: 我如何才能发现违反了唯一约束? 异常是链接在一起的,您必须递归调用以获取提供程序特定的异常(并可能转到),以将其转换为应用程序可以很好地为用户处理的内容。下面将打印异常链: 对于异常处理和“翻译”,您可以执行类似于Spring的操作(请参阅各种类,例如,以获取想法)。 所有这些都不是很好
我的桌子有两个独特的列: 我想写保存或更新方法 My jooq code: 但我遇到了异常: “错误:没有唯一或排除约束匹配ON CONFLICT规范” 请帮助。
我有一个实体,比如说雇员 with字段名标记为唯一。 提前谢谢你
问题内容: 问题概述 在看似随机的时间,我们会收到一个异常“ PostgreSQL重复键违反了唯一约束”。我确实认为我知道我们的问题是什么,但是我不想在没有可重现的测试用例的情况下对代码进行更改。但是由于除了随机生产之外,我们无法在任何环境中复制它,因此我要求SO的帮助。 在这个项目中,我们有多个postgres数据库,并且为每个数据库中的每个表配置了主键序列。这些序列是这样创建的: 我们使用以下