Búscalo aquí:

Uso de Clave Foránea en JPQL: Inner Join en JPA

Cuando trabajamos sobre Bases de Datos relacionales, es normal que tengamos que manejar claves foráneas, ya que estas nos facilitan enormemente el trabajo. En el caso de la imagen que muestro, un elemento de la tabla fid_trabajador usa como clave principal a la clave foránea que hereda de fid_persona_empresa. En este post se mostrará como puedo realizar una consulta JPQL (Java Persistence Query Language) que me permita acceder a los datos almacenados en fid_persona_empresa usando la clave foránea que fid_trabajador usa, de manera más precisa, usaremos un inner join en JPA para resolver este problema.

Al mapear las tablas de una Base de Datos usando algún ORM como TopLink Essentials o Hibernate (entre otros) notaremos que, en las clases creadas para el ejemplo de la imagen mostrada, se obtendra un mapeo similar a esto:

Para FidPersonaEmpresa:

public class FidPersonaEmpresa implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "nombres", length = 255)
private String nombres;
.
.
.
@OneToOne(cascade = CascadeType.ALL, mappedBy = "fidPersonaEmpresa")
private FidTrabajador fidTrabajador;
.
.
.
}
Para FidTrabajador:

public class FidTrabajador implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "fid_persona_empresa_id", nullable = false)
private Integer fidPersonaEmpresaId;
.
.
.
@JoinColumn(name="fid_persona_empresa_id",referencedColumnName = "id",
nullable = false, insertable = false, updatable = false)
@OneToOne(optional = false)
private FidPersonaEmpresa fidPersonaEmpresa;
.
.
.
}

El mapeo genera automaticamente variables para el acceso a ambas tablas, este acceso nos servirá como "puente" para poder hacer nuestra consulta usando un conocido INNER JOIN de una SQL tradicional pero con la sintaxis de JPQL.

De esta manera suponiendo que necesito recuperar todos los trabajadores cuyos nombres contengan la palabra "gonzales", me veré en la necesidad de buscar todos los elementos FidPersonaEmpresa que tengan por nombre "gonzales" y que a su vez se encuentren en FidTrabajador, para esto, la JPQL que hace uso de la clave foránea mediante el inner join sería:

String jpql = "SELECT t FROM FidTrabajador t JOIN
t.fidPersonaEmpresa p WHERE p.nombres like :nombres
and p.id = t.fidPersonaEmpresaId";

De manera similar, cuando quiero recuperar los datos personales de todos los trabajadores que tengan por nombre "gonzales" , la JPQL que hace uso de la clave foránea mediante el inner join sería:

SELECT p FROM FidPersonaEmpresa p JOIN p.fidTrabajador t  WHERE
p.nombres like :nombres and p.id = t.fidPersonaEmpresaId


De esa manera logramos acceder a las tablas que deseamos y hacer las operaciones necesarias para cumplir nuestra con nuestra consulta.

Espero les sea de utilidad, saludos.


Quieres leer más post como éste???...suscribete aquí!!!

6 comentarios:

  1. Me gustaria poder aclarar que uno de los fines del framework de persistencia de java JPA es utilizar el operador punto "." como acceso a los diferentes objetos foraneos que puedan estar relacionados y declarados dentro de la clase entidad.

    PE. en la consulta que realizaste
    String jpql = "SELECT t FROM FidTrabajador t JOINt.fidPersonaEmpresa p WHERE p.nombres like :nombresand p.id = t.fidPersonaEmpresaId";

    podriamos tambien utilizarla de la siguiente forma:

    String jpql = "SELECT t FROM FidTrabajador t WHERE p.nombres like :nombresand t.fidPersonaEmpresa.id = t.fidPersonaEmpresaId";

    La condicion para que el acceso atravez del operador punto "." se realizae correctamente es que tiene que tener redefinido los metodos equals y hascode para que JPA proceda a realizar el matching correspondiente.

    Saludos

    ResponderEliminar
  2. interesante george, pero dime podria usar el inner join de esta manera en JPA?:

    SELECT r.id, r.nombre, r.descripcion
    FROM fid_rol_trabajador_has_fid_trabajador h
    INNER JOIN fid_trabajador t ON h.fid_trabajador_fid_persona_empresa_id=t.fid_persona_empresa_id
    INNER JOIN fid_rol_trabajador r ON h.fid_rol_trabajador_id=r.id
    WHERE h.fid_trabajador_fid_persona_empresa_id=12

    Con lo cual el reporte que obtengo en la consola del HeidiSQL es perfecto.

    Estaria correcto usar asi el inner join en JPA?

    ResponderEliminar
  3. Buen aporte vimero, es una muy buena forma de evitar el uso de los inner join o en todo caso, de no usarlo cuando no es del todo necesario

    ResponderEliminar
  4. Micki, por lo que mencionas, la consulta se ejecuta correctamente, sin embargo me parece que esta un poco larga, hasta donde entiendo, se necesitan obtener los datos de los roles de un trabajador.

    Si es asi, para lograr eso, solamente necesitamos de la tabla de roles y de los roles de trabajadores, y por su puesto, el id de un trabajador como clave de busqueda. La query que propongo es esta:

    SELECT rt.id, rt.nombre, rt.descripcion
    FROM fid_rol_trabajador_has_fid_trabajador
    INNER JOIN fid_rol_trabajador rt
    WHERE fid_rol_trabajador_id = rt.id
    AND fid_trabajador_fid_persona_empresa_id=12

    Debería de dar los mismos resultados que la consulta que propones Micki.

    Saludos y gracias por leerme :D

    ResponderEliminar
  5. Listar los productos (idfab, idproducto, precio y descripción) para los cuales no se ha recibido ningún pedido menor al año 1999 e importe superior a 25000 pesos

    ResponderEliminar
  6. Hola George me podrias ayudar con esta consulta...
    @NamedQuery(name = "deleteAbsencesByPersonId", query = "SELECT A.tipoAusentismo FROM Ausentismo A " +
    "JOIN Contrato C ON A.IdContrato = C.IdContrato" +
    "JOIN Persona P ON C.IdPersona = P.IdPersona" +
    "WHERE A.tipoAusentismo = :idAusentismo AND P.IdPersona = :idPersona")

    en sql me corre perfecto, pero en jpa me sale un error en el ON

    Cordial saludo,

    ResponderEliminar

Bienvenido a jcGeorge's Blog!!!

Por favor deja tu comentario, consulta o sugerencia, procura mantener habilitado tu perfil de Blogger o deja un enlace a tu blog o web.

Gracias por leer este blog!!!

Related Posts Plugin for WordPress, Blogger...