JavaRush /Blog Java /Random-ES /Tu primera aplicación de Hibernate

Tu primera aplicación de Hibernate

Publicado en el grupo Random-ES
En este artículo, se familiarizará con uno de los marcos empresariales más populares para Java y creará su primera aplicación utilizando Hibernate. ¿Nunca has oído hablar de Hibernate? ¿Quizás has oído hablar de él, pero no lo has usado? ¿O intentó empezar pero no lo consiguió? En los tres casos, bienvenidos al corte :) Tu primera aplicación de Hibernate - 1¡Hola a todos! En este artículo, hablaré sobre las características principales del marco de Hibernate y te ayudaré a escribir tu primera miniaplicación. Para esto necesitamos:
  1. Intellij Idea última edición;
    Descárgalo desde el sitio web oficial y activa la versión de prueba de 30 días.
  2. PostgeSQL es uno de los sistemas de gestión de bases de datos (DBMS) modernos más populares;
  3. Maven (ya integrado en IDEA);
  4. Un poco de paciencia.
El artículo está dirigido principalmente a aquellos que nunca han trabajado con esta tecnología, por lo que se ha reducido al máximo la cantidad de código. ¡Empecemos!

¿Qué es Hibernar?

Esta es una de las implementaciones más populares del modelo ORM. El modelo relacional de objetos describe las relaciones entre los objetos de software y los registros en la base de datos. Por supuesto, la funcionalidad de Hibernate es muy amplia, pero nos centraremos en las funciones más simples. Nuestro objetivo: crear una aplicación CRUD (Crear, Leer, Actualizar, Eliminar) que sea capaz de:
  1. Cree usuarios (Usuario), así como búsquelos en la base de datos por ID, actualice sus datos en la base de datos y también elimínelos de la base de datos.
  2. Asignar objetos de vehículo (Auto) a los usuarios. Cree, edite, busque y elimine automóviles de la base de datos.
  3. Además, la aplicación debería eliminar automáticamente los coches "huérfanos" de la base de datos. Aquellos. Cuando se elimina un usuario, todos los coches que le pertenecen también deben eliminarse de la base de datos.
