7 Proyecto Students con JPA¶
Introducción¶
Una vez conocido todos los conceptos y relaciones pertinentes, es momento de aplicar dichos conocimientos a nuestro proyecto Bookstore, que en la última versión había sido añadida el patrón de diseño Repository. En esta versión, es indiferente el tipo de patrón de diseño a usar, ya que para lo que nos compete el funcionamiento es bastante similar.
Configuración de dependencias¶
Si usamos un gestor de dependencias como Maven o Gradle, es necesario importar los artifacts, tanto de Hibernate como de JPA, así como el conector de la base de datos:
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.2.7.Final</version>
</dependency>
</dependencies>
Configuración de las ORM¶
Podemos usar nuestras clases POJOs con anotaciones o haciendo uso del XML:
<entity-mappings xmlns="https://jakarta.ee/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence/orm https://jakarta.ee/xml/ns/persistence/orm/orm_3_0.xsd"
version="3.0">
<entity class="com.irudev.data.entity.Student" >
<table name="student"/>
<attributes>
<id name="id">
<column name="id"/>
<generated-value strategy="IDENTITY"/>
</id>
<basic name="name">
<column name="name"/>
</basic>
<basic name="age">
<column name="age"/>
</basic>
</attributes>
</entity>
</entity-mappings>
@Entity
public class Student implements Comparable<Student>{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private int age;
public Student(){}
public Student(Integer id, String name, int age){
this.id = id;
this.name = name;
this.age = age;
}
// ...
}
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd"
version="2.2">
<entity class="com.irudev.data.entity.Course">
<table name="course"/>
<attributes>
<id name="id">
<column name="id"/>
<generated-value strategy="IDENTITY"/>
</id>
<basic name="name">
<column name="name"/>
</basic>
<basic name="credits">
<column name="credits"/>
</basic>
</attributes>
</entity>
</entity-mappings>
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd"
version="2.2">
<entity class="com.irudev.data.entity.Inscription">
<table name="inscription"/>
<attributes>
<id name="id">
<column name="id"/>
<generated-value strategy="IDENTITY"/>
</id>
<many-to-one name="student" fetch="EAGER">
<join-column name="idStudent"/>
</many-to-one>
<many-to-one name="course" fetch="EAGER">
<join-column name="idCourse"/>
</many-to-one>
</attributes>
</entity>
</entity-mappings>
@Entity
public class Inscription implements Comparable<Inscription>{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "idStudent")
private Student student;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "idCourse")
private Course course;
public Inscription(){}
// ...
}
Archivo de configuración¶
Debemos de crear el archivo de configuración persistence xml
<!-- persistence.xml -->
<persistence version="3.0" xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
<persistence-unit name="myPersistenceUnit">
<!-- Asignación de Hibernate como JPA Provider -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- Mapeo ORM -->
<mapping-file>META-INF/orm/Student.xml</mapping-file>
<mapping-file>META-INF/orm/Course.xml</mapping-file>
<mapping-file>META-INF/orm/Inscription.xml</mapping-file>
<!-- Configuración de las propiedades -->
<properties>
<!-- Configuración de la fuente de datos para MySQL -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/students?useSSL=false&serverTimezone=UTC"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value=""/>
<!-- Configuración de Hibernate -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
Importante
En el fichero persistence.xml será obligatorio indicar el mapping-file
si se usa archivos xml para la ORM en lugar de anotaciones
Modelos¶
Al no utilizar los métodos ni crear las conexiones, los modelos deben cambiar:
public class JDBCStudentRepository implements StudentRepository {
private final EntityManager manager;
public JDBCStudentRepository(EntityManager manager){
this.manager = manager;
}
@Override
public Student getById(Integer id) {
return manager.find(Student.class, id);
}
@Override
public List<Student> getAll() {
return manager.createQuery("select s from Student s", Student.class).getResultList();
}
@Override
public boolean save(Student student) {
try{
manager.getTransaction().begin();
manager.persist(student);
manager.getTransaction().commit();
return true;
}catch (Exception e){
return false;
}
}
@Override
public boolean update(Student student) {
try{
manager.getTransaction().begin();
manager.merge(student);
manager.getTransaction().commit();
return true;
}catch (Exception e){
return false;
}
}
@Override
public boolean delete(Student student) {
try{
manager.getTransaction().begin();
manager.remove(student);
manager.getTransaction().commit();
return true;
}catch (Exception e){
return false;
}
}
}
public class JDBCCourseRepository implements CourseRepository {
private final EntityManager manager;
public JDBCCourseRepository(EntityManager manager) {
this.manager = manager;
}
@Override
public Course getById(Integer id) {
return manager.find(Course.class, id);
}
@Override
public List<Course> getAll() {
return manager.createQuery("select c from Course c", Course.class).getResultList();
}
@Override
public boolean save(Course course) {
try{
manager.getTransaction().begin();
manager.persist(course);
manager.getTransaction().commit();
return true;
}catch (Exception e){
return false;
}
}
@Override
public boolean update(Course course) {
try{
manager.getTransaction().begin();
manager.merge(course);
manager.getTransaction().commit();
return true;
}catch (Exception e){
return false;
}
}
@Override
public boolean delete(Course course) {
try{
manager.getTransaction().begin();
manager.remove(course);
manager.getTransaction().commit();
return true;
}catch (Exception e){
return false;
}
}
}
public class JDBCInscriptionRepository implements InscriptionRepository {
private final EntityManager manager;
public JDBCInscriptionRepository(EntityManager manager) {
this.manager = manager;
}
@Override
public Inscription getById(Integer id) {
return manager.find(Inscription.class, id);
}
@Override
public List<Inscription> getAll() {
return manager.createQuery("select i from Inscription i", Inscription.class).getResultList();
}
@Override
public boolean save(Inscription inscription) {
try{
manager.getTransaction().begin();
manager.persist(inscription);
manager.getTransaction().commit();
return true;
}catch (Exception e){
return false;
}
}
@Override
public boolean delete(Inscription inscription) {
try{
manager.getTransaction().begin();
manager.remove(inscription);
manager.getTransaction().commit();
return true;
}catch (Exception e){
return false;
}
}
}