jOOQ:允许字符限制?

时间:2015-09-21 08:30:34

标签: java jooq

我正在考虑从Hibernate转移到jOOQ,但我找不到例如 如何在Hibernate中对String这样的模式约束:

@NotEmpty(message = "Firstname cannot be empty")
@Pattern(regexp = "^[a-zA-Z0-9_]*$", message = "First Name can only contain characters.")
private String firstname;

我如何在jOOQ中做到这一点?

2 个答案:

答案 0 :(得分:2)

“jOOQ方式”

进行此类验证的“jOOQ方式”是创建:

  • 数据库中的CHECK约束。
  • 数据库中的触发器。
  • 数据库中的域。

毕竟,如果要确保数据完整性,数据库就是这种约束和完整性检查所属的地方(可能除了功能等效的客户端验证之外)。想象一下批处理作业,Perl脚本,甚至绕过JSR-303验证的JDBC语句。你很快就会发现自己有腐败的数据。

如果您确实想要实现客户端验证,您仍然可以在DTO上使用JSR-303,例如,它与您的UI进行交互。但是,您必须在将数据传递给jOOQ进行存储(as artbristol explained)之前执行验证

使用Converter

但是,您可以通过在单个列和registering such Converter with the source code generator上声明Converter来使用您自己的自定义类型。

基本上,Converter是:

public interface Converter<T, U> extends Serializable {
    U from(T databaseObject);
    T to(U userObject);
    Class<T> fromType();
    Class<U> toType();
}

在您的情况下,您可以实现注释:

public class NotEmptyAlphaNumericValidator implements Converter<String, String> {

    // Validation
    public String to(String userObject) {
        assertNotEmpty(userObject);
        assertMatches(userObject, "^[a-zA-Z0-9_]*$");
        return userObject;
    }

    // Boilerplate
    public String from(String databaseObject) { return databaseObject; }
    public Class<String> fromType() { return String.class; }
    public Class<String> toType() { return String.class; }
}

请注意,这更像是一种解决方法,因为Converter并非针对此用例设计,即使它可以完美地实现它。

使用正式的客户端验证

还有一个待处理的功能请求#4543,可以为客户端验证添加更多支持。截至jOOQ 3.7,尚未实施。

答案 1 :(得分:1)

我建议您不要尝试以'hibernate / JPA'方式使用jOOQ。保留jOOQ生成的类,并手动映射到您自己的域类,您可以随意添加注释。然后,您可以在尝试保留它们之前调用JSR验证程序。

例如,jOOQ可能会生成以下类

public class BookRecord extends UpdatableRecordImpl<BookRecord> {

    private String firstname;

    public void setId(Integer value) { /* ... */ }

    public Integer getId() { /* ... */ }

}

您可以创建自己的域对象

public class Book {

    @NotEmpty(message = "Firstname cannot be empty")
    @Pattern(regexp = "^[a-zA-Z0-9_]*$", message = "First Name can only contain characters.")
    private String firstname;

    public void setId(Integer value) { /* ... */ }

    public Integer getId() { /* ... */ }

}

并在您的DAO图层中检索BookRecord后手动绘制地图

Book book = new Book();
book.setId(bookRecord.getId());
book.setFirstname(bookRecord.getFirstname());

这看起来相当繁琐(而且ORM试图让你免受这种乏味)但实际上它在很复杂的领域对象中可以很好地扩展,在我看来,在应用程序中找出数据流总是很容易。