La estructura de nuestro proyecto será la siguiente: Tu primera aplicación de Hibernate - 2Como ves, nada complicado. 6 clases + 1 archivo con configuraciones. Primero, creemos un nuevo proyecto maven en Intellij Idea. Archivo -> Nuevo proyecto. De los tipos de proyectos propuestos, seleccione Maven y continúe. Tu primera aplicación de Hibernate - 3Apache Maven es un framework para automatizar el ensamblaje de proyectos a partir de una descripción de su estructura en archivos en lenguaje POM. La estructura completa de su proyecto se describirá en el archivo pom.xml, que la propia IDEA creará en la raíz de su proyecto. En la configuración del proyecto deberá especificar los parámetros de Maven: groupId y artefactoId. Normalmente, en proyectos, groupId es el nombre de la organización o división, y allí está escrito el nombre de dominio de la organización o sitio del proyecto. A su vez, artefactoId es el nombre del proyecto. Para groupdId puede especificar com.вашНикнейм.javarush, esto no afectará el funcionamiento de la aplicación de ninguna manera. Para artefactoId, seleccione el nombre de cualquier proyecto que desee. También puedes dejar la versión sin cambios. Tu primera aplicación de Hibernate - 4En la última pantalla, simplemente confirme sus datos ingresados ​​anteriormente. Tu primera aplicación de Hibernate - 5Entonces, hemos creado el proyecto, solo queda escribir el código y hacerlo funcionar :) En primer lugar, si queremos crear una aplicación que funcione con una base de datos, ¡definitivamente no podemos prescindir de una base de datos! Descargue PostgreSQL desde aquí (yo uso la versión 9). PostgreSQL tiene un usuario predeterminado 'postgres', deberá crear una contraseña durante la instalación. ¡No olvides tu contraseña, la necesitaremos más tarde! (En general, utilizar la base de datos predeterminada en las aplicaciones es una mala práctica, pero para reducir la cantidad de hemorroides nos conformaremos con crear nuestra propia base de datos). Si no se siente cómodo con la línea de comandos y las consultas SQL, hay buenas noticias. Intellij IDEA proporciona una interfaz de usuario bastante adecuada para trabajar con la base de datos. Se ve así: Tu primera aplicación de Hibernate - 6(ubicado en la barra lateral derecha de IDEA, pestaña Base de datos) Para crear una conexión, haga clic en "+", seleccione nuestro proveedor (PostgeSQL). Complete los campos con el usuario, el nombre de la base de datos (ambos son postgres) e ingrese la contraseña que estableció al instalar PostgreSQL. Si es necesario descargue el controlador de Postgres, esto lo puede hacer en esta misma página. Haga clic en "Probar conexión" para comprobar que la conexión a la base de datos esté establecida. Si ve la inscripción "Exitoso", seguimos adelante. Ahora creemos las tablas que necesitamos. Habrá dos de ellos: usuarios y automóviles. Parámetros para la tabla de usuarios: Tu primera aplicación en Hibernate - 7tenga en cuenta que la identificación es la clave principal. Si no sabe qué es una clave principal en SQL, busque en Google, es importante. Configuración de la tabla de autos: Tu primera aplicación en Hibernate - 8Para automóviles, debe configurar la clave externa: clave externa. Vinculará nuestras mesas. Te aconsejo que leas más sobre él; En pocas palabras, se refiere a una tabla externa, en nuestro caso, usuarios. Si el automóvil pertenece a un usuario con id=1, entonces en el campo user_id de la tabla de autos tendrá 1. Así es como conectamos a los usuarios con sus automóviles en nuestra aplicación. En nuestra tabla de autos, el campo user_id servirá como clave externa. Se referirá al campo de identificación de la tabla de usuarios. Tu primera aplicación de Hibernate - 9Así, hemos creado una base de datos con dos tablas. Queda por entender cómo gestionarlo desde el código Java. Comenzaremos con el archivo pom.xml, en el que debemos incluir las bibliotecas necesarias (en lenguaje Maven se llaman dependencias). Todas las bibliotecas se almacenan en el repositorio central de Maven. Aquellos que especifique en pom.xml, podrá utilizarlos en el proyecto. Tu pom.xml debería verse así: Tu primera aplicación de Hibernate - 10Nada complicado como puedes ver. Agregamos solo 2 dependencias: para usar PostgreSQL e Hibernate. Ahora pasemos al código Java. Cree todos los paquetes y clases necesarios para el proyecto. Para empezar, necesitaremos modelos de datos: clases Usery Auto.
package models;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table (name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(name = "name")
    private String name;
    // no puede especificar el nombre de la columna si coincide con el nombre de la columna en la tabla
    private int age;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Auto> autos;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
        autos = new ArrayList<>();
    }

    public void addAuto(Auto auto) {
        auto.setUser(this);
        autos.add(auto);
    }

    public void removeAuto(Auto auto) {
        autos.remove(auto);
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<Auto> getAutos() {
        return autos;
    }

    public void setAutos(List<Auto> autos) {
        this.autos = autos;
    }

    @Override
    public String toString() {
        return "models.User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package models;

import javax.persistence.*;

@Entity
@Table(name = "autos")
public class Auto {

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

    @Column (name = "model")
    private String model;

    // no puede especificar el nombre de la columna si coincide con el nombre de la columna en la tabla
    private String color;


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    public Auto() {
    }

    public Auto(String model, String color) {
        this.model = model;
        this.color = color;
    }

    public int getId() {
        return id;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return color + " " + model;
    }
}
Como puede ver, las clases están equipadas con un montón de anotaciones aún poco claras. Empecemos a ocuparnos de ellos. La anotación principal para nosotros es @Entity. Léelo en Wikipedia y recuerda todo, esta es la base de lo básico. Esta anotación permite asociar objetos Java de su clase con la base de datos. Para que una clase sea una entidad, debe cumplir los siguientes requisitos:
  • Debe tener un constructor vacío ( publico protected);
  • No se puede anidar, interfaz o enum;
  • No puede ser finalni contener final-campos/propiedades;
  • Debe contener al menos un campo @Id.
Consulta las clases de tu entidad, estos son un lugar muy popular para dispararte en el pie. Es muy fácil olvidar algo. En este caso, la entidad puede:
  • Contener constructores no vacíos;
  • Ser heredado y ser heredado;
  • Contiene otros métodos e implementa interfaces.
Como puede ver, la clase Useres muy similar a la tabla de usuarios. Hay campos id, name, age. Las anotaciones ubicadas encima de ellos no necesitan mucha explicación: ya está claro que @Id es una indicación de que el campo es un identificador de objetos de esta clase. La anotación @Table encima de la clase especifica el nombre de la tabla en la que se escriben los objetos. Preste atención al comentario sobre el campo de edad: si el nombre del campo en la clase y la tabla es el mismo, no es necesario agregar la anotación @Column, funcionará así. Respecto a la “estrategia=TipoGeneración.IDENTIDAD” indicada entre paréntesis: existen varias estrategias de generación de ID. Puedes buscarlo en Google, pero dentro del marco de nuestra aplicación no tienes que molestarte. Lo principal es que los identificadores de nuestros objetos se generarán automáticamente, por lo que no existe un definidor para el identificador y tampoco lo especificamos en el constructor. UserSin embargo, la clase todavía se destaca en algunos aspectos . ¡Tiene una lista de autos! La anotación @OneToMany aparece encima de la lista. Esto significa que un objeto de la clase de usuario puede corresponder a varias máquinas. La configuración "mappedBY" apunta al campo de usuario de la clase Auto. De esta forma, las máquinas y los usuarios están conectados entre sí. La configuración orphanRemoval se traduce bastante bien del inglés: "eliminar huérfanos". Si eliminamos un usuario de la base de datos, también se eliminarán todos los coches asociados a él. A su vez, en la clase Autoverás el campo de usuario con la anotación @ManyToOne (muchos Autos pueden corresponder a un Usuario) y la anotación @JoinColumn. Indica a través de qué columna de la tabla autos se produce la conexión con la tabla usuarios (la misma clave foránea de la que hablamos antes). Después de crear un modelo de datos, es hora de enseñarle a nuestro programa a realizar operaciones con estos datos en la base de datos. Comencemos con la clase de utilidad HibernateSessionFactoryUtil. Sólo tiene una tarea: crear una fábrica de sesiones para que nuestra aplicación funcione con la base de datos (hola, el patrón "Factory!"). No puede hacer nada más.
package utils;

import models.Auto;
import models.User;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactoryUtil {
    private static SessionFactory sessionFactory;

    private HibernateSessionFactoryUtil() {}

    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                Configuration configuration = new Configuration().configure();
                configuration.addAnnotatedClass(User.class);
                configuration.addAnnotatedClass(Auto.class);
                StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
                sessionFactory = configuration.buildSessionFactory(builder.build());

            } catch (Exception e) {
                System.out.println("¡Excepción!" + e);
            }
        }
        return sessionFactory;
    }
}
En esta clase, creamos un nuevo objeto de configuración, Configuración, y le pasamos las clases que debería percibir como entidades: Usery Auto. Presta atención al método configuration.getProperties(). ¿Qué otras propiedades? ¿Dónde? Las propiedades son parámetros sobre cómo funciona la hibernación, especificados en un archivo especial hibernate.cfg.xml. Tu primera aplicación de Hibernate - 11Hibernate.cfg.xml se lee aquí: new Configuration().configure(); Como puede ver, no contiene nada especial: parámetros para conectarse a la base de datos y un parámetro especial show_sql. Es necesario para que todas las consultas SQL que se ejecutarán en hibernación en nuestra base de datos se envíen a la consola. De esta manera, verá exactamente lo que Hibernate está haciendo en cada momento y eliminará el efecto "mágico". A continuación necesitamos la clase UserDAO. (En el buen sentido, es necesario programar a través de interfaces: crear una interfaz UserDAOe implementarla por separado UserDAOImpl, pero para reducir la cantidad de código omitiré esto. ¡No hagas esto en proyectos reales!). DAO (objeto de acceso a datos) es uno de los patrones de diseño más comunes, "Acceso a datos". Su significado es simple: crear una capa en la aplicación que sea responsable únicamente del acceso a los datos y nada más. Obtenga datos de la base de datos, actualícelos, elimínelos y listo. Lea más sobre las DAO; las utilizará constantemente en su trabajo. ¿ Qué puede hacer nuestra clase UserDao? En realidad, como todos los DAO, sólo puede funcionar con datos. Encuentre un usuario por identificación, actualice sus datos, elimínelo, obtenga una lista de todos los usuarios de la base de datos o guarde un nuevo usuario en la base de datos: esas son todas sus funciones.
package dao;

