JavaRush /Java 博客 /Random-ZH /您的第一个 Hibernate 应用程序

您的第一个 Hibernate 应用程序

已在 Random-ZH 群组中发布
在本文中,您将熟悉最流行的 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