La estructura de la tabla es la siguiente, la tabla pue`e quedar mas completa añadiendo o eliminando campos pero solo es para mostrar el uso de la llave compuesta
public class IdFactura implements Serializable{ private int folio; private String serie; public IdFactura(int folio, String serie) { super(); this.folio = folio; this.serie = serie; } }Cabe señalar que la clase IdFactura no esta escrita o no se añade alguna anotacion en particular, solo contiene las propiedades y constructores, ahora se genera la entidad Factura
import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.dracof.jpa.IdFactura; @Entity @Table (name="Factura") @IdClass (IdFactura.class) public class Factura implements Serializable { @Id @Column private int folio; @Id @Column private String serie; @Column private String emisor; @Column @Temporal (TemporalType.DATE) private Date fecha; //setters & getters }Aquí escribimos @IdClass (IdFactura.class) para indicar que haremos uso de la clase IdFactura para representar a la llave compuesta Se genera el cliente para realizar la inserción y la consulta
import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.dracof.jpa.entities.Factura; public class Cliente { public static void main(String[] args) { int folio = 1; String serie = "B"; Cliente cliente = new Cliente(); cliente.generaFactura(folio, serie); cliente.consultaFactura(folio, serie); } private void generaFactura(int folio, String serie) { System.out.println("Insertando Factura..."); EntityManagerFactory emf = null; EntityManager em = null; Factura factura = new Factura(); factura.setFolio(folio); factura.setSerie(serie); factura.setEmisor("Empresa X"); factura.setFecha(null); try { emf = Persistence.createEntityManagerFactory("unitPersistence"); em = emf.createEntityManager(); em.getTransaction().begin(); em.persist(factura); em.getTransaction().commit(); System.out.println("Factura insertada correctamente"); } catch (Exception e) { System.out.println("Existe un error al insertar factra"); em.getTransaction().rollback(); e.printStackTrace(); } finally { em.close(); emf.close(); } } private void consultaFactura(int folio, String serie) { System.out.println("Consultando Factura..."); EntityManagerFactory emf = null; EntityManager em = null; IdFactura idFactura = new IdFactura(folio, serie); try { emf = Persistence.createEntityManagerFactory("unitPersistence"); em = emf.createEntityManager(); Factura factura = em.find(Factura.class, idFactura); System.out.println("Folio: " + factura.getFolio()); System.out.println("Serie: " + factura.getSerie()); System.out.println("Emisor: " + factura.getEmisor()); System.out.println("Fecha: " + factura.getFecha()); } catch (Exception e) { e.printStackTrace(); } finally { em.close(); emf.close(); } } }Y vemos el resultado de ejecutar el cliente
Insertando Factura... Factura insertada correctamente Consultando Factura... Folio: 1 Serie: B Emisor: Empresa X Fecha: nullAhora se realizan algunos cambios para hacer la prueba con @EmbeddableId Se modifica la clase IdFactura de la siguiente forma
@Embeddable public class IdFactura implements Serializable { @Column private int folio; @Column private String serie; public IdFactura() { } public IdFactura(int folio, String serie) { super(); this.folio = folio; this.serie = serie; } public int getFolio() { return folio; } public String getSerie() { return serie; } //en este caso omiti los setters para convertir la clase en inmutable }Se nota que ahora la clase IdFactura se anota con @Embeddable y los campos folio y serie ahora contienen @Column, hay que recordar que como los campos serie y folio se llaman igual que los campos de la tabla podemos omitir el parámetro name de Column
import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.dracof.jpa.IdFactura; @Entity @Table (name="Factura") public class Factura implements Serializable { @EmbeddedId private IdFactura idFactura; @Column private String emisor; @Column @Temporal (TemporalType.DATE) private Date fecha; public IdFactura getIdFactura() { return idFactura; } public void setIdFactura(IdFactura idFactura) { this.idFactura = idFactura; } public String getEmisor() { return emisor; } public void setEmisor(String emisor) { this.emisor = emisor; } public Date getFecha() { return fecha; } public void setFecha(Date fecha) { this.fecha = fecha; } }Observamos que ahora para representar la llave compuesta dentro de Factura se usa @EmbeddedId y usamos IdFactura como una propiedad. El cliente se modifica ligeramente quedando
public class Cliente { public static void main(String[] args) { ... } private void generaFactura(int folio, String serie) { ... Factura factura = new Factura(); IdFactura idFactura = new IdFactura(folio, serie); factura.setIdFactura(idFactura); factura.setEmisor("Empresa X"); factura.setFecha(null); ... } private void consultaFactura(int folio, String serie) { // no sufre cambios } }Obteniendo el mismo resultado
Insertando Factura... Factura insertada correctamente Consultando Factura... Folio: 1 Serie: B Emisor: Empresa X Fecha: nullAhora realizamos el ejercicio usando solo XML, entonces borramos todas las anotaciones y la configuración del XML usando id-class y embeddable respectivamente
<entity-mappings> <entity class="org.dracof.jpa.entities.Factura"> <table name="Factura"/> <id-class class="org.dracof.jpa.IdFactura"/> <attributes> <id name="folio"> <column/> </id> <id name="serie"> <column/> </id> <basic name="emisor"> <column/> </basic> <basic name="fecha"> <temporal>DATE</temporal> <column/> </basic> </attributes> </entity> </entity-mappings>y
<entity-mappings> <embeddable class="org.dracof.jpa.IdFactura"> <attributes> <basic name="folio"> <column/> </basic> <basic name="serie"> <column/> </basic> </attributes> </embeddable> <entity class="org.dracof.jpa.entities.Factura"> <table name="Factura"/> <attributes> <embedded-id name="idFactura"/> <basic name="emisor"> <column/> </basic> <basic name="fecha"> <temporal>DATE</temporal> <column/> </basic> </attributes> </entity> </entity-mappings>La estructura del proyecto quedo como sigue