import models.Auto;
import models.User;
import org.hibernate.Session;
import org.hibernate.Transaction;
import utils.HibernateSessionFactoryUtil;
import java.util.List;

public class UserDao {

    public User findById(int id) {
        return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(User.class, id);
    }

    public void save(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.save(user);
        tx1.commit();
        session.close();
    }

    public void update(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.update(user);
        tx1.commit();
        session.close();
    }

    public void delete(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.delete(user);
        tx1.commit();
        session.close();
    }

    public Auto findAutoById(int id) {
        return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Auto.class, id);
    }

    public List<User> findAll() {
        List<User> users = (List<User>)  HibernateSessionFactoryUtil.getSessionFactory().openSession().createQuery("From User").list();
        return users;
    }
}
Los métodos UserDaoson similares entre sí. En la mayoría de ellos, recibimos un objeto de sesión (una sesión que se conecta a nuestra base de datos) usando nuestra Session Factory, creamos una única transacción dentro de esta sesión, realizamos las transformaciones de datos necesarias, guardamos el resultado de la transacción en la base de datos y cerramos la sesión. Los métodos en sí, como puede ver, son bastante sencillos. El DAO es el “corazón” de nuestra aplicación. Sin embargo, no crearemos el DAO directamente ni llamaremos a sus métodos en nuestro archivo main(). Toda la lógica se trasladará al UserService.
package services;

