2014-10-06 3 views
4

У меня есть контроллер MVC, который возвращает список контактов как JSON. На стороне интерфейса я использую плагин jquery datatables. На интерфейсе есть поле поиска для фильтрации списка сущностей.Технические характеристики и (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. LastName: Schmitz, ПгвЬЫате: Max, Company: (нуль)
  2. Lastname: Schmitz, Firstname: Moritz, Компания: XY
  3. Lastname: Muster, Имя: Max, Company: XY

    • Если я сейчас введи Schmitz в качестве ключа поиска, свяжитесь только 2, свяжитесь с 1 нет.
    • Если я ввести макс в качестве ключа поиска, единственный контакт 3 вернулся, контакт 1 не
    • только если ключ поиска является нуль/пустой, все контакты возвращаются

Я что-то пропустила?

вид касается Рицци

ответ

2

ответ сам;)

После исследования SQL-запросов я нашел решение. Я должен переписать свои спецификации. На связанных сущностях я должен добавить левый путь объединения, чтобы предотвратить создание строителей критериев автоматически с помощью кросс/внутренних соединений.

Внутреннее объединение только возвращенных объектов, у которых есть все поля. если какое-либо отношение сущности является нулевым, этот объект выпадает из списка результатов. Нормальное поведение внутреннего соединения.

так ...

Правильная спецификация должна быть.

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