2014-10-06 49 views
4

我有一個MVC控制器,返回一個聯繫人列表爲JSON。在前端我使用jQuery數據表插件。前端有一個搜索欄來過濾實體列表。規範和(null)多對一關係

我的實體:

@Entity 
public class Contact implements Serializable { 

    protected final static Logger LOGGER    = LoggerFactory.getLogger(Contact.class); 

    private static final long  serialVersionUID = -3691953100225344828L; 

    @Id 
    @GeneratedValue(generator = "hibernate-uuid") 
    @Column(length = 36, unique = true) 
    private String     id; 

    @Version 
    @JsonIgnore 
    private int      version; 

    private String     firstname; 
    private String     lastname; 

    @ManyToOne 
    private Company     company; 

    ... GETTER/SETTER ... 
} 

@Entity 
public class Company implements Serializable { 

    protected final static Logger LOGGER    = LoggerFactory.getLogger(Company.class); 

    private static final long  serialVersionUID = -7863930456400256944L; 

    @Id 
    @GeneratedValue(generator = "hibernate-uuid") 
    @Column(length = 36, unique = true) 
    private String     id; 

    private String     companyName; 
    private String     companyName1; 
    private String     companyName2; 

    ... GETTER/SETTER ... 
} 

我使用服務器端處理的搜索領域,在服務器端我使用的規格。

public class ContactSpecifications { 

    public static Specification<Contact> contactFirstnameLike(final String needle) { 
     return new Specification<Contact>() { 

      @Override 
      public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       return cb.like(cb.lower(root.<String> get(Contact_.firstname)), needle != null ? needle.toLowerCase() : null); 
      } 
     }; 
    } 

    public static Specification<Contact> contactLastnameLike(final String needle) { 
     return new Specification<Contact>() { 

      @Override 
      public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       return cb.like(cb.lower(root.<String> get(Contact_.lastname)), needle != null ? needle.toLowerCase() : null); 
      } 
     }; 
    } 

    public static Specification<Contact> contactFullnameLike(final String needle) { 
     return new Specification<Contact>() { 

      @Override 
      public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       return cb.or(cb.like(cb.lower(root.<String> get(Contact_.lastname)), needle != null ? needle.toLowerCase() : null), cb.like(cb.lower(root.<String> get(Contact_.firstname)), needle != null ? needle.toLowerCase() : null)); 
      } 
     }; 
    } 

    public static Specification<Contact> contactCompanyCompanyNameLike(final String needle) { 
     return new Specification<Contact>() { 

      @Override 
      public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
       final Path<Company> company = root.<Company> get(Contact_.company); 
       return cb.like(cb.lower(company.<String> get(Company_.companyName)), needle != null ? needle.toLowerCase() : null); 
      } 
     }; 
    } 
} 

我的數據庫查詢

contactRepository.findAll(specifications, new PageRequest(0,100)); 

和規格

specifications = Specifications.where(ContactSpecifications.contactFullnameLike(needle)).or(ContactSpecifications.contactCompanyCompanyNameLike(needle)); 

針是從前端的搜索關鍵字,並與周邊%掩蓋(例如 「%ASDF%」)

我的問題是,如果聯繫人沒有公司,規格不按預期工作。

例如我有3個聯繫人:

  1. 姓氏:施米茨,名字:最大,公司:(空)
  2. 姓氏:施米茨,姓:Moritz的公司:XY
  3. 姓氏: Muster,Firstname:Max,公司:XY

    • 如果我現在輸入Schmitz作爲搜索鍵,只有聯繫人2返回,聯繫人1不是。
    • 如果我輸入的最大搜索鍵,只有接觸3回,接觸1不
    • 只有當搜索鍵是空/空,所有聯繫人返回

我錯過了什麼?

親切的問候 Rizzi的

回答

2

答案我自己;)

研究後,SQL查詢我找到了解決辦法。我必須重寫我的規格。在相關實體上,我必須添加左連接路徑以防止條件生成器自動使用交叉/內連接。

內部連接只返回實體,它具有所有字段設置。如果某個實體關係爲空,則此實體將從結果列表中刪除。正常的內部連接行爲。

so ...

正確的規格必須是這樣的。

public static Specification<Contact> contactCompanyCompanyNameLike(final String needle) { 
    return new Specification<Contact>() { 

     @Override 
     public Predicate toPredicate(Root<Contact> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 
      final Join<Contact,Company> company = root.join(Contact_.company, JoinType.LEFT); 
      return cb.like(cb.lower(company.<String> get(Company_.companyName)), needle != null ? needle.toLowerCase() : null); 
     } 
    }; 
} 

通過這個小的修改,它現在開始正常工作。

親切的問候Rizzi