【问题标题】:Is there a way to (locally) bypass or disable an AttributeConverter during a Criteria API call?在 Criteria API 调用期间,有没有办法(本地)绕过或禁用 AttributeConverter?
【发布时间】:2017-06-08 17:20:45
【问题描述】:

假设CreditcardNumb.class 带有一个检查信用卡号是否有效的构造函数。

然后我创建一个CreditcardNumbConverter.class 将信用卡号转换为数据库中的字符串:

public class CreditcardnumbConverter
      implements AttributeConverter<CreditcardNumb, String> {

    public String convertToDatabaseColumn(CreditcardNumb cn) {
        if (cn== null) return null;
        return cn.toString();
        }

    public CreditcardNumb convertToEntityAttribute(String cn) {
        if ((cn == null) || cn.trim().isEmpty()) return null;
        return new CreditcardNumb(cn);
        }
    }

这没问题,但现在我想使用 Hibernate 的 Criteria API(新的或旧的 API)来搜索以“123”开头的信用卡号:

CreditcardNumb cn = new CreditcardNumb("123");

createCriteria(Wallet.class)
      .add(Restrictions.ilike("creditcard", cn, MatchMode.START))
      .list();

但是,由于“123”不是有效的信用卡号,对象实例化失败。此外,这甚至不会编译,因为ilike 方法只接受Strings,而不接受CreditcardNumbs。

我的问题:

是否有任何方法(本地)绕过或禁用转换,以便我可以执行以下操作:

createCriteria(Wallet.class)
      .disable(CreditcardnumbConverter.class))
      .add(Restrictions.ilike("creditcard", "123", MatchMode.START))
      .list();

或者有没有其他方法可以使用 Criteria API(不使用 HQL)搜索以“123”开头的信用卡号。

【问题讨论】:

  • 没办法。重新考虑您的验证。我个人不喜欢在构造函数内部进行验证。编译器在做任何事情之前首先查看构造函数。这就是你出错的原因。
  • 你不喜欢构造函数中的验证?抱歉,但我不喜欢我的物品处于非法状态。我只想拥有合法的信用卡号码,但能够使用 Criteria API 进行搜索。

标签: java hibernate hibernate-criteria jpa-2.1


【解决方案1】:

您可以将信用卡列映射到String 类型的另一个属性中:

@Entity
public class Wallet {

  private CreditcardNumb creditcard;

  @Column(name = ..., insertable = false, updatable = false)
  private String creditcardStr;

  ...
}

关键点是将该列映射为既不可插入也不可更新,这样它的值就不会被持久化(否则Hibernate 将不知道是使用creditcard 还是creditcardStr 值来更新底层数据库列)。

现在您的查询可能如下所示:

createCriteria(Wallet.class)
  .add(Restrictions.ilike("creditcardStr", "123", MatchMode.START))
  .list();

【讨论】:

  • 哇,非常有创意的解决方案。问题是,然后您在类中有一个额外的字段,并添加了其他过度的复杂性,从而违背了 AttributeConverters 的目的。如果这是我想我会放弃使用 AttributeConverters 的唯一方法,或者在等待 Hibernate 团队解决此问题时将此答案用作临时解决方案:hibernate.atlassian.net/browse/HHH-11415
  • 如果在接下来的几天里没有其他更好的想法出现,我会接受这个答案。
  • 没错,它需要权衡取舍。就个人而言,我会将其映射为字符串而不使用属性转换器,并创建 CreditcardNumb getter 和 setter 来进行转换。当然,那么您必须注意在所有查询中使用字符串值作为参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-03
  • 2022-06-14
  • 2011-12-11
  • 1970-01-01
  • 2011-03-29
  • 1970-01-01
  • 2023-03-25
相关资源
最近更新 更多