import dao.UserDao;
import models.Auto;
import models.User;

import java.util.List;

public class UserService {

    private UserDao usersDao = new UserDao();

    public UserService() {
    }

    public User findUser(int id) {
        return usersDao.findById(id);
    }

    public void saveUser(User user) {
        usersDao.save(user);
    }

    public void deleteUser(User user) {
        usersDao.delete(user);
    }

    public void updateUser(User user) {
        usersDao.update(user);
    }

    public List<User> findAllUsers() {
        return usersDao.findAll();
    }

    public Auto findAutoById(int id) {
        return usersDao.findAutoById(id);
    }


}
El servicio es una capa de datos en la aplicación que es responsable de ejecutar la lógica empresarial. Si su programa necesita realizar alguna lógica empresarial, lo hace a través de servicios. El servicio contiene dentro de sí mismo UserDaoy llama a métodos DAO en sus métodos. Esto puede parecerle una duplicación de funciones (¿por qué no simplemente llamar a métodos desde un objeto dao), pero con una gran cantidad de objetos y una lógica compleja, dividir la aplicación en capas tiene enormes beneficios (esta es una buena práctica, recuerde esta información para el futuro y lea sobre “capas de aplicación” "). En nuestro servicio, la lógica es simple, pero en proyectos reales, los métodos de servicio contendrán mucho más de una línea de código :) ¡Ahora tenemos todo lo que necesitamos para que la aplicación funcione! Creemos main()un usuario y máquinas para él en el método, conectémoslos entre sí y guárdelos en la base de datos.
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        ferrari.setUser(user);
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
    }
}
Como puede ver, la tabla de usuarios tiene su propia entrada y la tabla de autos tiene la suya propia. Tu primera aplicación de Hibernate - 13Tu primera aplicación de Hibernate - 14Intentemos cambiar el nombre de nuestro usuario. Limpiemos la tabla de usuarios y ejecutemos el código.
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
        user.setName("Sasha");
        userService.updateUser(user);
    }
}
¡Obras! Tu primera aplicación de Hibernate - 15¿Qué pasa si eliminas un usuario? Borremos la tabla de usuarios (los autos se borrarán solos) y ejecutemos el código.
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
        user.setName("Sasha");
        userService.updateUser(user);
        userService.deleteUser(user);
    }
}
Y nuestras tablas están completamente vacías (preste atención a la consola, allí se mostrarán todas las consultas que haya ejecutado Hibernate). Puedes jugar con la aplicación y probar todas sus funciones. Por ejemplo, cree un usuario con máquinas, guárdelo en la base de datos, vea qué ID se le asigna e intente usar el método main()para "sacar" al usuario de la base de datos mediante esta identificación y mostrar una lista de sus máquinas en la consola. . Por supuesto, sólo vimos una pequeña parte de la funcionalidad de Hibernate. Sus capacidades son muy amplias y durante mucho tiempo ha sido uno de los estándares de la industria para el desarrollo de Java. Si desea estudiarlo en detalle, puedo recomendarle el libro "Java Persistence API and Hibernate", que revisé en uno de mis artículos anteriores. Espero que este artículo haya sido útil para los lectores. Si tienes alguna pregunta, hazla en los comentarios, estaré encantado de responderte :) Además, no olvides apoyar al autor en el concurso dándole "Me gusta". O mejor aún: “Me gusta mucho” :) ¡Buena suerte en tus estudios!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION