Полнотекстовый поиск с Java спецификацией / предикатом

Я пытаюсь сравнить строку с каждым столбцом в таблице. Есть ли более простой способ сделать это?

public class MySpec implements Specification<Tbl> {

    private Tbl searchCriteria;

    public MySpec(Tbl searchCriteria){
        this.searchCriteria = searchCriteria;
    }

    @Override
    public Predicate toPredicate(Root<Tbl> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

        List<Predicate> textPredicates = new ArrayList<>();
        String searchText = "%" + searchCriteria.getSearchText() + "%";

        textPredicates.add(cb.like(root.get("col1"), searchText));
        textPredicates.add(cb.like(root.get("col2"), searchText));
        textPredicates.add(cb.like(root.get("col3"), searchText));
        textPredicates.add(cb.like(root.get("col4"), searchText));
        textPredicates.add(cb.like(root.get("col5"), searchText));
        textPredicates.add(cb.like(root.get("col6"), searchText));
        textPredicates.add(cb.like(root.get("col7"), searchText));
        textPredicates.add(cb.like(root.get("col8"), searchText));
        textPredicates.add(cb.like(root.get("col9"), searchText));

        return query.where(cb.or(textPredicates.toArray(new Predicate[0])
                    .distinct(true).getRestriction();
    }
}

Я не хочу менять код спецификации каждый раз, когда добавляю новый столбец в таблицу. Другой вариант - отдельная таблица, которая будет содержать объединенную версию каждого столбца в строке. Такие как:

TBL
Col1 | Col2    | Col3    | Col4
-----------------------------------------
1    | "Name"  | "Value" | "Other Value" 


TBL_CACHE
Col1 | Col2
------------------------------
1    | "Name Value OtherValue" 

Но я не хочу создавать другую таблицу для каждой таблицы, для которой требуется полнотекстовый поиск, и я не хочу, чтобы обслуживание заполнения этих данных или создание задания SQL делали это автоматически.

2 ответа

Решение

Для спящего режима, чтобы получить список столбцов из сущности.

String[] columnNames = getSessionFactory().getClassMetadata(Entity.class).getPropertyNames();

Для JPA вы можете просмотреть список полей

for (Field field : entity.getClass().getDeclaredFields()) {
   Column column = field.getAnnotation(Column.class);
   if (column != null) {
      columnNames.add(column.name());
   }
}

И вы можете использовать тот же подход, если вы аннотируете методы.

Также проверьте это и это. Еще один способ получить метаданные.

Затем, используя список столбцов, просто добавьте ваши условия в цикл.

Вы можете получить size() из CriteriaBuilder и создать цикл. Предполагается, что столбец начинается с 1 и заканчивается числом столбцов.

int sz = cb.size();
for (int ii = 1; ii <= sz; ii++) {
    String textIndex = "" + ii;
    textPredicates.add(cb.like(root.get("col" + textIndex), searchText));
}
Другие вопросы по тегам