CodeGym /Java-blogg /Tilfeldig /Din første Hibernate-applikasjon
John Squirrels
Nivå
San Francisco

Din første Hibernate-applikasjon

Publisert i gruppen
I denne artikkelen vil du bli kjent med et av de mest populære bedriftsrammeverkene for Java og lage din første Hibernate-applikasjon. Aldri hørt om Hibernate? Eller kanskje du har hørt om det, men ikke brukt det? Eller kanskje du prøvde å bruke den, men mislyktes? I alle tre tilfellene - velkommen til under snittet :) Din første Hibernate-applikasjon - 1 Hei alle sammen! I denne artikkelen skal jeg snakke om Hibernate-rammeverkets hovedfunksjoner og hjelpe deg med å skrive din første miniapplikasjon. Til dette trenger vi:
  1. IntelliJ IDEA Ultimate Edition
    Last den ned fra den offisielle nettsiden og aktiver 30-dagers prøveversjon.
  2. PostgreSQL - et av de mest populære moderne databasestyringssystemene (DBMS)
  3. Maven (allerede koblet til IDEA)
  4. Litt tålmodighet.
Bare i tilfelle, la jeg ut applikasjonskoden på GitHub (codegym-grenen). Artikkelen er først og fremst rettet mot de som aldri har jobbet med denne teknologien før, så jeg har minimert mengden kode. La oss komme i gang!

Hva er Hibernate?

Det er en av de mest populære implementeringene av objektrelasjonell kartlegging (ORM). En objektrelasjonell kartlegging definerer forholdet mellom programvareobjekter og databaseposter. Hibernate har selvfølgelig veldig bred funksjonalitet, men vi vil fokusere på de enkleste funksjonene. Målet vårt er å lage en CRUD-applikasjon (Create, Read, Update, Delete) som vil kunne:
  1. Opprett brukere (Bruker), søk etter dem i databasen etter ID, oppdater dataene deres i databasen og slett dem fra databasen.
  2. Tilordne bilobjekter (Auto) til brukere. Opprett, oppdater, finn og slett biler fra databasen.
  3. I tillegg skal applikasjonen automatisk fjerne "eierløse" biler fra databasen. Med andre ord, når en bruker slettes, må alle biler som tilhører den brukeren også slettes fra databasen.
Prosjektet vårt vil være strukturert slik: Din første Hibernate-applikasjon - 2Som du kan se, ingenting komplisert. 6 klasser + 1 fil med konfigurasjoner. Først oppretter du et nytt Maven-prosjekt i IntelliJ IDEA. Fil -> Nytt prosjekt. Velg Maven blant de foreslåtte prosjekttypene og gå til neste trinn. Din første Hibernate-applikasjon - 3Apache Maven er et rammeverk for automatisk å bygge prosjekter basert på en beskrivelse av deres struktur i POM-filer. Hele strukturen til prosjektet ditt vil bli beskrevet i pom.xml, en fil som IDEA selv vil lage i roten til prosjektet. I prosjektinnstillingene må du spesifisere følgende Maven-innstillinger: groupId og artifactId. I prosjekter er groupId vanligvis en beskrivelse av bedriften eller forretningsenheten. Domenenavnet til bedriften eller nettstedet kan gå her. I sin tur er artifactId navnet på prosjektet. For groupdId kan du skrive inn com.yourNickname.codegym. Dette vil ikke ha noen innvirkning på applikasjonen. For artifactId, velg et prosjektnavn du liker. Versjonen kan stå uendret. Din første Hibernate-applikasjon - 4På det siste skjermbildet, bekreft ganske enkelt de tidligere angitte dataene.Din første Hibernate-applikasjon - 5Så vi laget prosjektet. Nå gjenstår det bare å skrive litt kode og få det til å fungere :) Første ting først: hvis vi vil lage en applikasjon som fungerer med en database, kan vi definitivt ikke klare oss uten en database! Last ned PostgreSQL herfra (jeg bruker versjon 9). PostgreSQL har en standardbruker "postgres" - du må finne et passord for det når du installerer. Ikke glem passordet. Vi trenger det senere! (Generelt sett er det dårlig praksis å bruke standarddatabasen i applikasjoner, men vi vil gjøre det for å redusere antall sårårsaker ved å lage din egen database). Hvis du ikke er venner med kommandolinjen og SQL-spørringer, er det gode nyheter. IntelliJ IDEA gir et helt egnet brukergrensesnitt for å jobbe med databasen. Din første Hibernate-applikasjon - 6(plassert i IDEAs høyre rute, Database-fanen). For å opprette en tilkobling, klikk "+" og velg vår datakilde (PostgeSQL). Fyll ut feltene for brukeren og databasen ("postgres" for begge) og skriv inn passordet som ble satt under installasjonen av PostgreSQL. Last om nødvendig ned Postgres-driveren. Du kan gjøre dette på samme side. Klikk "Test tilkobling" for å bekrefte at databasetilkoblingen er etablert. Hvis du ser "Vellykket", så gå videre. Nå skal vi lage tabellene vi trenger. Det vil være totalt to: brukere og biler. Parametere for brukertabellen: Din første Hibernate-applikasjon - 7Merk at id er primærnøkkelen. Hvis du ikke vet hva primærnøkkelen er i SQL, Google det. Dette er viktig. Innstillinger for biltabell: Din første Hibernate-applikasjon - 8For biltabellen må du konfigurere en fremmednøkkel. Det vil tjene til å koble sammen tabellene våre. Jeg anbefaler at du leser mer om det. Enkelt sagt refererer det til en ekstern tabell, i vårt tilfelle brukere. Hvis en bil tilhører brukeren med id = 1, så vil bruker_id-feltet til autoene være lik 1. Dette er hvordan vi assosierer brukere med bilene deres i vår applikasjon. I vår biltabell vil feltet user_id fungere som fremmednøkkel. Det vil referere til id-feltet til brukertabellen. Din første Hibernate-applikasjon - 9Så vi har laget en database med to tabeller. Det som gjenstår er å forstå hvordan man administrerer det fra Java-kode. Vi starter med pom.xml-filen, der vi må inkludere de nødvendige bibliotekene (i Maven kalles de avhengigheter). Alle bibliotekene er lagret i det sentrale Maven-depotet. Bibliotekene du spesifiserer i pom.xml er tilgjengelige for deg å bruke i prosjektet. Din pom.xml skal se slik ut: Din første Hibernate-applikasjon - 10Ingenting komplisert, som du kan se. Vi la bare til 2 avhengigheter - for bruk av PostgreSQL og Hibernate. La oss nå gå videre til Java-koden. Lag alle nødvendige pakker og klasser i prosjektet. For å starte trenger vi en datamodell: klassene Userog 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, har klasser med en haug med obskure merknader. La oss begynne å grave i dem. For oss er hovedkommentaren @Entity. Les om det på Wikipedia og lær alt utenat. Dette er grunnlaget for stiftelsen. Denne merknaden lar objekter i Java-klassen din tilordnes til en database. For at en klasse skal være en enhet, må den tilfredsstille følgende krav:
  • Den må ha en tom konstruktør ( publiceller protected)
  • Det kan ikke være nestet, et grensesnitt eller enenum
  • Det kan ikke være finalog kan ikke ha finalfelt/egenskaper
  • Den må ha minst ett @Id-felt.
Sjekk entitetsklassene dine: de er veldig populære steder å skyte deg selv i foten. Det er veldig lett å glemme noe. Dessuten kan en enhet gjøre følgende:
  • Den kan ha ikke-tomme konstruktører
  • Det kan arve og gå i arv
  • Den kan ha andre metoder og implementere grensesnitt.
Som du kan se, Userer klassen veldig lik brukertabellen. Den har id, name, ogageEnger. Merknadene over dem trenger ingen spesiell forklaring: det er tydelig at @Id indikerer at feltet er en identifikator for objekter av denne klassen. @Table-kommentaren over klassen indikerer navnet på tabellen der objektene er skrevet. Legg merke til kommentaren over aldersfeltet: hvis navnet på feltet i klassen er det samme som navnet på tabellen, kan du utelate @Column-kommentaren og det vil fungere. Når det gjelder delen som er angitt i klammerparentesene ("strategi = GenerationType.IDENTITY"): det er flere strategier for å generere IDer. Du kan Google dem, men for vår applikasjon trenger du ikke bry deg. Hovedsaken er at for våre objekter vil verdien av id genereres automatisk. Følgelig er det ingen setter for id, og vi setter den heller ikke i konstruktøren. Derimot,Userklasse skiller seg ut. Den har en liste over biler! Din første Hibernate-applikasjon - 11@OneToMany-kommentaren henger over listen. Det betyr at flere biler kan tilsvare samme objekt i brukerklassen. "mappedBy"-elementet refererer til brukerfeltet til klassen Auto. Dermed henger biler og brukere sammen. OrphanRemoval-elementet angir om fjerningsoperasjonen skal brukes på enheter som ikke lenger har en relasjon. Hvis vi sletter en bruker fra databasen, så slettes også alle bilene som er knyttet til den. På sin side, iAutoklasse, vil du se brukerfeltet med @ManyToOne-kommentaren (én bruker kan tilsvare mange Autos) og @JoinColumn-kommentaren. Den indikerer hvilken kolonne i autos-tabellen som brukes til å referere til brukertabellen (dvs. fremmednøkkelen som vi snakket om tidligere). Etter å ha laget datamodellen, er det på tide å lære programmet vårt å utføre operasjoner med dataene i databasen. La oss starte med HibernateSessionFactoryUtil-verktøyklassen. Den har bare én jobb - å lage en sesjonsfabrikk for applikasjonen vår for å fungere med databasen (si hei til fabrikkdesignmønsteret!). Den vet ikke hvordan den skal gjøre noe annet.

 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 denne klassen lager vi et nytt konfigurasjonsobjekt, og sender det klassene som det skal behandle som entiteter: Userog Auto. Vær oppmerksom på configuration.getProperties()metoden. Hvilke andre eiendommer er det? Hvor kommer de fra? Egenskaper er dvalemodusinnstillingene som er angitt i den spesielle hibernate.cfg.xml-filen. Din første Hibernate-applikasjon - 12Hibernate.cfg.xml leses her: new Configuration().configure(); Som du ser, er det ikke noe spesielt med den: den inneholder parameterne for å koble til databasen, samt parameteren show_sql. Dette er nødvendig for at alle sql-spørringer utført av Hibernate skal vises på konsollen. På denne måten vil du se nøyaktig hva Hibernate gjør til enhver tid, og eliminere enhver følelse av "magi". Deretter trenger viUserDAOklasse. Den beste praksisen er å programmere gjennom grensesnittene - lag et eget UserDAOgrensesnitt og UserDAOImplimplementering, men jeg vil hoppe over dette for å redusere mengden kode. Ikke gjør dette i ekte prosjekter! DAO-designmønsteret (datatilgangsobjekt) er et av de vanligste. Ideen er enkel - lag et applikasjonslag som kun er ansvarlig for tilgang til data, ikke noe mer. Hent data fra databasen, oppdater data, slett data – det er det. Studer mer om DAO. Du vil bruke datatilgangsobjekter konstant i arbeidet ditt. UserDaoHva kan klassen vår gjøre? Vel, som alle DAO-er, kan det bare fungere med data. Finn en bruker etter id, oppdater dataene, slett dem, få en liste over alle brukere fra databasen, eller lagre en ny bruker i databasen – det er hele funksjonaliteten.

 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;
     }
 }
 
UserDaosine metoder ligner på hverandre. I de fleste av dem får vi et Session- objekt (databasetilkoblingsøkt) ved å bruke Session Factory, oppretter en enkelt transaksjon i denne sesjonen, utfører nødvendige datamanipulasjoner, lagrer resultatet av transaksjonen i databasen, og lukker deretter økten. Metodene i seg selv, som du kan se, er ganske enkle. DAO er "hjertet" i søknaden vår. Vi vil imidlertid ikke opprette en DAO direkte og kalle metodene i main()metoden vår. All logikk vil bli flyttet til 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 tjeneste er et applikasjonsdatalag som er ansvarlig for å utføre forretningslogikk. Hvis programmet ditt trenger å utføre en slags forretningslogikk, gjør det det gjennom tjenester. En tjeneste inneholder en UserDaoog kaller DAO-metoder i sine metoder. Det kan virke som om vi dupliserer funksjoner her (hvorfor ikke bare kalle metodene fra et DAO-objekt?), men med mange objekter og kompleks logikk gir lagdeling av applikasjonen store fordeler (det er god praksis – husk dette i fremtiden og les om "applikasjonslag"). Tjenesten vår har enkel logikk, men tjenestemetoder i virkelige prosjekter inneholder mye mer enn én kodelinje :) Nå har vi alt du trenger for å kjøre applikasjonen! I main()metoden, la oss lage en bruker og dens bil, assosiere den ene med den andre og lagre 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 brukertabellen sin egen post, og biltabellen har sin egen post. Din første Hibernate-applikasjon - 13Din første Hibernate-applikasjon - 14La oss prøve å gi nytt navn til brukeren vår. Tøm brukertabellen og utfø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 fungerer! Din første Hibernate-applikasjon - 15Hva om du sletter brukeren? Tøm brukertabellen (autos vil tømme seg selv) og utfø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);
     }
 }
 
 
Og bordene våre er helt tomme (vær oppmerksom på konsollen - alle forespørslene utført av Hibernate vil bli vist der). Du kan leke med applikasjonen og prøve ut alle funksjonene. Opprett for eksempel en bruker med biler, lagre den i databasen, se på ID-en som er tildelt brukeren, og prøv å bruke denne ID-en imain()metode for å hente brukeren fra databasen og vise en liste over bilene på konsollen. Selvfølgelig har vi bare sett en liten del av Hibernates funksjonalitet. Dens evner er svært brede, og den har lenge vært et standard industriverktøy for Java-utvikling. Hvis du vil studere det i detalj, kan jeg anbefale boken "Java Persistence API and Hibernate". Jeg anmeldte i en tidligere artikkel. Jeg håper denne artikkelen har vært nyttig for leserne. Hvis du har spørsmål, spør dem i kommentarene. Jeg svarer gjerne :) Ikke glem å støtte forfatteren i konkurransen ved å legge ut et "liker". Eller enda bedre — "Love it" :) Lykke til i studiene!
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION