CodeGym /Java blogg /Slumpmässig /Din första Hibernate-applikation
John Squirrels
Nivå
San Francisco

Din första Hibernate-applikation

Publicerad i gruppen
I den här artikeln kommer du att bli bekant med ett av de mest populära företagsramverken för Java och skapa din första Hibernate-applikation. Aldrig hört talas om Hibernate? Eller kanske du har hört talas om det, men inte använt det? Eller kanske du försökte använda den, men misslyckades? I alla tre fallen - välkommen till under snittet :) Din första Hibernate-applikation - 1 Hej alla! I den här artikeln kommer jag att prata om Hibernate-ramverkets huvudfunktioner och hjälpa dig att skriva din första miniapplikation. För detta behöver vi:
  1. IntelliJ IDEA Ultimate Edition
    Ladda ner den från den officiella webbplatsen och aktivera 30-dagars provversionen.
  2. PostgreSQL - ett av de mest populära moderna databashanteringssystemen (DBMS)
  3. Maven (redan kopplad till IDEA)
  4. Lite tålamod.
För säkerhets skull la jag upp applikationskoden på GitHub (codegym-gren). Artikeln vänder sig i första hand till de som aldrig tidigare arbetat med den här tekniken, så jag har minimerat mängden kod. Låt oss börja!

Vad är Hibernate?

Det är en av de mest populära implementeringarna av objektrelationell mappning (ORM). En objektrelationell mappning definierar förhållandet mellan programvaruobjekt och databasposter. Naturligtvis har Hibernate mycket bred funktionalitet, men vi kommer att fokusera på de enklaste funktionerna. Vårt mål är att skapa en CRUD-applikation (Create, Read, Update, Delete) som kommer att kunna:
  1. Skapa användare (Användare), sök efter dem i databasen med ID, uppdatera deras data i databasen och ta bort dem från databasen.
  2. Tilldela bilobjekt (Auto) till användare. Skapa, uppdatera, hitta och ta bort bilar från databasen.
  3. Dessutom bör applikationen automatiskt ta bort "ägarelösa" bilar från databasen. Med andra ord, när en användare raderas måste alla bilar som tillhör den användaren också tas bort från databasen.
Vårt projekt kommer att vara uppbyggt så här: Din första Hibernate-applikation - 2Som du kan se, inget komplicerat. 6 klasser + 1 fil med konfigurationer. Skapa först ett nytt Maven-projekt i IntelliJ IDEA. Arkiv -> Nytt projekt. Välj Maven bland de föreslagna projekttyperna och gå vidare till nästa steg. Din första Hibernate-applikation - 3Apache Maven är ett ramverk för att automatiskt bygga projekt baserat på en beskrivning av deras struktur i POM-filer. Hela strukturen för ditt projekt kommer att beskrivas i pom.xml, en fil som IDEA själv kommer att skapa i roten av ditt projekt. I projektinställningarna måste du ange följande Maven-inställningar: groupId och artifactId. I projekt är groupId vanligtvis en beskrivning av företaget eller affärsenheten. Företagets eller webbplatsens domännamn kan gå här. I sin tur är artifactId namnet på projektet. För groupdId kan du ange com.yourNickname.codegym. Detta kommer inte att ha någon effekt på applikationen. För artifactId, välj vilket projektnamn du vill. Versionen kan lämnas oförändrad. Din första Hibernate-applikation - 4På den sista skärmen bekräftar du helt enkelt tidigare inmatade data.Din första Hibernate-applikation - 5Så vi skapade projektet. Nu återstår bara att skriva lite kod och få det att fungera :) Först och främst: om vi vill skapa en applikation som fungerar med en databas så klarar vi oss definitivt inte utan en databas! Ladda ner PostgreSQL härifrån ( jag använder version 9). PostgreSQL har en standardanvändare "postgres" — du måste komma på ett lösenord för det när du installerar. Glöm inte lösenordet. Vi behöver det senare! (I allmänhet är det dålig praxis att använda standarddatabasen i applikationer, men vi kommer att göra det för att minska antalet sår orsakar genom att skapa din egen databas). Om du inte är vän med kommandoraden och SQL-frågor finns det goda nyheter. IntelliJ IDEA ger ett helt passande användargränssnitt för att arbeta med databasen. Din första Hibernate-applikation - 6(finns på IDEAs högra fönster, fliken Databas). För att skapa en anslutning, klicka på "+" och välj vår datakälla (PostgeSQL). Fyll i fälten för användaren och databasen ("postgres" för båda) och ange lösenordet som angavs under installationen av PostgreSQL. Om det behövs, ladda ner Postgres-drivrutinen. Du kan göra detta på samma sida. Klicka på "Testa anslutning" för att verifiera att databasanslutningen är upprättad. Om du ser "Lyckad", gå vidare. Nu ska vi skapa de tabeller vi behöver. Det kommer att finnas totalt två: användare och bilar. Parametrar för användartabellen: Din första Hibernate-applikation - 7Observera att id är den primära nyckeln. Om du inte vet vad primärnyckeln är i SQL, googla det. Det här är viktigt. Inställningar för biltabell: Din första Hibernate-applikation - 8För biltabellen måste du konfigurera en främmande nyckel. Det kommer att tjäna till att länka våra tabeller. Jag rekommenderar att du läser mer om det. Enkelt uttryckt refererar det till en extern tabell, i vårt fall användare. Om en bil tillhör användaren med id = 1, så kommer fältet user_id för bilarna att vara lika med 1. Det är så vi associerar användare med deras bilar i vår applikation. I vår biltabell kommer fältet user_id att fungera som främmande nyckel. Det kommer att referera till id-fältet i användartabellen. Din första Hibernate-applikation - 9Så vi har skapat en databas med två tabeller. Det som återstår är att förstå hur man hanterar det från Java-kod. Vi börjar med filen pom.xml, där vi måste inkludera de nödvändiga biblioteken (i Maven kallas de beroenden). Alla bibliotek lagras i det centrala Maven-förrådet. Biblioteken du anger i pom.xml är tillgängliga för dig att använda i projektet. Din pom.xml ska se ut så här: Din första Hibernate-applikation - 10Inget komplicerat, som du kan se. Vi har bara lagt till två beroenden — för att använda PostgreSQL och Hibernate. Låt oss nu gå vidare till Java-koden. Skapa alla nödvändiga paket och klasser i projektet. För att börja behöver vi en datamodell: klasserna Useroch .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 omit the Column attribute if the name property matches the column name 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 omit the Column attribute if the name property matches the column name 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;
     }
 }
 
 
Som du kan se, klasser har med en massa obskyra kommentarer. Låt oss börja gräva i dem. För oss är huvudkommentaren @Entity. Läs om det på Wikipedia och lär dig allt utantill. Detta är grunden för stiftelsen. Den här anteckningen låter objekt i din Java-klass mappas till en databas. För att en klass ska vara en enhet måste den uppfylla följande krav:
  • Den måste ha en tom konstruktor ( publiceller protected)
  • Det kan inte vara kapslat, ett gränssnitt eller enenum
  • Det kan inte vara finaloch kan inte ha finalfält/egenskaper
  • Den måste ha minst ett @Id-fält.
Kontrollera dina entitetsklasser: de är mycket populära ställen att skjuta dig själv i foten. Det är väldigt lätt att glömma något. Dessutom kan en enhet göra följande:
  • Den kan ha icke-tomma konstruktörer
  • Det kan ärva och gå i arv
  • Den kan ha andra metoder och implementera gränssnitt.
Som du kan se Userär klassen väldigt lik användartabellen. Den har id, name, ochagefält. Anteckningarna ovanför dem behöver ingen särskild förklaring: det är tydligt att @Id indikerar att fältet är en identifierare för objekt av denna klass. @Table-kommentaren ovanför klassen anger namnet på tabellen där objekten är skrivna. Notera kommentaren ovanför åldersfältet: om namnet på fältet i klassen är detsamma som namnet på tabellen kan du utelämna @Column-kommentaren så fungerar det. När det gäller den del som anges i klammerparenteserna ("strategy = GenerationType.IDENTITY"): det finns flera strategier för att generera ID:n. Du kan Google dem, men för vår ansökan behöver du inte bry dig. Huvudsaken är att för våra objekt kommer värdet av id att genereras automatiskt. Följaktligen finns det ingen setter för id, och vi ställer inte in den i konstruktorn heller. Dock,Userklass sticker ut. Den har en lista över bilar! Din första Hibernate-applikation - 11@OneToMany-kommentaren hänger ovanför listan. Det betyder att flera bilar kan motsvara samma objekt i användarklassen. Elementet "mappedBy" refererar till klassens användarfält Auto. Således är bilar och användare relaterade. Elementet orphanRemoval anger om borttagningsåtgärden ska tillämpas på enheter som inte längre har en relation. Om vi ​​tar bort en användare från databasen kommer även alla bilar som är kopplade till den att raderas. I sin tur iAutoklass kommer du att se användarfältet med @ManyToOne-kommentaren (en användare kan motsvara många Autos) och @JoinColumn-kommentaren. Den indikerar vilken kolumn i autos-tabellen som används för att referera till användartabellen (dvs. den främmande nyckeln som vi pratade om tidigare). Efter att ha skapat datamodellen är det dags att lära vårt program att utföra operationer med data i databasen. Låt oss börja med verktygsklassen HibernateSessionFactoryUtil. Den har bara ett jobb — att skapa en sessionsfabrik för vår applikation att fungera med databasen (säg hej till Factory designmönster!). Den vet inte hur man gör något annat.

 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("Исключение!" + e);
             }
         }
         return sessionFactory;
     }
 }
 
I den här klassen skapar vi ett nytt konfigurationsobjekt och skickar det de klasser som det ska behandla som entiteter: Useroch Auto. Var uppmärksam på configuration.getProperties()metoden. Vilka andra fastigheter finns det? Var kommer de ifrån? Egenskaper är vilolägesinställningarna som anges i den speciella hibernate.cfg.xml-filen. Din första Hibernate-applikation - 12Hibernate.cfg.xml läses här: new Configuration().configure(); Som du ser är det inget speciellt med det: det innehåller parametrarna för att ansluta till databasen, såväl som parametern show_sql. Detta krävs för att alla sql-frågor som körs av Hibernate ska visas på konsolen. På så sätt kommer du att se exakt vad Hibernate gör vid varje givet ögonblick, vilket eliminerar all känsla av "magi". Därefter behöver viUserDAOklass. Den bästa praxisen är att programmera genom gränssnitten — skapa ett separat UserDAOgränssnitt och UserDAOImplimplementering, men jag kommer att hoppa över detta för att minska mängden kod. Gör inte detta i riktiga projekt! DAO (data access object) designmönster är ett av de vanligaste. Tanken är enkel – skapa ett applikationslager som bara ansvarar för åtkomst till data, inget mer. Hämta data från databasen, uppdatera data, radera data — det är allt. Läs mer om DAO. Du kommer att använda dataåtkomstobjekt ständigt i ditt arbete. Vad kan vår UserDaoklass göra? Tja, som alla DAO:er kan det bara fungera med data. Hitta en användare med id, uppdatera dess data, ta bort den, få en lista över alla användare från databasen eller spara en ny användare i databasen – det är hela dess funktionalitet.

 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;
     }
 }
 
UserDaos metoder liknar varandra. I de flesta av dem får vi ett Session -objekt (databasanslutningssession) med vår Session Factory, skapar en enda transaktion inom denna session, utför nödvändiga datamanipulationer, sparar resultatet av transaktionen i databasen och stänger sedan sessionen. Metoderna i sig, som du kan se, är ganska enkla. DAO är "hjärtat" i vår ansökan. Vi kommer dock inte att skapa en DAO direkt och anropa dess metoder i vår main()metod. All logik kommer att flyttas till UserServiceklassen.

 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);
     }
 
 
 }
 
 
En tjänst är ett applikationsdatalager som ansvarar för att utföra affärslogik. Om ditt program behöver utföra någon form av affärslogik, gör det det genom tjänster. En tjänst innehåller en UserDaooch anropar DAO-metoder i sina metoder. Det kan tyckas som att vi duplicerar funktioner här (varför inte bara anropa metoderna från ett DAO-objekt?), men med många objekt och komplex logik ger skiktning av applikationen enorma fördelar (det är bra att göra det – kom ihåg detta i framtiden och läs om "applikationslager"). Vår tjänst har enkel logik, men servicemetoder i verkliga projekt innehåller mycket mer än en kodrad :) Nu har vi allt du behöver för att köra applikationen! I main()metoden, låt oss skapa en användare och dess bil, associera den ena med den andra och spara dem i databasen.

 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 ("Jenny", 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);
     }
 }
 
 
Som du kan se har användartabellen sin egen post, och biltabellen har sin egen post. Din första Hibernate-applikation - 13Din första Hibernate-applikation - 14Låt oss försöka byta namn på vår användare. Rensa användartabellen och kör koden

 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 ("Jenny", 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 ("Benny");
         userService.updateUser(user);
     }
 }
 
 
Det fungerar! Din första Hibernate-applikation - 15Vad händer om du tar bort användaren? Rensa användartabellen (autos rensar sig själv) och kör koden

 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 ("Jenny", 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 ("Benny");
         userService.updateUser(user);
         userService.deleteUser(user);
     }
 }
 
 
Och våra bord är helt tomma (var uppmärksam på konsolen - alla förfrågningar som utförs av Hibernate kommer att visas där). Du kan leka med applikationen och prova alla dess funktioner. Till exempel, skapa en användare med bilar, spara den i databasen, titta på det id som tilldelats användaren och försök använda detta id imain()metod för att hämta användaren från databasen och visa en lista över dess bilar på konsolen. Naturligtvis har vi bara sett en liten del av Hibernates funktionalitet. Dess möjligheter är mycket breda, och det har länge varit ett standardverktyg för Java-utveckling. Om du vill studera det i detalj kan jag rekommendera boken "Java Persistence API and Hibernate". Jag recenserade i en tidigare artikel. Jag hoppas att den här artikeln har varit till hjälp för läsarna. Om du har frågor, ställ dem i kommentarerna. Jag svarar gärna :) Glöm inte heller att stötta författaren i tävlingen genom att lägga upp ett "Gilla". Eller ännu bättre — "Love it" :) Lycka till i dina studier!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION