验证检查唯一复合键

时间:2016-04-14 14:05:44

标签: spring hibernate spring-mvc bean-validation hibernate-validator

我有一个实体类的3个字段,我不希望它们是唯一的,但我希望它们可以用作一个必须本身唯一的密钥的复合字段。 我的课程POJO:

    @Entity
        @Table(name="EMPLOYEE")
        public class Employee {

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

            @Size(min=3, max=50)
            @Column(name = "NAME", nullable = false)
            private String name;

            @Size(min=3, max=50)
            @Column(name = "A", nullable = false)
            private String a;
            @Size(min=3, max=50)
            @Column(name = "B", nullable = false)
            private String b;
            @Size(min=3, max=50)
            @Column(name = "C", nullable = false)
            private String c;

            @NotNull
            @DateTimeFormat(pattern="dd/MM/yyyy") 
            @Column(name = "JOINING_DATE", nullable = false)
            @Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
            private LocalDate joiningDate;

            @NotNull
            @Digits(integer=8, fraction=2)
            @Column(name = "SALARY", nullable = false)
            private BigDecimal salary;

            @NotEmpty
            @Column(name = "SSN", unique=true, nullable = false)
            private String ssn;
    }

我正在处理表单提交,通过 JSR303注释验证用户输入。如果验证失败,则显示默认错误消息。我配置了 ResourceBundleMessageSource

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.fussa.fyby")
public class AppConfig {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages");
        return messageSource;
    }
}

/src/main/resources/messages.properties

Size.employee.name=between {2} and {1} characters long
NotNull.employee.joiningDate=can not be blank
NotNull.employee.salary=are u working for free !
Digits.employee.salary=Only numeric data with max 8 digits and with max 2 precision is allowed
NotEmpty.employee.ssn=can not be blank
typeMismatch=Invalid format
non.unique.ssn=SSN {0} already exist.

我找到了创建唯一密钥的解决方案:

@Table( name = "EMPLOYEE",
        uniqueConstraints = { @UniqueConstraint( columnNames = { "A", "B", "C" } ) } )

我的问题是,如果违反了uniqueconstraint,我如何使用 messages.properties 显示消息?

更新1

@Service("employeeService")
@Transactional
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeDao dao;

    //....

    public void saveEmployee(Employee employee) {
        dao.saveEmployee(employee);
    }

}

感谢您的任何建议..

2 个答案:

答案 0 :(得分:1)

如果要使用Bean Validation,则需要编写一个自定义约束,该约束验证三列是唯一的。请注意,这有一个问题。除非您锁定整个表,否则总会遇到这样的问题,即当您的约束验证程序检查唯一性时,另一个并发事务会更改数据库。另请参阅此Stackoverflow问题 - Unique constraint with JPA and Bean Validation。 Validator Wiki上有blog post关于Unique约束的样子,但它附带了刚才提到的警告。验证可能会通过,但是在插入期间,由于另一个事务在此期间修改了数据这一事实,您仍然可能会获得数据库级异常(因此您的代码也需要处理此情况)。使用Bean Validation 1.1,您可以直接注入SessionFactory

答案 1 :(得分:0)

我设法为一个字段创建了一个唯一的约束验证,完成以下步骤:

1-创建约束注释。 2-create约束验证器。 3 - 错误消息。 4 - 如何使用约束。

我在这里发布了解决方案的代码:Link ..