Reputation: 1635
I am trying to compare a String against every column in the table. Is there an easier way to do this?
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();
}
}
I don't want to have to change the specification code every time I add a new column to the table. Another option is a separate table that will hold a concatenated version of each column in a string. Such as:
TBL
Col1 | Col2 | Col3 | Col4
-----------------------------------------
1 | "Name" | "Value" | "Other Value"
TBL_CACHE
Col1 | Col2
------------------------------
1 | "Name Value OtherValue"
But I don't want to create another table for each table I want to full text search on and I don't want the maintenance of populating this data or creating a SQL job to do it automatically.
Upvotes: 0
Views: 1217
Reputation: 57421
For hibernate to retrieve list of columns from entity.
String[] columnNames = getSessionFactory().getClassMetadata(Entity.class).getPropertyNames();
For JPA you can go through the list of fields
for (Field field : entity.getClass().getDeclaredFields()) {
Column column = field.getAnnotation(Column.class);
if (column != null) {
columnNames.add(column.name());
}
}
And you can use the same approach if you annotate methods.
Also check this and this. One more way to get metadata.
Then using the columns list jusst add your conditions in a loop.
Upvotes: 1
Reputation: 175
You could get the size() from the CriteriaBuilder and create a loop. This assumes the column starts at 1 and ends at number of columns.
int sz = cb.size();
for (int ii = 1; ii <= sz; ii++) {
String textIndex = "" + ii;
textPredicates.add(cb.like(root.get("col" + textIndex), searchText));
}
Upvotes: 0