- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遇到了识别哪个约束触发 DataIntegrityViolationException 的问题。我有两个独特的限制条件:用户名和电子邮件,但我没有找到答案。
我试图找出根本原因异常,但我收到了这条消息
唯一索引或主键违规:“UK_6DOTKOTT2KJSP8VW4D0M25FB7_INDEX_4 ON PUBLIC.USERS(EMAIL) VALUES ('copeland@yahoo.com', 21)”;语句:
插入用户 (id, created_at, updated_at, country, email, last_name, name, password, phone, sex, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23505-193]
阅读错误我知道电子邮件约束会触发验证,但我想返回给用户,例如:{type: ERROR, message: "The email already exist"}
我在其他帖子中读过,人们处理它是为了在异常中寻找约束名称(例如,users_unique_username_idx
)并向用户显示正确的消息。但是我无法获得那种类型的约束名称
也许我缺少配置。我正在使用:
Spring Boot 1.5.1.RELEASE、JPA、Hibernate 和 H2
我的application.properties
spring.jpa.generate-ddl=true
用户类:
@Entity(name = "users")
public class User extends BaseEntity {
private static final Logger LOGGER = LoggerFactory.getLogger(User.class);
public enum Sex { MALE, FEMALE }
@Id
@GeneratedValue
private Long id;
@Column(name = "name", length = 100)
@NotNull(message = "error.name.notnull")
private String name;
@Column(name = "lastName", length = 100)
@NotNull(message = "error.lastName.notnull")
private String lastName;
@Column(name = "email", unique = true, length = 100)
@NotNull(message = "error.email.notnull")
private String email;
@Column(name = "username", unique = true, length = 100)
@NotNull(message = "error.username.notnull")
private String username;
@Column(name = "password", length = 100)
@NotNull(message = "error.password.notnull")
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
@Enumerated(EnumType.STRING)
private Sex sex;
@Column(name = "phone", length = 50)
private String phone;
@Column(name = "country", length = 100)
@NotNull(message = "error.country.notnull")
private String country;
public User() {}
// Getters and setters
}
ControllerValidationHandler.class
@ControllerAdvice
public class ControllerValidationHandler {
private final Logger LOGGER = LoggerFactory.getLogger(ControllerValidationHandler.class);
@Autowired
private MessageSource msgSource;
private static Map<String, String> constraintCodeMap = new HashMap<String, String>() {
{
put("users_unique_username_idx", "exception.users.duplicate_username");
put("users_unique_email_idx", "exception.users.duplicate_email");
}
};
// This solution I see in another stackoverflow answer but not work
// for me. This is the closest solution to solve my problem that I found
@ResponseStatus(value = HttpStatus.CONFLICT) // 409
@ExceptionHandler(DataIntegrityViolationException.class)
@ResponseBody
public ErrorInfo conflict(HttpServletRequest req, DataIntegrityViolationException e) {
String rootMsg = ValidationUtil.getRootCause(e).getMessage();
LOGGER.info("rootMessage" + rootMsg);
if (rootMsg != null) {
Optional<Map.Entry<String, String>> entry = constraintCodeMap.entrySet().stream()
.filter((it) -> rootMsg.contains(it.getKey()))
.findAny();
LOGGER.info("Has entries: " + entry.isPresent()); // false
if (entry.isPresent()) {
LOGGER.info("Value: " + entry.get().getValue());
e=new DataIntegrityViolationException(
msgSource.getMessage(entry.get().getValue(), null, LocaleContextHolder.getLocale()));
}
}
return new ErrorInfo(req, e);
}
此时的响应是:
{"timestamp":1488063801557,"status":500,"error":"内部服务器错误","exception":"org.springframework.dao.DataIntegrityViolationException","message":"无法执行语句;SQL [n/a];约束 [\"UK_6DOTKOTT2KJSP8VW4D0M25FB7_INDEX_4 ON PUBLIC.USERS(EMAIL) VALUES ('copeland@yahoo.com', 21)\"; SQL 语句:\ninsert into users (id, created_at, updated_at , country, email, last_name, name, password, phone, sex, username) values (null, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [23505-193]]; 嵌套异常是 org.hibernate.exception.ConstraintViolationException: 无法执行语句","path":"/users"
更新
这是我处理持久化操作的服务层
MysqlService.class
@Service
@Qualifier("mysql")
class MysqlUserService implements UserService {
private UserRepository userRepository;
@Autowired
public MysqlUserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public List<User> findAll() {
return userRepository.findAll();
}
@Override
public Page<User> findAll(Pageable pageable) {
return userRepository.findAll(pageable);
}
@Override
public User findOne(Long id) {
return userRepository.findOne(id);
}
@Override
public User store(User user) {
return userRepository.save(user);
}
@Override
public User update(User usr) {
User user = this.validateUser(usr);
return userRepository.save(user);
}
@Override
public void destroy(Long id) {
this.validateUser(id);
userRepository.delete(id);
}
private User validateUser(User usr) {
return validateUser(usr.getId());
}
/**
* Validate that an user exists
*
* @param id of the user
* @return an existing User
*/
private User validateUser(Long id) {
User user = userRepository.findOne(id);
if (user == null) {
throw new UserNotFoundException();
}
return user;
}
}
更新#2
repo 重现问题 https://github.com/LTroya/boot-users .我在 ValidationExceptionHandler.class
上评论了我的处理程序,以便查看异常。
发送两次 json at Json to test on Readme.md to POST/users/
最佳答案
您要做的不是在 @Column
注释上指定唯一的列要求,您可以在 JPA 的 @Table
注释上实际定义那些具有名称的列提供对这些约束的进一步控制。
@Entity
@Table(uniqueConstraints = {
@UniqueConstraint(name = "UC_email", columnNames = { "email" } ),
@UniqueConstraint(name = "UC_username", columnNames = " { "userName" } )
})
现在有两种处理异常的方法:
您可以选择将解析逻辑放在您的 Controller 中,并简单地捕获 spring 抛出的 DataIntegrityException
并在那里解析它。类似于以下伪代码:
public ResponseBody myFancyControllerMethod(...) {
try {
final User user = userService.myFactoryServiceMethod(...);
}
catch ( DataIntegrityException e ) {
// handle exception parsing & setting the appropriate error here
}
}
对我来说,这种方法的最终症结在于,我们将处理持久性问题的代码向上移动了两层,而不是直接位于持久性层之上的层。这意味着如果我们有多个 Controller 需要处理这种情况,我们要么发现自己正在执行以下操作之一
将代码放在表示层中还会引入一些问题,当您需要与可能实际上不会返回某种类型的 html View 的其他消费者类型共享该服务时。
这就是为什么我建议将逻辑再向下推一层。
这是一种更简洁的方法,因为我们将约束处理的验证推送到持久层之上的层,这意味着我们最终将在其中处理持久性故障。不仅如此,我们的代码实际上记录了失败条件,我们可以根据上下文选择忽略或处理它们。
这里需要注意的是,我建议您创建从服务层代码中抛出的特定异常类,以便识别唯一约束失败并在解析来自 hibernate 。
在您的 web Controller 、rest Controller 或任何其他正在调用您的服务的消费者中,您只需要在必要时捕获适当的异常类并相应地进行分支。这是一些服务伪代码:
public User myFancyServiceMethod(...) {
try {
// do your stuff here
return userRepository.save( user );
}
catch( ConstraintViolationException e ) {
if ( isExceptionUniqueConstraintFor( "UC_email" ) ) {
throw new EmailAddressAlreadyExistsException();
}
else if ( isExceptionUniqueConstraintFor( "UC_username" ) ) {
throw new UserNameAlreadyExistsException();
}
}
}
关于java - 标识触发 DataIntegrityViolationException 的约束名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42462829/
我正在使用 Spring 3 来管理数据库事务。每当引发异常时,我都会捕获异常并返回相应的消息。但是当 Spring 提交事务时,异常再次引发并包含在 org.springframework.dao.
我正在使用 Spring Boot 和 MySQL 作为数据库编写简单的 Web 应用程序。代码如下 我有一个实体用户: @Entity @IdClass(UserKey.class) public
我正在编写一个 Spring 应用程序,似乎当我遇到数据库错误时,有时 Hibernate 的 ConstraintViolationException有时会抛出 Spring 的 DataInteg
我有这样的关系。有一个 Car 表和 CarGroup 表。汽车组表中存放着汽车。我想要的是:当一辆车被移除时,如果它在一个汽车组内,它也应该像往常一样从那里移除。我在我的项目中使用 Spring 和
我正在使用 Spring 制作 REST API,但在对其进行单元测试时遇到了麻烦。我编写了一个端点来更新用户组,当我在前端创建一个具有重复名称的组时(unique=true),它确实会发送 409
假设我有以下类(class): class Mapping { @Id long id; String uuid; String object; @ManyTo
我遇到了识别哪个约束触发 DataIntegrityViolationException 的问题。我有两个独特的限制条件:用户名和电子邮件,但我没有找到答案。 我试图找出根本原因异常,但我收到了这条消
目前,我有两个不同的异常被 DataIntegrityViolationException 类捕获: 重复的键。 数据截断:数据对于列来说太长。 我的问题: 我遗漏了哪些案例? 如何区分不同的 Dat
以前的 update() 方法抛出 具有相同标识符值的不同对象已经与 session 关联 所以我将 dao 更改为 merge .现在它给出 org.springframework.dao.Data
项目背景 项目整体采用的是springboot+mybatis 方式。有一次做数据查询的时候。console突然报:DataIntegrityViolationException: Error att
我有 2 个表,Person 和 Phone,它们具有一对一的关系。 **Person** person_id name **Phone** phone_id person_id -- foreign
我有一个带有 Hibernate 的 REST Spring 启动应用程序。为简单起见,我们假设此工作流程: Controller 处理传入请求,调用服务方法 服务方式为@Transactional
我正在使用 org.springframework.data.jpa.repository.JpaRepository 保存方法来保存实体。我认为 save 方法来自 CrudRepository 接
我需要在我的 Spring 3.0 应用程序中显示自定义消息。我有一个带 Hibernate 的数据库,但有几个限制。我对如何以良好的方式处理 DataIntegrityViolationExcept
我需要创建实体,如果它已经存在,还可以选择更新它。如果我捕获DataIntegrityViolationException并尝试在Catch中进行处理,则会收到错误org.hibernate.Asse
我需要创建实体,如果它已经存在,还可以选择更新它。如果我捕获DataIntegrityViolationException并尝试在Catch中进行处理,则会收到错误org.hibernate.Asse
我需要创建实体,如果它已经存在,还可以选择更新它。如果我捕获DataIntegrityViolationException并尝试在Catch中进行处理,则会收到错误org.hibernate.Asse
我正在编写单元测试来使用存储过程测试数据库中失败的更新。我有一个更新表之一的存储过程。根据测试,我在存储过程中发送了不正确的数据(即违反表中完整性约束的数据)。所以我期待 SQLException 但
我正在为 ManyToMany 之间的关系构建示例:User(1) - ()AccessLevel() - (1)Role 我已经在 Java 中使用 hibernate 实现了 3 个类,如下所
正在处理一个 api 调用,该调用会更改数据库中的一些数据。我正在尝试从 api 提供有意义的消息,以防 JPA 层出现异常。在任何 sql 查询运行失败时,我都会从 JPA 收到 DataInteg
我是一名优秀的程序员,十分优秀!