sta*_*tan 5 java postgresql spring hibernate exception
我有一个 Spring 应用程序,并向我的用户实体添加了用户名和电子邮件的唯一约束。因此,用户无法使用相同的用户名或电子邮件创建多个帐户。当有人使用已存在的用户名创建新用户时,我的应用程序会抛出 ConstraintViolationException
我的异常详细信息:
org.postgresql.util.PSQLException:错误:重复的键值违反唯一约束“ukdfui7gxngrgwn9ewee3ogtgym”详细信息:键(用户名)=(dev123)已存在。
我的用户实体:
@Table(name = "usr", uniqueConstraints={
@UniqueConstraint(columnNames ={"username"}),
@UniqueConstraint(columnNames={"email"})})
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="usr_seq")
@SequenceGenerator(name = "usr_seq", sequenceName = "usr_seq", initialValue = 1, allocationSize=1)
@Column(name="id")
private Long id;
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "role")
private Role role;
@Column(name = "email")
private String email;
@Column(name = "status")
private Status status;
// @OneToMany(mappedBy = "author")
// private List<Message> messages;
// @OneToMany(mappedBy = "author")
// private List<Comment> comments;
@OneToOne
@JoinColumn(name = "gender_id")
private Gender gender;
@OneToOne
@JoinColumn(name = "address_id")
private Address address;
@ManyToMany
@JoinTable(
name = "user_subscriptions",
joinColumns = @JoinColumn(name = "channel_id") ,
inverseJoinColumns = @JoinColumn(name = "subscriber_id"))
private Set<User> subscribers;
@ManyToMany
@JoinTable(
name = "user_subscriptions",
joinColumns = @JoinColumn(name = "subscriber_id") ,
inverseJoinColumns = @JoinColumn(name = "channel_id"))
private Set<User> subscriptions;
@OneToOne
@JoinColumn(name = "file_id")
private FileEntity fileEntity;
}
Run Code Online (Sandbox Code Playgroud)
我的用户表:
create table usr
(
id bigint not null
constraint usr_pkey
primary key,
email varchar(255)
constraint ukg9l96r670qkidthshajdtxrqf
unique,
first_name varchar(255),
last_name varchar(255),
password varchar(255),
role integer,
status integer,
username varchar(255)
constraint ukdfui7gxngrgwn9ewee3ogtgym
unique,
address_id integer
constraint fkilsqnqkb7dlk6s5gqedb6lk3r
references address,
file_id bigint
constraint fkabswqn807logqymtak5wfktfr
references file,
gender_id integer
constraint fkp89wdnbeu22hjl41g38rk8a1q
references gender
);
alter table usr
owner to postgres;
Run Code Online (Sandbox Code Playgroud)
我尝试在 @RestControllerAdvice 类中处理该异常:
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Object> handleConstraintViolationException(){
ExceptionDetails exceptionDetails = new ExceptionDetails(Errors.ERROR9.getMessage(),timestamp);
return new ResponseEntity<>(exceptionDetails,HttpStatus.FORBIDDEN);
}
Run Code Online (Sandbox Code Playgroud)
但这捕获了约束的所有问题(不是空违规、主键违规等),我只想捕获我的用户名和电子邮件的特定约束违规
如果您依赖 Hibernate Validator,则无法执行自定义异常。
要解释原因,请查看 BeanValidationEventHandler,它侦听所有 Create/Update/Delete 事件,它使用该Validator validate方法并仅处理ConstraintViolation:
private <T> void validate(T object, EntityMode mode, EntityPersister persister,
SessionFactoryImplementor sessionFactory, GroupsPerOperation.Operation operation) {
if ( object == null || mode != EntityMode.POJO ) {
return;
}
TraversableResolver tr = new HibernateTraversableResolver(
persister, associationsPerEntityPersister, sessionFactory
);
Validator validator = factory.usingContext()
.traversableResolver( tr )
.getValidator();
final Class<?>[] groups = groupsPerOperation.get( operation );
if ( groups.length > 0 ) {
final Set<ConstraintViolation<T>> constraintViolations = validator.validate( object, groups );
if ( constraintViolations.size() > 0 ) {
Set<ConstraintViolation<?>> propagatedViolations =
new HashSet<ConstraintViolation<?>>( constraintViolations.size() );
Set<String> classNames = new HashSet<String>();
for ( ConstraintViolation<?> violation : constraintViolations ) {
LOG.trace( violation );
propagatedViolations.add( violation );
classNames.add( violation.getLeafBean().getClass().getName() );
}
StringBuilder builder = new StringBuilder();
builder.append( "Validation failed for classes " );
builder.append( classNames );
builder.append( " during " );
builder.append( operation.getName() );
builder.append( " time for groups " );
builder.append( toString( groups ) );
builder.append( "\nList of constraint violations:[\n" );
for (ConstraintViolation<?> violation : constraintViolations) {
builder.append( "\t" ).append( violation.toString() ).append("\n");
}
builder.append( "]" );
throw new ConstraintViolationException(
builder.toString(), propagatedViolations
);
}
}
}
Run Code Online (Sandbox Code Playgroud)
该Validator接口还处理 ConstraintViolation:
public interface Validator {
/**
* Validates all constraints on {@code object}.
*
* @param object object to validate
* @param groups the group or list of groups targeted for validation (defaults to
* {@link Default})
* @return constraint violations or an empty set if none
* @throws IllegalArgumentException if object is {@code null}
* or if {@code null} is passed to the varargs groups
* @throws ValidationException if a non recoverable error happens
* during the validation process
*/
<T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
731 次 |
| 最近记录: |