我有一個 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;
}
我的用戶表:
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;
我試圖在@RestControllerAdvice 類中處理該例外:
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Object> handleConstraintViolationException(){
ExceptionDetails exceptionDetails = new ExceptionDetails(Errors.ERROR9.getMessage(),timestamp);
return new ResponseEntity<>(exceptionDetails,HttpStatus.FORBIDDEN);
}
但這可以解決所有約束問題(不是空違規、主鍵違規等),我只想為我的用戶名和電子郵件捕獲特定的約束違規
uj5u.com熱心網友回復:
如果您依賴于 Hibernate Validator,則不能執行自定義例外。
要解釋原因,請查看偵聽所有 Create/Update/Delete 事件的 BeanValidationEventHandler,它使用該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
);
}
}
}
https://github.com/hibernate/hibernate-orm/blob/main/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationEventListener.java
該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);
uj5u.com熱心網友回復:
在保存用戶之前,您可以檢查給定的用戶名是否已經存在。如果它已經存在,則不要保存用戶并要求輸入另一個用戶名,否則保存用戶。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/416162.html
標籤:
