Ya estoy inscrito ¿Todavía no tienes acceso? Nuestros Planes
Ya estoy inscrito ¿Todavía no tienes acceso? Nuestros Planes
Solucionado (ver solución)
Solucionado
(ver solución)
1
respuesta

JPQL no admite rand() ni limit;

Gracias por compartir tu clase MedicoRepository. El problema principal está en este fragmento del @Query que estás usando con JPQL:

java Copiar código @Query(""" select m from Medico m where m.activo = true and m.especialidad = :especialidad and m.id not in( select c.medico.id from Consulta c where c.fecha = :fecha ) order by rand() limit 1 """) Medico seleccionarMedicoConEspecialidadEnFecha(Especialidad especialidad, LocalDateTime fecha); Problemas: limit 1 y order by rand() no son válidos en JPQL:

JPQL (Java Persistence Query Language) no soporta limit ni order by rand() porque es un lenguaje abstracto independiente del motor de base de datos.

Estas cláusulas son propias de SQL nativo (por ejemplo, en MySQL sí están permitidas).

Soluciones: Opción 1: Usa Pageable en lugar de limit (recomendado para JPQL) Spring Data JPA permite pasar un Pageable al método, y así puedes limitar a un solo resultado sin usar limit ni rand().

java Copiar código @Query(""" select m from Medico m where m.activo = true and m.especialidad = :especialidad and m.id not in( select c.medico.id from Consulta c where c.fecha = :fecha ) """) List seleccionarMedicosDisponibles(Especialidad especialidad, LocalDateTime fecha, Pageable pageable); Y luego en tu servicio, haces algo como:

java Copiar código var medicos = medicoRepository.seleccionarMedicosDisponibles(especialidad, fecha, PageRequest.of(0, 1)); if (medicos.isEmpty()) return null; return medicos.get(0); Opción 2: Usa SQL nativo (solo si necesitas rand()) java Copiar código @Query(value = """ SELECT * FROM medicos m WHERE m.activo = true AND m.especialidad = :especialidad AND m.id NOT IN ( SELECT c.medico_id FROM consultas c WHERE c.fecha = :fecha ) ORDER BY RAND() LIMIT 1 """, nativeQuery = true) Medico seleccionarMedicoConEspecialidadEnFecha(Especialidad especialidad,

1 respuesta
solución!

Hola Pedro, espero que estés bien

Entiendo tu frustración con las limitaciones de JPQL al no soportar limit y order by rand(). Aquí te dejo algunas soluciones que podrían ayudarte a resolver este problema:

  1. Usar Pageable en lugar de limit: Como mencionaste, Spring Data JPA permite utilizar Pageable para limitar el número de resultados. Puedes ajustar tu consulta para devolver una lista de médicos y luego seleccionar el primero de la lista. Aquí tienes un ejemplo de cómo hacerlo:

    @Query("""
        select m from Medico m
        where
        m.activo = true
        and
        m.especialidad = :especialidad
        and
        m.id not in(
            select c.medico.id from Consulta c
            where c.fecha = :fecha
        )
    """)
    List<Medico> seleccionarMedicosDisponibles(Especialidad especialidad, LocalDateTime fecha, Pageable pageable);
    

    Y en tu servicio:

    var medicos = medicoRepository.seleccionarMedicosDisponibles(especialidad, fecha, PageRequest.of(0, 1));
    if (medicos.isEmpty()) return null;
    return medicos.get(0);
    
  2. Usar SQL nativo para order by rand(): Si necesitas seleccionar un médico aleatoriamente, puedes optar por usar una consulta SQL nativa. Aquí tienes un ejemplo:

    @Query(value = """
        SELECT * FROM medicos m
        WHERE m.activo = true
        AND m.especialidad = :especialidad
        AND m.id NOT IN (
            SELECT c.medico_id FROM consultas c
            WHERE c.fecha = :fecha
        )
        ORDER BY RAND()
        LIMIT 1
    """, nativeQuery = true)
    Medico seleccionarMedicoConEspecialidadEnFecha(Especialidad especialidad, LocalDateTime fecha);
    

Espero que estas opciones te sean útiles para resolver el problema. Recuerda que al usar SQL nativo, pierdes la independencia del motor de base de datos, pero puede ser necesario si necesitas funcionalidades específicas como order by rand().

Espero haber ayudado y buenos estudios!