JavaRush /Blogue Java /Random-PT /Seu primeiro aplicativo Hibernate

Seu primeiro aplicativo Hibernate

Publicado no grupo Random-PT
Neste artigo, você conhecerá uma das estruturas corporativas mais populares para Java e criará seu primeiro aplicativo usando o Hibernate. Nunca ouviu falar em Hibernate? Talvez você já tenha ouvido falar, mas ainda não usou? Ou tentou começar, mas não conseguiu? Nos três casos, sejam bem-vindos ao corte :) Seu primeiro aplicativo Hibernate - 1Olá a todos! Neste artigo, falarei sobre os principais recursos do framework Hibernate e ajudarei você a escrever seu primeiro miniaplicativo. Para isso precisamos:
  1. Edição final do Intellij Idea;
    Baixe no site oficial e ative a versão de teste de 30 dias.
  2. PostgeSQL é um dos sistemas modernos de gerenciamento de banco de dados (SGBD) mais populares;
  3. Maven (já integrado ao IDEA);
  4. Um pouco de paciência.
O artigo é dirigido principalmente a quem nunca trabalhou com esta tecnologia, por isso a quantidade de código foi reduzida ao máximo. Vamos começar!

O que é hibernar?

Esta é uma das implementações mais populares do modelo ORM. O modelo objeto-relacional descreve os relacionamentos entre objetos de software e registros no banco de dados. Claro, a funcionalidade do Hibernate é muito ampla, mas vamos nos concentrar nas funções mais simples. Nosso objetivo: criar uma aplicação CRUD (Criar, Ler, Atualizar, Excluir) que seja capaz de:
  1. Criar usuários (Usuário), bem como procurá-los no banco de dados por ID, atualizar seus dados no banco de dados e também excluí-los do banco de dados.
  2. Atribuir objetos de veículo (Auto) aos usuários. Crie, edite, encontre e exclua carros do banco de dados.
  3. Além disso, o aplicativo deverá remover automaticamente os carros “órfãos” do banco de dados. Aqueles. Quando um usuário é excluído, todos os carros pertencentes a ele também devem ser excluídos do banco de dados.
A estrutura do nosso projeto será a seguinte: Seu primeiro aplicativo Hibernate - 2Como vocês podem ver, nada complicado. 6 classes + 1 arquivo com configurações. Primeiro, vamos criar um novo projeto maven no Intellij Idea. Arquivo -> Novo Projeto. Dos tipos de projeto propostos, selecione Maven e siga em frente. Seu primeiro aplicativo Hibernate - 3Apache Maven é um framework para automatizar a montagem de projetos a partir da descrição de sua estrutura em arquivos na linguagem POM. Toda a estrutura do seu projeto estará descrita no arquivo pom.xml, que o próprio IDEA criará na raiz do seu projeto. Nas configurações do projeto você precisará especificar os parâmetros do Maven - groupId e artefatoId. Normalmente, em projetos, groupId é o nome da organização ou divisão, e o nome de domínio da organização ou site do projeto está escrito lá. Por sua vez, artefatoId é o nome do projeto. Para groupdId você pode especificar com.вашНикнейм.javarush, isso não afetará de forma alguma a operação do aplicativo. Para artefatoId, selecione qualquer nome de projeto de sua preferência. Você também pode deixar a Versão inalterada. Seu primeiro aplicativo Hibernate - 4Na última tela, basta confirmar os dados inseridos anteriormente. Seu primeiro aplicativo Hibernate - 5Então, criamos o projeto, só falta escrever o código e fazê-lo funcionar :) Em primeiro lugar, se quisermos criar uma aplicação que funcione com um banco de dados, definitivamente não podemos prescindir de um banco de dados! Baixe o PostgreSQL aqui (eu uso a versão 9). O PostgreSQL possui um usuário padrão ‘postgres’, você precisará criar uma senha para ele durante a instalação. Não esqueça sua senha, precisaremos dela mais tarde! (Em geral, usar o banco de dados padrão em aplicativos é uma má prática, mas para reduzir a quantidade de hemorróidas, nos contentaremos em criar nosso próprio banco de dados). Se você não se sente confortável com a linha de comando e as consultas SQL, há boas notícias. O Intellij IDEA fornece uma interface de usuário bastante adequada para trabalhar com o banco de dados. Fica assim: Seu primeiro aplicativo Hibernate - 6(localizado na barra lateral direita do IDEA, aba Banco de dados) Para criar uma conexão, clique em “+”, selecione nosso provedor (PostgeSQL). Preencha os campos com o usuário, nome do banco de dados (ambos são postgres) e digite a senha que você definiu ao instalar o PostgreSQL. Se necessário, baixe o driver Postgres, isso pode ser feito nesta mesma página. Clique em “Testar Conexão” para verificar se a conexão com o banco de dados foi estabelecida. Se você vir a inscrição “Bem-sucedido”, seguimos em frente. Agora vamos criar as tabelas que precisamos. Haverá dois deles: usuários e automóveis. Parâmetros para a tabela de usuários: Sua primeira aplicação no Hibernate – 7Observe que id é a chave primária. Se você não sabe o que é uma chave primária em SQL, pesquise no Google, é importante. Configuração para a tabela autos: Seu primeiro aplicativo Hibernate - 8Para automóveis você precisa configurar Foreign Key - chave estrangeira. Isso vinculará nossas tabelas. Aconselho você a ler mais sobre ele; Simplificando, refere-se a uma tabela externa, no nosso caso, usuários. Se o carro pertencer a um usuário com id=1, então no campo user_id da tabela autos ele terá 1. É assim que conectamos os usuários aos seus carros em nossa aplicação. Em nossa tabela autos, o campo user_id servirá como chave estrangeira. Ele se referirá ao campo id da tabela de usuários. Seu primeiro aplicativo Hibernate - 9Assim, criamos um banco de dados com duas tabelas. Resta entender como gerenciá-lo a partir do código Java. Começaremos com o arquivo pom.xml, no qual precisamos incluir as bibliotecas necessárias (na linguagem Maven elas são chamadas de dependências). Todas as bibliotecas são armazenadas no repositório central do Maven. Aqueles que você especifica em pom.xml, você pode usar no projeto. Seu pom.xml deve ficar assim: Seu primeiro aplicativo Hibernate - 10Nada complicado como você pode ver. Adicionamos apenas 2 dependências - para usar PostgreSQL e Hibernate. Agora vamos passar para o código Java. Crie todos os pacotes e classes necessários para o projeto. Para começar, precisaremos de modelos de dados - classes Usere 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;
    //you can not specify Column name if it matches the name of the column in the table
    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;

    //you can not specify Column name if it matches the name of the column in the table
    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 você pode ver, as classes estão equipadas com um monte de anotações ainda pouco claras. Vamos começar a lidar com eles. A anotação principal para nós é @Entity. Leia sobre isso na Wikipedia e lembre-se de tudo, esta é a base do básico. Esta anotação permite que objetos Java da sua classe sejam associados ao banco de dados. Para que uma classe seja uma entidade, ela deve atender aos seguintes requisitos:
  • Deve ter um construtor vazio ( publicou protected);
  • Não pode ser aninhado, interface ou enum;
  • Não pode ser finale não pode conter final-campos/propriedades;
  • Deve conter pelo menos um campo @Id.
Verifique as classes da sua entidade, estes são um lugar muito popular para dar um tiro no próprio pé. É muito fácil esquecer alguma coisa. Neste caso, a entidade pode:
  • Contém construtores não vazios;
  • Ser herdado e ser herdado;
  • Contém outros métodos e implementa interfaces.
Como você pode ver, a classe Useré muito semelhante à tabela de usuários. Existem campos id, name, age. As anotações localizadas acima delas não precisam de muita explicação: já está claro que @Id é uma indicação de que o campo é um identificador de objetos desta classe. A anotação @Table acima da classe especifica o nome da tabela na qual os objetos são gravados. Preste atenção no comentário acima do campo idade: se o nome do campo na classe e na tabela for o mesmo, não é necessário adicionar a anotação @Column, funcionará assim. Em relação à “estratégia = GenerationType.IDENTITY” indicada entre parênteses: existem diversas estratégias de geração de ID. Você pode pesquisar no Google, mas dentro da estrutura do nosso aplicativo você não precisa se preocupar. O principal é que os ids dos nossos objetos serão gerados automaticamente, portanto não há setter para o id e também não o especificamos no construtor. UserNo entanto, a classe ainda se destaca em alguns aspectos . Ele tem uma lista de carros! A anotação @OneToMany aparece acima da lista. Isso significa que um objeto da classe usuário pode corresponder a várias máquinas. A configuração "mappedBY" aponta para o campo de usuário da classe Auto. Dessa forma, máquinas e usuários ficam conectados entre si. A configuração orphanRemoval traduz muito bem do inglês - “remover órfãos”. Se excluirmos um usuário do banco de dados, todos os carros associados a ele também serão excluídos. Por sua vez, na classe Autovocê verá o campo user com a anotação @ManyToOne (muitos Autos podem corresponder a um usuário) e a anotação @JoinColumn. Indica através de qual coluna da tabela autos ocorre a conexão com a tabela de usuários (a mesma chave estrangeira que falamos anteriormente). Depois de criar um modelo de dados, é hora de ensinar nosso programa a realizar operações nesses dados no banco de dados. Vamos começar com a classe de utilitário HibernateSessionFactoryUtil. Ele tem apenas uma tarefa - criar uma fábrica de sessões para que nosso aplicativo funcione com o banco de dados (olá, padrão "Factory!"). Ele não pode fazer mais nada.
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("Exception!" + e);
            }
        }
        return sessionFactory;
    }
}
Nesta classe, criamos um novo objeto de configuração, Configuration, e passamos para ele as classes que ele deve perceber como entidades - Usere Auto. Preste atenção ao método configuration.getProperties(). Quais outras propriedades? Onde? Propriedades são parâmetros de como o hibernate funciona, especificados em um arquivo especial hibernate.cfg.xml. Seu primeiro aplicativo Hibernate - 11Hibernate.cfg.xml é lido aqui: new Configuration().configure(); Como você pode ver, não há nada de especial nele - parâmetros para conexão ao banco de dados e um parâmetro especial show_sql. É necessário para que todas as consultas SQL que hibernam serão executadas em nosso banco de dados sejam enviadas para o console. Dessa forma, você verá exatamente o que o Hibernate está fazendo a cada momento e se livrará do efeito “mágico”. Em seguida, precisamos da classe UserDAO. (No bom sentido, você precisa programar por meio de interfaces - crie uma interface UserDAOe implemente-a separadamente UserDAOImpl, mas para reduzir a quantidade de código vou omitir isso. Não faça isso em projetos reais!). DAO (objeto de acesso a dados) é um dos padrões de design mais comuns, “Acesso a Dados”. Seu significado é simples - criar uma camada na aplicação que seja responsável apenas pelo acesso aos dados e nada mais. Obtenha dados do banco de dados, atualize os dados, exclua os dados - e é isso. Leia mais sobre DAOs; você os usará constantemente em seu trabalho. O que nossa classe pode fazer UserDao? Na verdade, como todos os DAOs, ele só funciona com dados. Encontre um usuário por ID, atualize seus dados, exclua-o, extraia uma lista de todos os usuários do banco de dados ou salve um novo usuário no banco de dados - essa é toda a sua funcionalidade.
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;
    }
}
Os métodos UserDaosão semelhantes entre si. Na maioria deles, recebemos um objeto Session (uma sessão conectando ao nosso banco de dados) usando nosso Session Factory, criamos uma única transação dentro desta sessão, realizamos as transformações de dados necessárias, salvamos o resultado da transação no banco de dados e fechamos a sessão. Os métodos em si, como você pode ver, são bastante simples. O DAO é o “coração” da nossa aplicação. Entretanto, não criaremos o DAO diretamente e chamaremos seus métodos em nosso arquivo main(). Toda a lógica será movida para o arquivo 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);
    }


}
Serviço é uma camada de dados no aplicativo responsável pela execução da lógica de negócios. Se o seu programa precisar executar alguma lógica de negócios, ele fará isso por meio de serviços. O serviço contém dentro de si UserDaoe chama métodos DAO em seus métodos. Isso pode parecer duplicação de funções para você (por que não apenas chamar métodos de um objeto dao), mas com um grande número de objetos e lógica complexa, dividir o aplicativo em camadas traz enormes benefícios (esta é uma boa prática, lembre-se desta informação para o futuro e leia sobre “camadas de aplicação” "). Em nosso serviço a lógica é simples, mas em projetos reais os métodos de serviço conterão muito mais de uma linha de código :) Agora temos tudo que precisamos para o aplicativo funcionar! Vamos criar main()um usuário e máquinas para ele no método, conectá-los entre si e salvá-los no banco de dados.
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 você pode ver, a tabela users tem sua própria entrada e a tabela autos tem a sua própria. Seu primeiro aplicativo Hibernate - 13Seu primeiro aplicativo Hibernate - 14Vamos tentar renomear nosso usuário. Vamos limpar a tabela de usuários e executar o 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);
    }
}
Funciona! Seu primeiro aplicativo Hibernate - 15E se você excluir um usuário? Vamos limpar a tabela de usuários (autos se limpará) e executar o 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);
    }
}
E nossas tabelas estão completamente vazias (preste atenção no console, todas as consultas que o Hibernate executou serão exibidas lá). Você pode brincar com o aplicativo e experimentar todos os seus recursos. Por exemplo, crie um usuário com máquinas, salve-o no banco de dados, veja qual ID está atribuído a ele e tente usar o método main()para “puxar” o usuário do banco de dados por esse ID e exibir uma lista de suas máquinas no console . Claro, vimos apenas uma pequena parte da funcionalidade do Hibernate. Seus recursos são muito amplos e há muito tempo é um dos padrões da indústria para desenvolvimento Java. Se você quiser estudá-lo detalhadamente, posso recomendar o livro “Java Persistence API and Hibernate”, que revi em um de meus artigos anteriores. Espero que este artigo tenha sido útil para os leitores. Se você tiver alguma dúvida, pergunte nos comentários, terei prazer em responder :) Além disso, não se esqueça de apoiar o autor no concurso dando um “Curtir” nele. Ou melhor ainda - “Gostei muito” :) Boa sorte nos estudos!
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION