darrachequesne / spring-data-jpa-datatables

Spring Data JPA extension to work with the great jQuery plugin DataTables (https://datatables.net/)
Apache License 2.0
447 stars 173 forks source link

Can't search in columns of type DATE #133

Closed carlosluisbm closed 1 year ago

carlosluisbm commented 3 years ago

Hello,

the DataTablesInput is trying to search the date column (fecha_alta) like varchar2 column.

(lower(cast(expediente0_.fechaalta as varchar2(255 char))) like ? escape ?) order by expediente0.fecha_alta desc ) where rownum <= ? 2021-09-03 03:48:19 TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [%2021-08-01 22:53:17%] 2021-09-03 03:48:19 TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [2] as [CHAR] - [~]

It is the same problem as the one in this post https://github.com/darrachequesne/spring-data-jpa-datatables/issues/59, but I cannot find a solid or developed solution in it. I don't understand how the Specifications work. Can someone please give me a complete solution to this problem?

Thanks.

darrachequesne commented 1 year ago

For future readers: I've added an example in the documentation there.

class DateSpecification implements Specification<MyEntity> {
  private final LocalDate value;

  DateSpecification(Column column) {
    String value = column.getSearch().getValue();
    column.setSearchable(false); // either here or in the table definition
    this.value = parseValue(value);
  }

  private LocalDate parseValue(String value) {
    if (hasText(value)) {
      try {
        return LocalDate.parse(value);
      } catch (DateTimeParseException e) {
        return null;
      }
    }
    return null;
  }

  @Override
  public Predicate toPredicate(Root<MyEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
    Expression<LocalDate> expr = root.get("myColumn").as(LocalDate.class);
    if (this.value != null) {
      return criteriaBuilder.equal(expr, this.value);
    } else {
      return criteriaBuilder.conjunction();
    }
  }
}

Usage:

@RestController
public class MyController {

  @RequestMapping(value = "/entities", method = RequestMethod.GET)
  public DataTablesOutput<MyEntity> list(@Valid DataTablesInput input) {
    return myRepository.findAll(input, new DateSpecification(input.getColumn("myField")));
  }
}

Sorry for the delay.