【问题标题】:Criteria query returns []条件查询返回 []
【发布时间】:2019-06-11 22:02:25
【问题描述】:

当某些类字段可以为空时,我正在尝试使用标准存储库按类字段查找数据库记录。我正在检查字符串、整数,并且我正在使用 SQL 中的“like”来检查二进制字中的位。

我的实体类和元模型都在一个单独的包中:

-metapackage
    |
    +-MyEntity1.java
    |
    +-MyEntity1_.java

这是我的元模型:

    public static volatile SingularAttribute< MyEntity1, String> country;
    public static volatile SingularAttribute< MyEntity1, String> city;
    public static volatile SingularAttribute< MyEntity1, LocalDate> added;
    public static volatile SingularAttribute< MyEntity1, String> address;
    public static volatile SingularAttribute< MyEntity1, UserJPA> userJpa;
    public static volatile SingularAttribute< MyEntity1, String> title;
    public static volatile SingularAttribute< MyEntity1, Integer> size;
    public static volatile SingularAttribute< MyEntity1, String> sizeUnit;
    public static volatile SingularAttribute< MyEntity1, String> flags;// <<<<<<< this is a binary word of 8 bits
    public static volatile SingularAttribute< MyEntity1, Long> id;

这是我的标准代码:

    CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();
    
    CriteriaQuery< MyEntity1> cquery = builder.createQuery( MyEntity1.class);
    Root< MyEntity1> croot = cquery.from( MyEntity1.class);
    
    cquery.select(croot);
    Predicate pred = builder.isNotNull(croot.<String>get( MyEntity1_.flags));
    
    if(RestPreconditions.checkString(model.getCity())) {
        pred = builder.and(pred, builder.equal(croot.get( MyEntity1_.city), model.getCity()));
    }
    if(RestPreconditions.checkString(model.getCountry())) {
        pred = builder.and(pred, builder.equal(croot.get( MyEntity1_.country), model.getCountry()));
    }
    if(RestPreconditions.checkString(model.getAddress())) {
        pred = builder.and(pred, builder.equal(croot.get( MyEntity1_.address), model.getAddress()));
    }
    
    if(model.getMaxSize()!=null) {
        pred = builder.and(pred, builder.lessThanOrEqualTo(croot.get( MyEntity1_.size), model.convertSizeToM2(model.getMaxSize())));
    }
    if(model.getMinSize()!=null) {
        pred = builder.and(pred, builder.greaterThanOrEqualTo(croot.get( MyEntity1_.size), model.convertSizeToM2(model.getMinSize())));
    }
    // .flagsToBword() always returns something
    String bword = model.flagsToBWord();
    if(!bword.matches("0{8}")){
        pred = builder.and(pred, builder.like(croot.<String>get( MyEntity1_.flags), bword.replaceAll("0", "_")));
    }
    
    return entityManagerFactory.createEntityManager()
            .createQuery(cquery.where(pred))
            .getResultList();
        

问题是我不断收到一个空列表作为响应,即使我知道数据库中有匹配的对象。

我做错了什么?

编辑:

例如,如果我想在一个名为 London 的城市中查找记录,这就是我发送的对象:

{
    "city":"London"
}

我有一个与该城市连续的数据库记录。

另外,当我构造我的谓词时,这行代码:

谓词 pred = builder.isNotNull(croot.get(MyEntity1_.flags));

是否只是启动连词; flags 永远不会为空

【问题讨论】:

  • 您能否提供一个(最好是简单的)示例对象,该对象位于您的数据库中,应该在执行查询后返回?

标签: java hibernate hibernate-criteria


【解决方案1】:

你在正确的轨道上。您犯的唯一错误是每次都覆盖 pred 的值。

如果要链接 where 语句,则必须使用自身 + where 子句重新分配 pred 值。

Specification<MyEntity1> spec = Specification.where(
    (root, cb, cq) -> cb.isNotNull(root.get(MyEntity1_.flags)));

if (RestPreconditions.checkString(model.getCity())) 
    spec = spec.and(
        (root, cb, cq) -> cb.equal(root.get(MyEntity1_.city), model.getCity()))

return yourRepository.findAll(spec);

【讨论】:

    【解决方案2】:

    我终于明白了。

    当我打电话时:

    String bword = model.flagsToBWord();
    

    我会使用 java.util.Arrays

    将标志数组组合成一个字符串/二进制字

    这会产生一个像这样的字符串:

    "[0,0,1,0,0,1,0,1]"
    

    而不是我需要的常规二进制字:

    "00100101"
    

    当然没用;它一直在寻找 LIKE 值无效的记录。

    现在它可以正常工作了。

    【讨论】:

      猜你喜欢
      • 2019-06-24
      • 2017-06-15
      • 2015-02-26
      • 2013-08-10
      • 1970-01-01
      • 2013-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多