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 :) ¡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:
Ahora pasemos al código Java. Cree todos los paquetes y clases necesarios para el proyecto. Para empezar, necesitaremos modelos de datos: clases
- Intellij Idea última edición;
Descárgalo desde el sitio web oficial y activa la versión de prueba de 30 días. - PostgeSQL es uno de los sistemas de gestión de bases de datos (DBMS) modernos más populares;
- Maven (ya integrado en IDEA);
- Un poco de paciencia.
¿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:- 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.
- Asignar objetos de vehículo (Auto) a los usuarios. Cree, edite, busque y elimine automóviles de la base de datos.
- 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.
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. En la última pantalla, simplemente confirme sus datos ingresados anteriormente. Entonces, 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í: (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: tenga 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: Para 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. Así, 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í: Nada complicado como puedes ver. Agregamos solo 2 dependencias: para usar PostgreSQL e Hibernate.
User
y 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 (
public
oprotected
); - No se puede anidar, interfaz o
enum
; - No puede ser
final
ni contenerfinal
-campos/propiedades; - Debe contener al menos un campo @Id.
- Contener constructores no vacíos;
- Ser heredado y ser heredado;
- Contiene otros métodos e implementa interfaces.
User
es 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. User
Sin 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 Auto
verá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: User
y 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. Hibernate.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 UserDAO
e 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 UserDao
son 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 UserDao
y 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. Intentemos 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! ¿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!
GO TO FULL VERSION