Crear un modelo-controlador

Para hacer con Spring Boot un Modelo – Controlador, es decir, que podamos acceder a una base de datos y mostrar información tenemos que hacer los siguientes pasos:

1.- Crear un proyecto con las dependencias SpringBoot, JPA y Mysql

2.- Configurar el acceso a la base de datos:
application.properties

spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:mysql://localhost:3306/sakila
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.show-sql: true

3.- Crear una entidad, igual que hacía en hibernate

package com.trifulcas.SpringBootData;

import java.sql.Timestamp;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import jakarta.persistence.*;

@Entity
@Table(name = "category")
public class Category {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "category_id")
	private int categoryId;

	@Column(name = "name", nullable = false)
	private String name;

	@Column(name = "last_update", nullable = false)
	private Timestamp lastUpdate;

	
	public Category() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Category(String name) {
		super();
		this.name = name;
		Date now = new Date();
		this.lastUpdate = new Timestamp(now.getTime());
	}

	public int getCategoryId() {
		return categoryId;
	}

	public void setCategoryId(int categoryId) {
		this.categoryId = categoryId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Timestamp getLastUpdate() {
		return lastUpdate;
	}

	public void setLastUpdate(Timestamp lastUpdate) {
		this.lastUpdate = lastUpdate;
	}

	@Override
	public String toString() {
		return "Category [categoryId=" + categoryId + ", name=" + name + ", lastUpdate=" + lastUpdate + "]";
	}

}

4.- Crear un ‘repository’ para la entidad. ¿Qué es esto? Es una especie de DAO pero ya prefabricado.¡OJO! Es un interface, no una clase.

public interface CategoryRepository extends CrudRepository<Category, Integer> {

}

5.- Por último podremos usar todas las utilidades del repository en cualquier controlador. Para hacerlo tenemos que definir una clase del mismo tipo que el repository y anotarla con @AutoWired

package com.trifulcas.SpringBootData;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

// Esta anotación serializa por defecto todo lo que las funciones retornen
@RestController
public class CategoryController {
	
	// Lo que hace es crear e inyectar un objeto de tipo
	// CRUD con la entidad 'Category'
	// Este objeto nos servirá como un DAO, nos permite crear, modificar
	// obtener y borrar cualquier elemento de la web
	// el objeto repository nos permite usar findall, findbyid, deletebyid, save...
	@Autowired
	private CategoryRepository categoryRepository;

	@GetMapping("/add")
	public String addNewCategory(
			@RequestParam(value = "name", defaultValue = "Nueva categoría") 
			String name) {
		Category cat = new Category(name);
		categoryRepository.save(cat);
		return "Saved "+cat.getCategoryId();
	}
	
	@GetMapping("/all")
	public Iterable<Category> viewAll() {
		return categoryRepository.findAll();
	}

@GetMapping("/delete")
	public String deleteCategory(
			@RequestParam(value = "id", defaultValue = "0") 
			String id) {
		try {
			categoryRepository.deleteById(Integer.parseInt(id));
			return "Borrado "+id;
		}catch(Exception ex) {
			return ex.getMessage();
		}
	}
	
}

Solución ejercicio

package com.trifulcas.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class EjercicioController {
	// Endpoint. Cualquier programa que acceda a este endpoint
	// Tendrá esta respuesta
	// url del servidor + '/ola'
	@GetMapping("/ola")
	public String ola() {
		return "Ola k ase???";
	}
	
	@GetMapping("/normal")
	public String normal() {
		return "Hola ¿Qué tal?";
	}

	@GetMapping("/personal")
	public String personal(
			@RequestParam(value = "nombre", defaultValue = "Anónimo")
			String nombre) {
		return String.format("Hola %s ¿Cómo estás?", nombre);
	}

	@GetMapping("/azar")
	public String azar() {
		return azarRandom();
	}
	private String azarRandom() {
		List<String> mensajes = new ArrayList<>(Arrays.asList("Hola", "Que hay?", "Buenas", "Jelou", "Hey"));
		Random r=new Random();
		return mensajes.get(r.nextInt(mensajes.size()));
	}
}

Spring boot

Asó queda el main

package com.trifulcas.TestSpringBoot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.trifulcas")
public class TestSpringBootApplication {

	public static void main(String[] args) {
		SpringApplication.run(TestSpringBootApplication.class, args);
	}

}

Así queda el controlador

package com.trifulcas.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
	// Dentro del controlador pondré todas las entradas a mi app
	// Se mapean con Mapping y la ruta
	@GetMapping("/")
	public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
		return String.format("Hello %s!", name);
	}
}

Controlador con más endpoints

package com.trifulcas.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
	// Dentro del controlador pondré todas las entradas a mi app
	// Se mapean con Mapping y la ruta
	// Defino un punto de entrada que es la raiz
	@GetMapping("/")
	public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
		System.out.println("Han entrado en la raiz. Name vale"+name);
		return String.format("Hello %s!", name);
	}
	// mi punto de entrada es /pepe
	@GetMapping("/pepe")
	public String pepe() {
		System.out.println("Han entrado en pepe");
		return "Me llamo pepe";
	}
	// Punto de entrada /suma y recupero dos parámetros (a y b) con los que hago la suma
	@GetMapping("/suma")
	public String suma(@RequestParam(value = "a", defaultValue = "1") String a, @RequestParam(value = "b", defaultValue = "1") String b) {
		System.out.println("Han entrado en suma con valores "+a+","+b);
		return (Integer.parseInt(a)+Integer.parseInt(b))+"";
	}
}

Ejemplos HQL

	Session session = HibernateUtil.getSessionFactory().openSession();
		// Ojo aquí, el from es caseinsensitive pero la entidad 'Autor'
		// SI LO ES tiene que ser como se llame la entidad
		// Esto es lo más sencillo, seleccionar todo de una entidad
		List<Autor> autores = session.createQuery("from Autor", Autor.class).list();
		System.out.println(autores);

		// Podemos añadir condiciones con Where
		autores = session.createQuery("from Autor  where idautor=6", Autor.class).list();
		System.out.println(autores);
		// Podemos seleccionar algunas propiedades
		List<String> nombres = session.createQuery("select nombre from Autor", String.class).list();
		System.out.println(nombres);
		
		// Podemos usar parámetros
		Query<Autor> query = session.createQuery("from Autor where idautor=:id", Autor.class);
		query.setParameter("id",6);
		autores=query.list();
		System.out.println(autores);
		
		// Si nos fijamos después de cada query ponemos list()
		// Esto nos sirve para dos cosas: obtener una lista
		// Y, sobre todo, ejecutar la query.
		// Las queries son como los procedimientos preparados
		// No se lanzan hasta que se lo decimos

Ejercicio de trabajar con Hibernate

Por partes.
Crear un género:

Genero g=new Genero();
g.setNombre("SteamPunk");
		DAO<Genero> gdao=new DAO<>(Genero.class);
		gdao.save(g);

Crear un libro:

DAO<Genero> gdao=new DAO<>(Genero.class);
		Genero g=gdao.get(8);
		Libro l=new Libro();
		l.setTitulo("Luna cruel");
		l.setPaginas(750);
		l.setGenero(g);
	DAO<Libro> ldao=new DAO<>(Libro.class);
	
		ldao.save(l);

Crear un autor

DAO<Libro> ldao=new DAO<>(Libro.class);
		Libro l=ldao.get(9);
		
		DAO<Autor> adao=new DAO<>(Autor.class);
		Autor a=new Autor();
		a.setNombre("Juan Perez");
		a.getLibros().add(l);
		adao.save(a);

Todo junto

	// Todo junto
		DAO<Genero> gdao=new DAO<>(Genero.class);
		DAO<Libro> ldao=new DAO<>(Libro.class);
		DAO<Autor> adao=new DAO<>(Autor.class);
		
		// Creo el género
		Genero g=new Genero();
		g.setNombre("Realismo sucio");
		gdao.save(g);
		
		// Creo el libro
		Libro l=new Libro();
		l.setTitulo("Cloacas de Barcelona");
		l.setPaginas(750);
		// Le asigno el género que acao de crear
		l.setGenero(g);
		ldao.save(l);
		
		// Creo el autor
		Autor a=new Autor();
		a.setNombre("Andreu Martín");
		// Le añado el libro que acabo de crear
		a.getLibros().add(l);
		adao.save(a);

Autores por género.
Con un método:

package com.trifulcas.Biblioteca;

import java.util.ArrayList;
import java.util.List;

import com.trifulcas.DAO.DAO;
import com.trifulcas.models.Autor;
import com.trifulcas.models.Genero;
import com.trifulcas.models.Libro;

public class GetAutores {

	public static void main(String[] args) {
		DAO<Genero> gdao=new DAO<>(Genero.class);
		Genero g=gdao.get(8);
		System.out.println(getAutores2(g));
		System.out.println(g.getAutores());
	}

	public static List<Autor> getAutores(Genero genero){
		List<Autor> res=new ArrayList<>();
		for(Libro libro:genero.getLibros()) {
			for(Autor autor:libro.getAutores()) {
				res.add(autor);
			}
		}
		return res;
	}
	public static List<Autor> getAutores2(Genero genero){
		List<Autor> res=new ArrayList<>();
		for(Libro libro:genero.getLibros()) {
			res.addAll(libro.getAutores());
		}
		return res;
	}
}

Dentro del POJO (no recomendable pero… ya se sabe 😉 )

package com.trifulcas.models;

import java.util.ArrayList;
import java.util.List;

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

@Entity
public class Genero {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idgenero")
	private int idGenero;

	private String nombre;

	@OneToMany(mappedBy="genero")
	List<Libro> libros=new ArrayList();
	
	public Genero() {
		super();
		// TODO Auto-generated constructor stub
	}

	public int getIdGenero() {
		return idGenero;
	}

	public void setIdGenero(int idGenero) {
		this.idGenero = idGenero;
	}

	public String getNombre() {
		return nombre;
	}

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

	public List<Libro> getLibros() {
		return libros;
	}

	public void setLibros(List<Libro> libros) {
		this.libros = libros;
	}
	public List<Autor> getAutores() {
		List<Autor> res=new ArrayList<>();
		for(Libro libro:this.getLibros()) {
			res.addAll(libro.getAutores());
		}
		return res;
	}
	@Override
	public String toString() {
		return "Genero [idGenero=" + idGenero + ", nombre=" + nombre + "]";
	}

	
}

Seguimos con DAO y más

Añado la clase DAO en un paquete aparte

package com.trifulcas.DAO;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.trifulcas.hibernate.HibernateUtil;

public class DAO<T> {
	private Class<T> entityClass;
	public Session session;

	public DAO(Class<T> clase) {
		this.entityClass = clase;
		session = HibernateUtil.getSessionFactory().openSession();
	}

	public void save(T Objeto) {
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			session.persist(Objeto);
			// commit transaction
			transaction.commit();
		} catch (Exception e) {
			if (transaction != null) {
				transaction.rollback();
			}
			e.printStackTrace();
		}
	}

	public List<T> getAll() {
		return session.createQuery("from " + entityClass.getSimpleName(), entityClass).list();

	}

	public T get(int id) {
		return session.get(entityClass, id);
	}

	public boolean delete(int id) {
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			
			T objeto = session.get(entityClass, id);
			session.remove(objeto);
			transaction.commit();
			return true;
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			if (transaction != null) {
				transaction.rollback();
			}
			return false;
		}
	}
}

Creo la entidad Libro

package com.trifulcas.models;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Libro {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idlibro")
	private int idLibro;
	private String titulo;
	private int paginas;
	@ManyToOne
	@JoinColumn(name="idgenero")
	private Genero genero;
	
	public Libro() {
		super();
		// TODO Auto-generated constructor stub
	}
	public int getIdLibro() {
		return idLibro;
	}
	public void setIdLibro(int idLibro) {
		this.idLibro = idLibro;
	}
	public String getTitulo() {
		return titulo;
	}
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}
	public int getPaginas() {
		return paginas;
	}
	public void setPaginas(int paginas) {
		this.paginas = paginas;
	}
	
	public Genero getGenero() {
		return genero;
	}
	public void setGenero(Genero genero) {
		this.genero = genero;
	}
	@Override
	public String toString() {
		return "Libro [idLibro=" + idLibro + ", titulo=" + titulo + ", paginas=" + paginas + "]";
	}
	
}

Añado a Genero la anotación onetomany

package com.trifulcas.models;

import java.util.ArrayList;
import java.util.List;

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

@Entity
public class Genero {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idgenero")
	private int idGenero;

	private String nombre;

	@OneToMany(mappedBy="genero")
	List<Libro> libros=new ArrayList();
	
	public Genero() {
		super();
		// TODO Auto-generated constructor stub
	}

	public int getIdGenero() {
		return idGenero;
	}

	public void setIdGenero(int idGenero) {
		this.idGenero = idGenero;
	}

	public String getNombre() {
		return nombre;
	}

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

	public List<Libro> getLibros() {
		return libros;
	}

	public void setLibros(List<Libro> libros) {
		this.libros = libros;
	}

	@Override
	public String toString() {
		return "Genero [idGenero=" + idGenero + ", nombre=" + nombre + "]";
	}

	
}

Lo anoto en hibernateutil

...
				configuration.addAnnotatedClass(Libro.class);

...

Y lo pruebo

package com.trifulcas.Biblioteca;

import com.trifulcas.DAO.DAO;
import com.trifulcas.models.Genero;
import com.trifulcas.models.Libro;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
    	try {
			DAO<Genero> gdao=new DAO<>(Genero.class);
			Genero g=gdao.get(1);
			System.out.println(g);
			System.out.println(g.getLibros());
			DAO<Libro> ldao=new DAO<>(Libro.class);
			Libro l=ldao.get(2);
			System.out.println(l);
			System.out.println(l.getGenero());

			/*
			 * Genero sf=new Genero();
			
			sf.setNombre("Ciencia ficción");
			gdao.save(sf);
			 */
			//gdao.delete(6);
		} catch (Exception ex) {
			System.out.println(ex);
		}
    	
    }
}

Añado autor, pongo el manytomany y modifico libro para que también lo tenga

package com.trifulcas.models;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "autor")
public class Autor {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int idautor;

	private String nombre;

	@ManyToMany(cascade= {CascadeType.MERGE})
	@JoinTable(name = "libro_autor", joinColumns = { @JoinColumn(name = "idautor") }, // La de esta entidad
			inverseJoinColumns = { @JoinColumn(name = "idlibro") })
	List<Libro> libros = new ArrayList();

	// Constructor por defecto
	public Autor() {
	}

	// Constructor con parámetros
	public Autor(String nombre) {
		this.nombre = nombre;
	}

	// Getters y Setters
	public int getIdautor() {
		return idautor;
	}

	public void setIdautor(int idautor) {
		this.idautor = idautor;
	}

	public String getNombre() {
		return nombre;
	}

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

	public List<Libro> getLibros() {
		return libros;
	}

	public void setLibros(List<Libro> libros) {
		this.libros = libros;
	}

	// Método toString
	@Override
	public String toString() {
		return "Autor{" + "idautor=" + idautor + ", nombre='" + nombre + '\'' + '}';
	}
}
package com.trifulcas.models;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;

@Entity
public class Libro {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idlibro")
	private int idLibro;
	private String titulo;
	private int paginas;
	
	@ManyToMany(mappedBy="libros")
	List<Autor> autores=new ArrayList();
	@ManyToOne
	@JoinColumn(name="idgenero")
	private Genero genero;
	
	public Libro() {
		super();
		// TODO Auto-generated constructor stub
	}
	public int getIdLibro() {
		return idLibro;
	}
	public void setIdLibro(int idLibro) {
		this.idLibro = idLibro;
	}
	public String getTitulo() {
		return titulo;
	}
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}
	public int getPaginas() {
		return paginas;
	}
	public void setPaginas(int paginas) {
		this.paginas = paginas;
	}
	
	public Genero getGenero() {
		return genero;
	}
	public void setGenero(Genero genero) {
		this.genero = genero;
	}
	
	public List<Autor> getAutores() {
		return autores;
	}
	public void setAutores(List<Autor> autores) {
		this.autores = autores;
	}
	@Override
	public String toString() {
		return "Libro [idLibro=" + idLibro + ", titulo=" + titulo + ", paginas=" + paginas + "]";
	}
	
}

Lo pruebo:

package com.trifulcas.Biblioteca;

import com.trifulcas.DAO.DAO;
import com.trifulcas.models.Autor;
import com.trifulcas.models.Genero;
import com.trifulcas.models.Libro;

/**
 * Hello world!
 *
 */
public class App {
	public static void main(String[] args) {
		try {
			DAO<Genero> gdao = new DAO<>(Genero.class);
			Genero g = gdao.get(1);
			System.out.println(g);
			System.out.println(g.getLibros());
			DAO<Libro> ldao = new DAO<>(Libro.class);
			Libro l = ldao.get(2);
			System.out.println(l);
			System.out.println(l.getGenero());
			DAO<Autor> adao = new DAO<>(Autor.class);
			Autor a = adao.get(2);
			System.out.println(a);
			System.out.println(a.getLibros());
			
			Libro fantasia=ldao.get(7);
			
			// Añado el libro al autor
			a.getLibros().add(fantasia);
			// Lo guardo
			adao.save(a);
			/*
			 * Genero sf = new Genero();
			 * 
			 * sf.setNombre("Fantasía romántica"); 
			 * gdao.save(sf);
			 * Libro libro=new Libro();
			 * libro.setTitulo("Amor en el fin del mundo"); 
			 * libro.setPaginas(200);
			 * libro.setGenero(sf); 
			 * ldao.save(libro);
			 */
			
		} catch (Exception ex) {
			System.out.println(ex);
		}

	}
}

Pasos proyecto

1.- Crear proyecto Maven (maven-archetype-quickstart)
2.- Añadir dependencias: Mysql e hibernate

<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.32</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.6.15.Final</version>
		</dependency>

3.- Creo la clase HibernateUtil

package com.trifulcas.hibernate;

import java.util.Properties;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {
	  private static  SessionFactory sessionFactory;
	 
	    public static SessionFactory getSessionFactory() {
	    	if (sessionFactory == null) {
				try {
					Configuration configuration = new Configuration();

					// Hibernate settings equivalent to hibernate.cfg.xml's properties
					Properties settings = new Properties();
					settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
					settings.put(Environment.URL, "jdbc:mysql://localhost:3306/sakila");
					settings.put(Environment.USER, "root");
					settings.put(Environment.PASS, "");
					settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");

					settings.put(Environment.SHOW_SQL, "true");

					settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");


					configuration.setProperties(settings);
					
					

					ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
							.applySettings(configuration.getProperties()).build();
					
					sessionFactory = configuration.buildSessionFactory(serviceRegistry);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return sessionFactory;
	    }
	 
	    public static void shutdown() {
	        // Close caches and connection pools
	        getSessionFactory().close();
	    }
}

4.- Pongo los datos correctos de conexión: BD, usuario y password (settings.put(Environment.URL, “jdbc:mysql://localhost:3306/biblioteca”);)
5.- Creo mi entidad

package com.trifulcas.models;

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

@Entity
@Table(name = "genero")
public class Genero {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idgenero")
	private int idGenero;

	private String nombre;

	public Genero() {
		super();
		// TODO Auto-generated constructor stub
	}

	public int getIdGenero() {
		return idGenero;
	}

	public void setIdGenero(int idGenero) {
		this.idGenero = idGenero;
	}

	public String getNombre() {
		return nombre;
	}

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

	@Override
	public String toString() {
		return "Genero [idGenero=" + idGenero + ", nombre=" + nombre + "]";
	}

	
}

6.- Lo anotamos en hibernateutil

...
				configuration.addAnnotatedClass(Genero.class);
...

7.- Lo pruebo:

Session session = HibernateUtil.getSessionFactory().openSession();
		try {
			Genero g = session.get(Genero.class, 1);
			System.out.println(g);
		} catch (Exception ex) {
			System.out.println(ex);
		}
		session.close();

Ejercicio Hibernate Biblioteca

Vamos a hacer la siguiente BD y la vamos a implementar con Hibernate

Genero 1–N Libro N–N Autor

Genero: Nombre
Libro: Titulo, paginas
Autor: nombre

 


CREATE TABLE `biblioteca`.`genero` (
  `idgenero` INT NOT NULL AUTO_INCREMENT,
  `nombre` VARCHAR(45) NULL,
  PRIMARY KEY (`idgenero`));

CREATE TABLE `biblioteca`.`libro` (
  `idlibro` INT NOT NULL AUTO_INCREMENT,
  `idgenero` INT NULL,
  `titulo` VARCHAR(45) NULL,
  `paginas` INT NULL,
  PRIMARY KEY (`idlibro`));
  
  CREATE TABLE `biblioteca`.`autor` (
  `idautor` INT NOT NULL AUTO_INCREMENT,
  `nombre` VARCHAR(150) NULL,
  PRIMARY KEY (`idautor`));

CREATE TABLE `libro_autor` (
  `idlibro_autor` int(11) NOT NULL AUTO_INCREMENT,
  `idlibro` int(11) DEFAULT NULL,
  `idautor` int(11) DEFAULT NULL,
  PRIMARY KEY (`idlibro_autor`),
  KEY `fk_libro_idx` (`idlibro`),
  KEY `fk_autor_idx` (`idautor`),
  CONSTRAINT `fk_autor` FOREIGN KEY (`idautor`) REFERENCES `autor` (`idautor`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_libro` FOREIGN KEY (`idlibro`) REFERENCES `libro` (`idlibro`) ON DELETE NO ACTION ON UPDATE NO ACTION
) 

ALTER TABLE `biblioteca`.`libro` 
ADD INDEX `fk_genero_idx` (`idgenero` ASC) ;
;
ALTER TABLE `biblioteca`.`libro` 
ADD CONSTRAINT `fk_genero`
  FOREIGN KEY (`idgenero`)
  REFERENCES `biblioteca`.`genero` (`idgenero`)
  ON DELETE NO ACTION
  ON UPDATE NO ACTION;

Datos de prueba

INSERT INTO `biblioteca`.`genero` (`nombre`) VALUES 
('Ficción'),
('No Ficción'),
('Ciencia Ficción'),
('Fantasía'),
('Biografía');

INSERT INTO `biblioteca`.`libro` (`idgenero`, `titulo`, `paginas`) VALUES 
(1, 'El Gran Gatsby', 180),
(2, 'Sapiens: De animales a dioses', 443),
(3, 'Dune', 412),
(4, 'Harry Potter y la piedra filosofal', 309),
(5, 'Steve Jobs', 656);

INSERT INTO `biblioteca`.`autor` (`nombre`) VALUES 
('F. Scott Fitzgerald'),
('Yuval Noah Harari'),
('Frank Herbert'),
('J.K. Rowling'),
('Walter Isaacson');
INSERT INTO `libro_autor` (`idlibro`, `idautor`) VALUES 
(1, 1),  -- El Gran Gatsby por F. Scott Fitzgerald
(2, 2),  -- Sapiens: De animales a dioses por Yuval Noah Harari
(3, 3),  -- Dune por Frank Herbert
(4, 4),  -- Harry Potter y la piedra filosofal por J.K. Rowling
(5, 5);  -- Steve Jobs por Walter Isaacson

Onetomany

package com.trifulcas.models;

import java.util.Date;
import java.util.List;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;

@Entity
@Table(name = "city")
public class City {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "city_id")
	private Short cityId;

	@Column(name = "city", nullable = false)
	private String city;

	// En la entidad de 'varios' ponemos ManyToOne
	@ManyToOne
	// Especificamos cual es la clave foránea de esta relación
	@JoinColumn(name = "country_id", nullable = false)
	// La propiedad siempre será la entidad relacionada
	private Country country; // Cuando recuperamos la entidad se cargan automáticamente las entidades relacionadas
	// Es decir, cuando yo cargo una ciudad se carga su país
	// Y puedo acceder a sus valores

	@OneToMany(mappedBy="city",cascade=CascadeType.ALL)
	private List<Address> addreses;
	
	@Column(name = "last_update", nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
	@Temporal(TemporalType.TIMESTAMP)
	private java.util.Date lastUpdate = new Date();

	// Constructor, getters, and setters

	public City() {
	}

	public City(String city, Country country) {
		this.city = city;
		this.country = country;
	}

	public Short getCityId() {
		return cityId;
	}

	public void setCityId(Short cityId) {
		this.cityId = cityId;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public Country getCountry() {
		return country;
	}

	public void setCountry(Country country) {
		this.country = country;
	}

	public java.util.Date getLastUpdate() {
		return lastUpdate;
	}

	public void setLastUpdate(java.util.Date lastUpdate) {
		this.lastUpdate = lastUpdate;
	}

	public List<Address> getAddreses() {
		return addreses;
	}

	public void setAddreses(List<Address> addreses) {
		this.addreses = addreses;
	}

	// Cuidado con poner country porque entramos en bucle
	@Override
	public String toString() {
		return "City [cityId=" + cityId + ", city=" + city + ", country="+country.getCountry()+"]";
	}

}

package com.trifulcas.models;

import java.sql.Timestamp;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;

@Entity
@Table(name = "address")
public class Address {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "address_id")
    private short addressId;

    @Column(name = "address", nullable = false, length = 50)
    private String address;

    @Column(name = "address2", length = 50)
    private String address2;

    @Column(name = "district", nullable = false, length = 20)
    private String district;

    @ManyToOne
    @JoinColumn(name="city_id")
    private City city;
   
   

	@Column(name = "postal_code", length = 10)
    private String postalCode;

    @Column(name = "phone", nullable = false, length = 20)
    private String phone;

    @Column(name = "last_update", nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
    private Timestamp lastUpdate;

    // Getters and Setters

    public short getAddressId() {
        return addressId;
    }

    public void setAddressId(short addressId) {
        this.addressId = addressId;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getAddress2() {
        return address2;
    }

    public void setAddress2(String address2) {
        this.address2 = address2;
    }

    public String getDistrict() {
        return district;
    }

    public void setDistrict(String district) {
        this.district = district;
    }
    public City getCity() {
		return city;
	}

	public void setCity(City city) {
		this.city = city;
	}

    public String getPostalCode() {
        return postalCode;
    }

    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Timestamp getLastUpdate() {
        return lastUpdate;
    }

    public void setLastUpdate(Timestamp lastUpdate) {
        this.lastUpdate = lastUpdate;
    }

	@Override
	public String toString() {
		return "Address [addressId=" + addressId + ", address=" + address + ", address2=" + address2 + ", district="
				+ district + ", city=" + city + ", postalCode=" + postalCode + ", phone=" + phone + ", lastUpdate="
				+ lastUpdate + "]";
	}
    
}

No olvideis anotar en HibernateUtil:

...
		configuration.addAnnotatedClass(Address.class);
...