JavaRush /Java Blog /Random-TW /您的第一個 Hibernate 應用程式

您的第一個 Hibernate 應用程式

在 Random-TW 群組發布
在本文中,您將熟悉最受歡迎的 Java 企業框架之一,並使用 Hibernate 建立您的第一個應用程式。從未聽過休眠?也許您聽說過它,但沒有使用過?或嘗試開始,但沒有成功?在這三種情況下,歡迎剪切:) 您的第一個 Hibernate 應用程式 - 1大家好!在這篇文章中,我將討論 Hibernate 框架的主要功能,並幫助您編寫您的第一個迷你應用程式。為此我們需要:
  1. Intellij Idea終極版;從官方網站
    下載並啟動30天試用版。
  2. PostgeSQL 是最受歡迎的現代資料庫管理系統(DBMS)之一;
  3. Maven(已內建於 IDEA 中);
  4. 有點耐心。
本文主要針對從未使用過該技術的人,因此已盡可能減少程式碼量。讓我們開始吧!

什麼是休眠?

這是 ORM 模型最受歡迎的實現之一。物件關係模型描述了軟體物件和資料庫中的記錄之間的關係。當然,Hibernate的功能非常廣泛,但我們將專注於最簡單的功能。我們的目標:建立一個 CRUD 應用程式(建立、讀取、更新、刪除),它將能夠:
  1. 建立使用者(User),以及透過ID在資料庫中搜尋他們,更新他們在資料庫中的數據,並從資料庫中刪除他們。
  2. 將車輛物件(自動)分配給使用者。從資料庫建立、編輯、尋找和刪除汽車。
  3. 此外,應用程式應自動從資料庫中刪除「孤兒」汽車。那些。當刪除使用者時,屬於該使用者的所有汽車也必須從資料庫中刪除。
我們專案的結構如下: 您的第一個 Hibernate 應用程式 - 2如您所見,沒什麼複雜的。6 個類別 + 1 個有配置的檔案。首先,我們在Intellij Idea中建立一個新的maven專案。文件 -> 新項目。從建議的項目類型中,選擇 Maven 並繼續。您的第一個 Hibernate 應用程式 - 3Apache Maven 是一個框架,用於根據 POM 語言檔案中的專案結構描述自動組裝專案。專案的整個結構將在 pom.xml 檔案中描述,IDEA 本身將在專案的根目錄中建立該檔案。在專案設定中,您需要指定 Maven 參數 - groupId 和 artifactId。通常在專案中,groupId 是組織或部門的名稱,組織或專案網站的網域寫在那裡。反過來,artifactId 是專案的名稱。對於groupdId,您可以指定com.вашНикнейм.javarush,這不會以任何方式影響應用程式的操作。對於artifactId,選擇您喜歡的任何項目名稱。您也可以保持版本不變。您的第一個 Hibernate 應用程式 - 4在最後一個畫面上,只需確認您先前輸入的資料即可。您的第一個 Hibernate 應用程式 - 5所以,我們已經創建了項目,剩下的就是編寫程式碼並使其運行:)首先,如果我們想創建一個與資料庫一起使用的應用程序,我們絕對不能沒有資料庫!從這裡下載 PostgreSQL (我使用版本 9)。PostgreSQL 有一個預設使用者“postgres”,您需要在安裝過程中為其建立一個密碼。不要忘記您的密碼,我們稍後會需要它!(一般來說,在應用程式中使用預設資料庫是不好的做法,但為了減少痔瘡的數量,我們將湊合創建自己的資料庫)。如果您不熟悉命令列和 SQL 查詢,那麼有個好消息。Intellij IDEA 提供了一個非常適合使用資料庫的使用者介面。它看起來像這樣:(您的第一個 Hibernate 應用程式 - 6位於 IDEA 右側欄的“資料庫”標籤)要建立連接,請按一下“+”,選擇我們的提供者(PostgeSQL)。在欄位中填寫使用者、資料庫名稱(均為 postgres)並輸入安裝 PostgreSQL 時設定的密碼。如有必要,請下載 Postgres 驅動程序,這可以在同一頁上完成。按一下「測試連線」檢查是否已建立與資料庫的連線。如果您看到“成功”字樣,我們就繼續。現在讓我們建立我們需要的表格。其中有兩個——用戶和汽車。users 表的參數: 您在 Hibernate 上的第一個應用程式 - 7請注意 id 是主鍵。如果您不知道 SQL 中的主鍵是什麼,請 Google 一下,這很重要。autos 表的設定: 您在 Hibernate 上的第一個應用程式 - 8對於汽車,您需要配置外鍵 - 外鍵。它將連結我們的表。我建議你多讀一些關於他的文章;簡而言之,它指的是外部表,在我們的例子中是使用者。如果汽車屬於 id=1 的用戶,則 autos 表的 user_id 欄位中的值將為 1。這就是我們在應用程式中將用戶與其汽車連接起來的方式。在我們的 autos 表中,user_id 欄位將用作外鍵。它將引用用戶表的 id 欄位。 您的第一個 Hibernate 應用程式 - 9因此,我們建立了一個包含兩個表的資料庫。仍然需要了解如何從 Java 程式碼中管理它。我們將從 pom.xml 檔案開始,其中需要包含必要的程式庫(在 Maven 語言中它們稱為依賴項)。所有庫都儲存在中央 Maven 儲存庫中。您可以在專案中使用您在 pom.xml 中指定的那些內容。您的 pom.xml 應該如下所示: 您的第一個 Hibernate 應用程式 - 10正如您所看到的,沒有什麼複雜的。我們只新增了 2 個依賴項 - 用於使用 PostgreSQL 和 Hibernate。 現在讓我們繼續討論 Java 程式碼。為專案建立所有必需的套件和類別。首先,我們需要資料模型 - 類別UserAuto.
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;
    }
}
正如您所看到的,這些類別配備了一堆仍然不清楚的註釋。讓我們開始對付他們。我們的主要註解是@Entity。在維基百科上閱讀並記住所有內容,這是基礎知識的基礎。該註解允許您的類別的 Java 物件與資料庫關聯。一個類別要成為一個實體,它必須滿足以下要求:
  • 必須有一個空的構造函數(publicprotected);
  • 不能嵌套、介面或enum
  • 不能final且不能包含final-fields/properties;
  • 必須至少包含一個 @Id 欄位。
檢查你的實體類,這些是一個非常受歡迎的搬起石頭砸自己腳的地方。很容易忘記一些事情。在這種情況下,該實體可以:
  • 包含非空構造函數;
  • 被繼承,被繼承;
  • 包含其他方法並實作介面。
正如您所看到的,該類別User與用戶表非常相似。有字段id, name, age。位於它們上方的註解不需要太多解釋:已經很清楚@Id表明該欄位是該類別的物件的識別碼。類別上方的 @Table 註解指定寫入物件的表格的名稱。注意age欄位上面的註解:如果類別中的欄位名稱和表格中的欄位名稱相同,則不必加上@Column註解,就可以了。關於括號中指示的「strategy = GenerationType.IDENTITY」:有多種ID產生策略。您可以用谷歌搜尋它,但在我們的應用程式框架內您不必費心。最主要的是我們的物件的 id 會自動生成,所以沒有 id 的 setter,我們也不在建構函式中指定它。然而,該班級在某些方面User仍然很突出。他有一份汽車清單!@OneToMany 註釋出現在清單上方。這意味著使用者類別的一個物件可以對應多台機器。“mappedBY”設定指向該類別的使用者欄位Auto。這樣,機器和使用者就相互連接起來了。orphanRemoval 設定從英文翻譯得很好 - “刪除孤兒”。如果我們從資料庫中刪除一個用戶,與他關聯的所有汽車也將被刪除。反過來,在類別中Auto您將看到帶有 @ManyToOne 註釋(許多 Auto 可以對應於一個 User)和 @JoinColumn 註釋的使用者欄位。它指示透過 autos 表中的哪一列與 users 表發生連接(與我們之前討論的外鍵相同)。建立資料模型後,是時候教導我們的程式對資料庫中的資料執行操作了。讓我們從 HibernateSessionFactoryUtil 實用程式類別開始。它只有一個任務 - 為我們的應用程式建立一個會話工廠來使用資料庫(你好,「工廠!」模式)。他無能為力。
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;
    }
}
在此類中,我們建立一個新的配置物件 Configuration,並將其應視為實體的類別傳遞給它 -UserAuto。講究方法configuration.getProperties()。還有哪些屬性?在哪裡?屬性是 hibernate 如何運作的參數,在特殊檔案 hibernate.cfg.xml 中指定。 您的第一個 Hibernate 應用程式 - 11Hibernate.cfg.xml 讀取如下:new Configuration().configure(); 如您所見,其中沒有什麼特別的 - 用於連接資料庫的參數,以及一個特殊的參數 show_sql。需要它,以便 hibernate 將針對我們的資料庫執行的所有 SQL 查詢輸出到控制台。這樣,您將準確地看到 Hibernate 在每個時刻正在做什麼,並擺脫“魔法”效應。接下來我們需要類別UserDAO。(好的方式是,您需要透過介面進行程式設計 - 建立一個介面UserDAO並單獨實現它UserDAOImpl,但為了減少程式碼量,我將省略這一點。在實際專案中不要這樣做!)。DAO(資料存取物件)是最常見的設計模式之一,「資料存取」。它的含義很簡單——在應用程式中創建一個只負責存取資料的層,而不負責其他任何事情。從資料庫取得資料、更新資料、刪除資料——僅此而已。閱讀有關 DAO 的更多資訊;您將在工作中不斷使用它們。我們班能做什麼呢UserDao?實際上,像所有 DAO 一樣,它只能處理資料。透過 ID 尋找使用者、更新他的資料、刪除他、從資料庫中提取所有使用者的清單或在資料庫中儲存新使用者 - 這就是它的所有功能。
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;
    }
}
這些方法UserDao彼此相似。在大多數情況下,我們使用會話工廠接收一個會話物件(連接到資料庫的會話),在該會話中建立單一事務,執行必要的資料轉換,將事務結果保存在資料庫中並關閉會話。正如您所看到的,這些方法本身非常簡單。DAO 是我們應用程式的「核心」。但是,我們不會直接創建 DAO 並在main(). 所有邏輯都將轉移到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);
    }


}
服務是應用程式中的資料層,負責執行業務邏輯。如果您的程式需要執行某些業務邏輯,它會透過服務來完成。該服務包含其自身UserDao並在其方法中呼叫 DAO 方法。這對您來說可能看起來像是函數的重複(為什麼不只是從dao 物件呼叫方法),但是對於大量物件和複雜邏輯,將應用程式分成層具有巨大的好處(這是一個很好的實踐,請記住此資訊未來並閱讀“應用程式層””)。在我們的服務中,邏輯很簡單,但在實際專案中,服務方法將包含不只一行程式碼:) 現在我們擁有應用程式運行所需的一切!讓我們main()在方法中為他創建一個使用者和機器,將它們相互連接並將它們保存在資料庫中。
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);
    }
}
正如您所看到的,users 表有自己的條目,autos 表也有自己的條目。 您的第一個 Hibernate 應用程式 - 13您的第一個 Hibernate 應用程式 - 14讓我們嘗試重命名我們的用戶。讓我們清除用戶表並運行程式碼
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);
    }
}
作品! 您的第一個 Hibernate 應用程式 - 15如果刪除用戶怎麼辦?讓我們清除用戶表(autos 會自行清除)並執行程式碼
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);
    }
}
我們的表完全是空的(注意控制台,Hibernate 執行的所有查詢都會顯示在那裡)。您可以試用該應用程式並嘗試其所有功能。例如,建立一個擁有機器的用戶,將其儲存到資料庫中,查看分配給它的ID,然後嘗試使用該方法main()透過該id從資料庫中「拉取」用戶並在控制台中顯示他的機器清單。當然,我們只看到了Hibernate的一小部分功能。它的功能非常廣泛,長期以來一直是Java開發的行業標準之一。如果你想詳細研究它,我可以推薦《Java Persistence API and Hibernate》一書,我在之前的一篇文章中評論過這本書。我希望這篇文章對讀者有用。如果您有任何疑問,請在評論中提問,我將很樂意回答:) 另外,不要忘記透過「喜歡」他來支持作者的比賽。或更好 - “我非常喜歡它”:) 祝你學習順利!
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION