Explicadores · en criollo
function() de JPQL
☕ Java · Hibernate · en criollo

function() de JPQL, explicado de una

El comodín para hablarle a la base en su propio idioma. Dale play y lo entendés de una vez.

1 · Hay dos idiomas

Vos escribís en un idioma, la base entiende otro

JPQL · idioma entidades
select i from ISO8583Message i where i.authCode ...

Hablás de campos Java: i.authCode, el atributo de la entidad.

🌐
Hibernate
traduce
SQL · idioma base
select * from h3_iso8583_message where auth_code ...

La base habla de columnas reales: auth_code en la tabla.

Vos escribís JPQL. Hibernate lo traduce a SQL antes de mandarlo a la base. Nunca ves el SQL — el traductor lo arma solo.

2 · Por qué es así

La gracia: el mismo JPQL anda en cualquier base

🐬 MySQL 🐘 Postgres 🔶 Oracle

JPQL es agnóstico de base: no lo atás a ninguna. Esa portabilidad es su superpoder.

El costo: para ser portable, solo conoce un diccionario chico de funciones — las que existen en todas las bases:

LENGTHSUBSTRINGLOWERCONCATTRIM
3 · El problema

Necesitás REGEXP_INSTR… y no está en el diccionario

Es una función de MariaDB para buscar con expresiones regulares. Potente, pero específica de esa base.

✅ LENGTH ✅ LOWER 🚫 REGEXP_INSTR

El traductor no la tiene en su diccionario → no la sabe decir → no la podés escribir en JPQL normal. Punto muerto.

4 · La salida de emergencia

JPA 2.1 agregó function()

function('nombre_funcion', arg1, arg2)
1️⃣ 'nombre' = la función de la base (entre comillas simples)
2️⃣ el resto = sus argumentos: campos i.authCode, literales, parámetros

En criollo: le decís al traductor "che, esta palabra pasala tal cual, no la traduzcas".

5 · Qué pasa por dentro

El paso a paso de la traducción

1
Vos escribís en JPQL:
function('regexp_instr', i.authCode, '^X[0-9]{5,6}$')
2
Hibernate resuelve el campo → columna:
i.authCode  →  auth_code
3
Emite el SQL, dejando la función tal cual:
regexp_instr(auth_code, '^X[0-9]{5,6}$')
4
MariaDB ejecuta la función de verdad. 🎯
→ devuelve un número

El campo authCode se tradujo a auth_code. La función regexp_instr pasó intacta. Eso hace function().

6 · Qué devuelve

REGEXP_INSTR devuelve la posición del match

La posición donde matchea el patrón (1, 2, 3…) o 0 si no matchea.

Por eso el filtro dice = 0: "no matchea el patrón de marca → conservá la fila".

X270762pos 1🚫 excluida
R0155540✅ conservada
7 · El detalle fino

"Pass-through": Hibernate la reenvía, no la inventa

function('regexp_instr', …) 🌐 Hibernate 5: "no la tengo registrada" la deja pasar tal cual

Si la función no está registrada en el dialect (nuestro caso), Hibernate 5 la reenvía confiando en que la base la tenga. No la valida, no la chequea — solo la deja pasar.

8 · El costo

Poderoso, pero canta — sabé cuándo

🔗 Atado a MariaDB

La función tiene que existir en esa base. Perdés la portabilidad que era la gracia de JPQL.

🕳️ Sin chequeo de tipos

Hibernate no valida los argumentos ni el retorno. Si te equivocás, revienta en runtime.

👀 "Canta" por nuevo

En un repo donde nunca se usó, salta a la vista aunque sea JPA estándar. Documentalo.

No es un hack ni un native query: es API oficial de JPA. Pero se paga con portabilidad y con que hay que explicarlo.

✨ En una frase

function() = el comodín oficial

Meter una función de la base adentro de un query JPQL, sin salir a native ni tocar el dialect.

🌐 lo traduce Hibernate 🎯 la función corre en la base
1/1