JPA example from zero to hero!

If you need further information about the topic, follow this link.

Here's how you can make the database schema.

Build the model with the VO classes

      
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="fabricantes")

public class FabricanteVO {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int idfabricante;
	@Column (length=20)
	private String nombre;
	@Column (length=20)
	private String pais;
	private int contador;
	@OneToMany(mappedBy="fabricante")
	private List<VehiculoVO> vehiculos;
	
	public FabricanteVO(int idfabricante, String nombre, String pais, int contador, List<VehiculoVO> vehiculos) {
		super();
		this.idfabricante = idfabricante;
		this.nombre = nombre;
		this.pais = pais;
		this.contador = contador;
		this.vehiculos = vehiculos;
	}

	public FabricanteVO(String nombre, String pais, int contador, List<VehiculoVO> vehiculos) {
		super();
		this.nombre = nombre;
		this.pais = pais;
		this.contador = contador;
		this.vehiculos = vehiculos;
	}

	public FabricanteVO() {
		super();
	}

	public int getIdfabricante() {
		return idfabricante;
	}

	public void setIdfabricante(int idfabricante) {
		this.idfabricante = idfabricante;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public String getPais() {
		return pais;
	}

	public void setPais(String pais) {
		this.pais = pais;
	}

	public int getContador() {
		return contador;
	}

	public void setContador(int contador) {
		this.contador = contador;
	}

	public List<VehiculoVO> getVehiculos() {
		return vehiculos;
	}

	public void setVehiculos(List<VehiculoVO> vehiculos) {
		this.vehiculos = vehiculos;
	}

	@Override
	public int hashCode() {
		return Objects.hash(idfabricante, nombre, pais);
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		FabricanteVO other = (FabricanteVO) obj;
		return idfabricante == other.idfabricante && Objects.equals(nombre, other.nombre)
				&& Objects.equals(pais, other.pais);
	}

	@Override
	public String toString() {
		return "FabricanteVO [idfabricante=" + idfabricante + ", nombre=" + nombre + ", pais=" 
		+ pais + ", contador="
				+ contador + "]";
	}
      
      
        
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="vehiculos")

public class VehiculoVO {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int idvehiculo;
	@Column (length=20, unique=true )
	private String modelo;
	private LocalDate fechaCreacion;
	@ManyToOne
	private FabricanteVO fabricante;
	
	public VehiculoVO(int idvehiculo, String modelo, LocalDate fechaCreacion, FabricanteVO fabricante) {
		super();
		this.idvehiculo = idvehiculo;
		this.modelo = modelo;
		this.fechaCreacion = fechaCreacion;
		this.fabricante = fabricante;
	}

	public VehiculoVO(String modelo, LocalDate fechaCreacion, FabricanteVO fabricante) {
		super();
		this.modelo = modelo;
		this.fechaCreacion = fechaCreacion;
		this.fabricante = fabricante;
	}

	public VehiculoVO() {
		super();
	}

	public int getIdvehiculo() {
		return idvehiculo;
	}

	public void setIdvehiculo(int idvehiculo) {
		this.idvehiculo = idvehiculo;
	}

	public String getModelo() {
		return modelo;
	}

	public void setModelo(String modelo) {
		this.modelo = modelo;
	}

	public LocalDate getFechaCreacion() {
		return fechaCreacion;
	}

	public void setFechaCreacion(LocalDate fechaCreacion) {
		this.fechaCreacion = fechaCreacion;
	}

	public FabricanteVO getFabricante() {
		return fabricante;
	}

	public void setFabricante(FabricanteVO fabricante) {
		this.fabricante = fabricante;
	}

	@Override
	public int hashCode() {
		return Objects.hash(fabricante, fechaCreacion, idvehiculo, modelo);
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		VehiculoVO other = (VehiculoVO) obj;
		return Objects.equals(fabricante, other.fabricante) && Objects.equals(fechaCreacion, 
		other.fechaCreacion)
				&& idvehiculo == other.idvehiculo && Objects.equals(modelo, other.modelo);
	}

	@Override
	public String toString() {
		return "VehiculoVO [idvehiculo=" + idvehiculo + ", modelo=" + modelo + ", fechaCreacion=" 
		+ fechaCreacion
				+ ", fabricante=" + fabricante + "]";
	}
	
	
	
		
}

      
      

Build the DAO implementation

      
      
public interface FabricanteDAO {
	
	Optional findByName(String nombre);
	

}

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import org.hibernate.exception.ConstraintViolationException;

import com.dawes.dao.FabricanteDAO;
import com.dawes.modelo.FabricanteVO;

public class FabricanteDAOImpl implements FabricanteDAO {
	
	private EntityManager manejadorEntidad;

	public FabricanteDAOImpl(EntityManager manejadorEntidad) {
		this.manejadorEntidad = manejadorEntidad;
	}

	@Override
	public Optional<FabricanteVO> findByName(String name) {
		try {
			manejadorEntidad.clear();
			// usamos la clase Query creada con el manejador de entidad
			Query consultaNombre = manejadorEntidad.createQuery("select f from FabricanteVO f where nombre=:x");
			// se da valor al par�metro
			consultaNombre.setParameter("x", name);
			FabricanteVO fabri = (FabricanteVO) consultaNombre.getSingleResult();
			return  Optional.of(fabri);
			
		} catch (NoResultException e) {
			// previamente he buscado el tipo de error si buscaba un fabricante que no exist�a, comprobado en test02
			System.out.println("Error al buscar. Ese nombre de fabricante no existe. " + e.getMessage());
			// se devuelve un Optional vacio para evitar nulos
			return Optional.empty();
		}
	}

}
            
      
      
      
  public class VehiculoDAOImpl implements VehiculoDAO {
	
	private EntityManager manejadorEntidad;

	public VehiculoDAOImpl(EntityManager manejadorEntidad) {
		this.manejadorEntidad = manejadorEntidad;
	}

	@Override
	public int insertar(VehiculoVO vehiculo) {
		try {
			manejadorEntidad.getTransaction().begin();
			manejadorEntidad.persist(vehiculo);
			
			// al insertar vehiculo nuevo el contador del fabricante aumenta en 1
			int contadorFabriOld = vehiculo.getFabricante().getContador();
			int contadorFabriNew = contadorFabriOld + 1;
			FabricanteVO fabri = vehiculo.getFabricante();
			fabri.setContador(contadorFabriNew);
			manejadorEntidad.merge(fabri);
			
			manejadorEntidad.getTransaction().commit();			
					
			return 1;
			
		} catch (PersistenceException e) {
			// System.out.println("El error es del tipo " + e.getCause()); // Para saber cual es el error

			if(e.getCause() instanceof DataException) {
				System.out.println("El tama�o de alg�n campo excede al de la base de datos.");
			}
			else if(e.getCause() instanceof ConstraintViolationException) {
				System.out.println("Error, nombre del modelo repetido. " + e.getMessage());
			}
			else {
				System.out.println("Error al insertar el veh�culo " + e.getMessage());
			}
			
			manejadorEntidad.getTransaction().rollback();
			
		}
		return 0;
		
		
	}

}
            
      

Services and implementation

      
      public interface ServicioFabricante {
	
	Optional<FabricanteVO> findByName(String nombre);
}

public class ServicioFabricanteImpl implements ServicioFabricante {

	private FabricanteDAO f;
	private MySqlDAOFactory factoria;
	
	public ServicioFabricanteImpl() {
		factoria = MySqlDAOFactory.conectar();
		f = factoria.getFabricanteDAOImpl();
	}

	public Optional<FabricanteVO> findByName(String nombre) {
		return f.findByName(nombre);
	}

	
	

	
}
      
      

Factory

      
    
    public class MySqlDAOFactory {

	EntityManagerFactory factoria;
	EntityManager manejadorEntidad;
	private static MySqlDAOFactory facto;
	
	private MySqlDAOFactory() {
		try {
			//generamos el esquema
			Persistence.generateSchema("exament3", null);
			// creo la factoria
			factoria = Persistence.createEntityManagerFactory("exament3");
			// creo el manejador de entidad
			manejadorEntidad = factoria.createEntityManager();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public FabricanteDAO getFabricanteDAOImpl() {
		return new FabricanteDAOImpl(manejadorEntidad);
	}
	
	public VehiculoDAO getVehiculoDAOImpl() {
		return new VehiculoDAOImpl(manejadorEntidad);
	}
	
		
	public static MySqlDAOFactory conectar() {
		if (facto==null)
			return new MySqlDAOFactory();
		else return facto;
	}
	
}
         
      

TEST

      
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.time.LocalDate;

import org.junit.jupiter.api.Test;

import com.dawes.modelo.VehiculoVO;
import com.dawes.servicio.ServicioFabricante;
import com.dawes.servicio.ServicioVehiculo;
import com.dawes.servicioImpl.ServicioFabricanteImpl;
import com.dawes.servicioImpl.ServicioVehiculoImpl;

public class TestJPA {

	static ServicioFabricante sf = new ServicioFabricanteImpl();
	static ServicioVehiculo sv = new ServicioVehiculoImpl();
	
	//primer test para comprobar la conexion y creaci�n del esquema
	@Test
	public void test01() {
		assertNotNull(sf);
	}
	
	// Test para comprobar que el fabricante buscado existe
	@Test
	public void test02() {
		assertEquals("seat", sf.findByName("seat").get().getNombre());
		// assertEquals(false, sf.findByName("citroen").isPresent());  // tambi�n funciona como comprobaci�n
		// assertEquals(true, sf.findByName("citroen").isEmpty());   // tambi�n funciona como comprobaci�n y salta el error
	
	}
	// Test para comprobar el n�mero de veh�culos del fabricante
	@Test 
	public void test03() {
		// como insertamos 2 desde el script, nos deber�a devolver 2 de tama�o de la lista de veh�culos
		assertEquals(2, sf.findByName("seat").get().getVehiculos().size());
	}	
		
	// Test para comprobar si la inserci�n del veh�culo se ha hecho correctamente 
	@Test 
	public void test04() {
		assertEquals(1, sv.insertar(new VehiculoVO("Ibiza", LocalDate.of(1995, 8, 15), sf.findByName("seat").get())));
	}
	
	// Test para comprobar el nuevo n�mero de veh�culos del fabricante
	@Test 
	public void test05() {
		// valdr�a para saber el n�mero de vehiculos del fabricante pero no si el contador se actualiza
		// assertEquals(3, sf.findByName("seat").get().getVehiculos().size()); 
		assertEquals(3, sf.findByName("seat").get().getContador());
	}
	
	// Test para comprobar si la inserci�n ha fallado xq los datos no cumplen las restricciones 
	@Test 
	public void test06() {
		// devuelve 0 si da el error buscado y no hace la inserci�n ni actualiza el contador
		assertEquals(0, sv.insertar(new VehiculoVO("IbizaIbizaIbizaIbizaIbiza", LocalDate.of(1995, 8, 15), sf.findByName("seat").get())));
	}
	
}

      
      

XML

      
  <persistence xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
	version="2.0">
	<persistence-unit name="exament3">
		<properties>
			<property name="javax.persistence.jdbc.driver"
				value="com.mysql.cj.jdbc.Driver" />
			<property name="javax.persistence.jdbc.url"
				value="jdbc:mysql://localhost:3306/exament3" />
			<property name="javax.persistence.jdbc.user" value="root" />
			<property name="javax.persistence.jdbc.password"
				value="temporal" />
			<property name="hibernate.show_sql" value="true" />
			<property
				name="javax.persistence.schema-generation.database.action"
				value="drop-and-create"></property>
			vproperty name="javax.persistence.sql-load-script-source"
				value="META-INF/data.sql"></property>
		</properties>
	</persistence-unit>
</persistence>




<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.dawes</groupId>
  <artifactId>laura_alvarez_JPA</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<properties>
		<maven.compiler.source>16</maven.compiler.source>
		<maven.compiler.target>16</maven.compiler.target>
	</properties>
	<dependencies>
		
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.27</version>
		</dependency>
		
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.6.2.Final</version>
		</dependency>
		
		<dependency>
			<groupId>org.hibernate.javax.persistence</groupId>
			<artifactId>hibernate-jpa-2.1-api</artifactId>
			<version>1.0.2.Final</version>
		</dependency>
	
	</dependencies>
</project>