【问题标题】:Spring data jpa Constraint Violation exception is not happening on save保存时未发生 Spring data jpa Constraint Violation 异常
【发布时间】:2019-08-23 13:10:06
【问题描述】:

我有一个简单的 spring-boot 应用程序,我正在使用 spring-data-jpa。在保存具有相同 ID 的记录时,我希望它会引发异常,但它不会引发异常并执行代码。虽然记录没有保存在数据库中,但也没有抛出异常。我期望下面的代码将转到异常块,但它直接使用创建的状态代码返回响应实体。

@PostMapping(value = "/events")
    public Object addEvent(@RequestBody Event event,HttpServletRequest request,HttpServletResponse response) {
        try {
            eventRepository.save(event);
        }catch (ConstraintViolationException e) {
            e.printStackTrace();
        }catch (Exception e) {

            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }

        return new ResponseEntity<>(null, HttpStatus.CREATED);
    }

实体类:

package com.hackerrank.github.model;

import java.io.Serializable;
import java.sql.Timestamp;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="EVENT")
public class Event implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = -1327610423837025202L;
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="ID", unique = true)
    private Long id;
    @Column(name="TYPE")
    private String type;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="ACTOR_ID")
    private Actor actor;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="REPO_ID")
    private Repo repo;
    @Column(name="CREATED")
    private Timestamp createdAt;

    public Event() {
    }

    public Event(Long id, String type, Actor actor, Repo repo, Timestamp createdAt) {
        this.id = id;
        this.type = type;
        this.actor = actor;
        this.repo = repo;
        this.createdAt = createdAt;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Actor getActor() {
        return actor;
    }

    public void setActor(Actor actor) {
        this.actor = actor;
    }

    public Repo getRepo() {
        return repo;
    }

    public void setRepo(Repo repo) {
        this.repo = repo;
    }

    public Timestamp getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Timestamp createdAt) {
        this.createdAt = createdAt;
    }
}

【问题讨论】:

  • 它进入catch (ConstraintViolationException e) 内部而不是返回创建状态。我猜你想在 catch 块中的e.printStackTrace(); 之后添加另一个返回或抛出异常。
  • 为什么你认为这应该触发 Bean Validation? Bean Validation 验证 Bean Validation 注释。 Save 在内部执行 EntityManager.merge,这可以进行更新。
  • 其实不是进入(ConstraintViolationException e),而是直接进入最后一行,重新生成状态码。保存调用后,它没有保存记录,但也没有抛出异常。
  • 这是正确的行为
  • @SimonMartinelli 我不是在谈论 bean 验证,它应该在保存数据库级别验证没有发生的记录时抛出异常。

标签: hibernate spring-boot jpa spring-data-jpa


【解决方案1】:

您可以创建自定义验证注释以验证是否存在具有 id 的事件。

@Constraint(validatedBy = UniqueIdValidator.class)
@Retention(RUNTIME)
@Target({ FIELD, METHOD })
public @interface UniqueId {

    public String message() default "There is already event with this id!";

    public Class<?>[] groups() default {};

    public Class<? extends Payload>[] payload() default{};

}

@Component
public class UniqueIdValidator implements ConstraintValidator<UniqueId, Long>{

    @Autowired
    private EventService eventService;

    @Override
    public boolean isValid(Long value, ConstraintValidatorContext context) {
        return value != null && !eventService.isIdAlreadyInUse(value);
    }
}


@Service
public class EventService {

     @Autowired
     private EventRepository eventRepository;

     public boolean isIdAlreadyInUse(Long value) {
         return eventRepository.findById(value).isPresent();
     }

}

@Entity
@Table(name="EVENT")
public class Event implements Serializable {

    @Id  
    ...
    @UniqueId
    ...
    private Long id;


}

【讨论】:

    猜你喜欢
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2019-03-06
    相关资源
    最近更新 更多