Necesito agregar un intervalo a una fecha (ambas columnas están en una tabla) usando los criterios MySQL y JPA. Sé que se requieren las siguientes funciones:
DATE_ADD de MySQL:
DATE_ADD(date,INTERVAL expr unit) function de CriteriaBuilder:
function(String name, Class<T> type, Expression<?>... args)También tengo una clase para crear expresiones de función:
public class SqlFunctionExpression extends BasicFunctionExpression<String> implements Serializable { public SqlFunctionExpression(CriteriaBuilderImpl criteriaBuilder, Class<String> javaType, String functionName) { super(criteriaBuilder, javaType, functionName); } @Override public String render(RenderingContext renderingContext) { return getFunctionName(); } } que se puede usar como new SqlFunctionExpression(null, String.class, "MINUTE") para crear una unidad de minutos.
Sin embargo, ¿cómo creo la expresión INTERVAL expr unit donde expr es una columna de tabla?
o podemos agregar la fecha directamente desde el lado de Java y enviarlo como argumento para comparar, así
criteriaBuilder.equal(exceptionsJoinOnRoot.get(MyModelClass_.tartDate), Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).plus(Period.ofDays(1)) .toInstant()))si esto no funciona, podemos usar la función mysql ADDDATE
criteriaBuilder.equal(exceptionsJoinOnRoot.get(MyModelClass_.tartDate), criteriaBuilder.function("ADDDATE",Date.class,criteraBuilder.currentTimestamp(),criteriaBuilder.literal(1)))función de registro
public class CommonMySQLDialect extends MySQL57Dialect { public CommonMySQLDialect() { super(); registerFunction("date_add", new SQLFunctionTemplate(TimestampType.INSTANCE, "date_add(?1, INTERVAL ?2 ?3)")); } }Agregar a la configuración de hibernación
<property name="hibernate.dialect">yourpackage.CommonMySQLDialect</property>Listo para usar
Expression<String> unit = new SqlFunctionExpression(null, String.class, "MINUTE"); Expression<Integer> num = cb.literal(10); Expression<Date> newDate = cb.function("date_add", Date.class, cb.currentTimestamp(), num, unit);Para pasar tokens sin procesar como INTERVAL 1 YEAR a MySQL, puede usar mi clase OpaqueLiteralExpression que se describe aquí: https://stackoverflow.com/a/69998155/263801