SET方法的Hibernate字段长度验证

时间:2012-08-19 03:14:19

标签: hibernate

是否有一种简单的方法让Hibernate在每个属性的set()方法中验证字段长度约束?

我想阻止EVER中的字段包含无效值,而不是等待以后发生例外。

我有一个具有Username属性的类:

@Column(name = "username", length = 12)
public String getUsername()
{
    return this.username;
}

public void setUsername(String username)
{
    this.username = username;
}

我可以修改我的Hibernate模板,以这种方式创建set()方法:

@Column(name = "username", length = 12)
public String getUsername()
{
    return this.username;
}

public void setUsername(String username)
{
    Method m = ClassWithUsername.getDeclaredMethod("setUsername");
    javax.persistence.Column col = m.getAnnotation(javax.persistence.Column.class);
    int maxLen = col.length();

    // Validate the field length 
    if(username!=null && username.length() > maxLen)
        throw Exception("Username must be no more than " + maxLen + " characters.");

    this.username = username;
}

在我这样做之前,我想知道是否还有其他方法。

2 个答案:

答案 0 :(得分:1)

如何使用 Bean验证?参考http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/

Column注释的length属性用于指定:列长度。 (仅在使用字符串值列时适用。)

例如,您可以定义stock_code列的最大长度为5,但在生成的ddl中,stock_code列为varchar(10)。在这种情况下,您可以在保存实体中捕获ConstraintViolationException。

[如果发现实体无效,则ConstraintViolationException会传播约束违规列表,这会暴露一组ConstraintViolations。 在提交时发生违规时,此异常将包装在RollbackException中。否则返回ConstraintViolationException(例如,在调用flush()]

希望这符合您的要求。

在您的实体类

@Column(name = "stock_code", unique = true, nullable = false, length = 10)
@Size(max = 5)
public String getStockCode() {
    return this.stockCode;
}

public void setStockCode(String stockCode) {
    this.stockCode = stockCode;
}
在您的dao类中

try {
    session.beginTransaction();

    Stock stock = new Stock();

    stock.setStockCode("77777");
    stock.setStockName("PADINI");

    session.save(stock);
    session.getTransaction().commit();

} catch (ConstraintViolationException e) {
        session.getTransaction().rollback();
        System.out.println("Violate Constraint..");
    } catch (Exception e1) {
        session.getTransaction().rollback();
        System.out.println("Other Exception");
    } finally {
        session.close();
    }

答案 1 :(得分:0)

我不确定我的建议是否会是“更好”的做法,但你要求“其他方法”: - )

我的第一个选择是这样的:

public void setUsername(String username) {
    User user = user.clone();
    user.username = username;

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    Set<ConstraintViolation<Car>> constraintViolations = validator.validateProperty(user, "username");

    if (constraintViolations.size() == 0) {
        this.username = username;
    } else {
        throw new IllegalArgumentException("Invalid username");
    }
}

当然,您可以通过创建一个包含对验证程序的静态引用的帮助程序类来优化代码,这样您就不需要在每次调用setUsername时创建它。或者你甚至可以将整个逻辑封装到帮助器中,这样你就可以在你的setter上只传递这个(小心这种方法,因为验证器不应该调用setter来改变用户名值):

public void setUsername(String username) {
    MyValidatorHelper.validateOnSetter(this, username, "username");
    this.username = username;
}

请注意,在这种情况下,MyValidatorHelper会抛出异常,因此,只有在未抛出异常时才会执行第二行。

另一种选择是与CDI Interceptors一起玩。我没有测试过(就像我没有测试过前面的例子一样),但我认为你可以将上面的逻辑封装到CDI拦截器中,并用@AroundInvoke拦截它。这样,您甚至可以“忘记”从您的setter中调用验证器助手,让CDI为您调用它。这样做的缺点是你的实体必须是CDI托管的bean(无论如何它们可能都是),并且你默认为所有setter启用它,这可能是也可能不是一个好主意。