如何使用Spring Data JPA处理重复的字段值?

时间:2019-04-25 10:49:50

标签: java spring spring-boot spring-mvc spring-data-jpa

我使用Spring Data JPA为项目保存User对象。

我在对象中具有电子邮件唯一字段,因此我的模型如下:

@Entity
@Data
@Table(schema = "public", name = "user", uniqueConstraints = @UniqueConstraint(columnNames = "email"))
@NoArgsConstructor
@AllArgsConstructor
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column
    private String email;
}

UserRepository:

public interface UserRepository extends PagingAndSortingRepository<User, Integer>, JpaSpecificationExecutor<User> {

    List<User> findAllByAddressesContaining(Address address);

    User findByEmailIgnoreCase(String email);

    List<User> findAllByRoles_id(int id);
}

当我尝试使用userRepository.save(user)用DB中已经存在的电子邮件保存用户对象时 它可以工作,因此可以更新数据库中现有的用户对象。 我希望在发生唯一约束冲突而不是新对象更新的情况下引发异常,因此我将能够从我的spring MVC控制器发送409 CONFLICT状态。 如何以最有效和“正确”的方式实现这一目标?

2 个答案:

答案 0 :(得分:0)

您可以直接做一件事情,而不是直接保存!您可以创建将emailId作为参数并返回整数的自定义方法,例如... public int getCountForEmailId(String emailId);通过传递本机查询或HQL或JPQ,然后首先检查是否存在任何已发送电子邮件的ID,如果返回计数> 0,则可以返回该ID,并从控制器引发自定义异常。我希望您很清楚。

答案 1 :(得分:0)

在对象模型中此表达式的事实

uniqueConstraints = @UniqueConstraint (columnNames = "email")
使用

并不意味着在表中确实创建了该列的约束。

文档:  ...使用@UniqueConstraint批注指定对于主表或辅助表,将唯一约束包括在生成的DDL中。 ...

这并不意味着将在运行时检查某些内容。 确保此列约束确实存在于数据库表级别。 我猜你用弹簧吗? 您需要使用以下属性:

spring.jpa.hibernate.ddl-auto = none/create/update/validate <- select this

这将在上下文启动时创建/更新/检查架构。 验证-只需将您对实体(@Entity)的定义与数据库模式中描述的内容(类型,列,约束等)进行比较,例如,如果未向该模式中添加任何约束,则会出现错误。

在此列中添加数据约束后,每次收到约束违例异常时都会出现。