Hibernate Search

Пытаюсь реализовать поиск данных из таблицы patient. Суть в следующем: Есть 3 поля (Фамилия, Имя, Отчество). Поиск должен происходить по заполненным полям, но как это сделать пока не могу разобраться. Пока что сделал только для одного поля.

Класс Patient

@Entity
@Table(name = "patient")
@Indexed
public class Patient {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Field
    @Column(name = "fam")
    private String fam;

    @Field
    @Column(name = "im")
    private String im;

    @Field
    @Column(name = "ot")
    private String ot;
    
    @Column(name = "bdate")
    private Date bdate;
    @Column(name = "sex")
    private int sex;
    @Column(name = "phone")
    private String phone;
    @Column(name = "mail")
    private String mail;
    @Column(name = "snils")
    private String snils;
    @Column(name = "createdate")
    private Date createdate;

    public Patient() {

    }

    public Patient(String fam, String im, String ot, Date bdate, int sex, String phone, String mail, String snils, Date createdate) {
        this.fam = fam;
        this.im = im;
        this.ot = ot;
        this.bdate = bdate;
        this.sex = sex;
        this.phone = phone;
        this.mail = mail;
        this.snils = snils;
        this.createdate = createdate;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFam() {
        return fam;
    }

    public void setFam(String fam) {
        this.fam = fam;
    }

    public String getIm() {
        return im;
    }

    public void setIm(String im) {
        this.im = im;
    }

    public String getOt() {
        return ot;
    }

    public void setOt(String ot) {
        this.ot = ot;
    }

    public Date getBdate() {
        return bdate;
    }

    public void setBdate(Date bdate) {
        this.bdate = bdate;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getMail() {
        return mail;
    }

    public void setMail(String mail) {
        this.mail = mail;
    }

    public String getSnils() {
        return snils;
    }

    public void setSnils(String snils) {
        this.snils = snils;
    }

    public Date getCreatedate() {
        return createdate;
    }

    public void setCreatedate(Date createdate) {
        this.createdate = createdate;
    }
}

Метод для поиска

private void testSearch()  {

    Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();

    FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(session);
    try {
        fullTextEntityManager.createIndexer().startAndWait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Patient.class).get();

    Query query = queryBuilder
            .keyword()
            .wildcard()
            .onFields("fam")
            .matching(txtFieldFam.getText().trim() + "*")
            .createQuery();

    org.hibernate.search.jpa.FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(query, Patient.class);

    List<Patient> list = fullTextQuery.getResultList();

    for (Patient p: list
         ) {
        System.out.println(p.getFam() + " / " + p.getIm());
    }
}

Ответы (1 шт):

Автор решения: Иван Луполов

Если в вашем приложении используется Spring то первое что я рекомендую это использовать его стандартные репозитории, которые предоставляет Spring Data JPA, вместо способа создания запросов, который используете вы. Для ваших нужд вам необходимо будет создать интерфейс репозитория, например, PatientRepository который должен наследовать интерфейс JpaRepository<T, ID>, где T - это тип сохраняемой сущности, ID - класс, который представляет первичный ключ в сущности. JpaRepository уже будет иметь реализацию всех CRUD операций для вашей сущности. Теперь конкретно по вашему методу, у JpaRepository есть замечательный способ создания запросов из имен методов интерфейсов. Вот пример для вашего случая:

public interface PatientRepository extends JpaRepository<Patient, Integer> {
    List<Patient> findByFamOrImOrOtContaining(String searchString);
}

Метод аналогичен SQL-скрипту:

SELECT * FROM patient WHERE fam like '%searchString%' OR im like '%searchString%' OR ot like '%searchString%'

За более подробной информацией обращайтесь к документации.

Теперь относительно вашего кода. Не используйте примитивы для полей в сущностях Hibernate, поля должны допускать значение null если они не заданы, в случае примитива у вас там будет значение по умолчанию. Используйте нормальные имена переменных чтобы сразу было понятно для чего оно используется. В вашем случае, уж простите названия просто ужасны fam, im и ot. Они абсолютно не читабельны и не используйте транслит русских слов на латиницу, если возможно переменную назвать на английском: surName, firsName, patronymic. Русский транслит это уж очень крайний случай. Надеюсь мой ответ вам будет полезен.

PS. Также чтобы избавиться от кучи шаблонного кода советую вам почитать о проекте Lombok.

→ Ссылка