CodeGym /Java 博客 /随机的 /您的第一个 Hibernate 应用程序
John Squirrels
第 41 级
San Francisco

您的第一个 Hibernate 应用程序

已在 随机的 群组中发布
在本文中,您将熟悉最流行的 Java 企业框架之一,并创建您的第一个 Hibernate 应用程序。从未听说过 Hibernate?或者,也许您听说过它,但还没有使用过它?或者也许您尝试使用它,但失败了?在所有三种情况下 - 欢迎来到下面的剪辑 :) 你的第一个 Hibernate 应用程序 - 1 大家好!在本文中,我将讨论 Hibernate 框架的主要特性并帮助您编写您的第一个迷你应用程序。为此,我们需要:
  1. IntelliJ IDEA 旗舰版官网
    下载,激活30天试用版。
  2. PostgreSQL - 最流行的现代数据库管理系统 (DBMS) 之一
  3. Maven(已经连接到 IDEA)
  4. 有点耐心。
为了以防万一,我在GitHub(codegym 分支)上发布了应用程序代码。本文主要针对那些以前从未使用过该技术的人,因此我尽量减少了代码量。让我们开始吧!

什么是休眠?

它是最流行的对象关系映射 (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.yourNickname.codegym. 这不会对应用程序产生任何影响。对于 artifactId,选择您喜欢的任何项目名称。版本可以保持不变。 你的第一个 Hibernate 应用程序 - 4在最后一个屏幕上,只需确认之前输入的数据。你的第一个 Hibernate 应用程序 - 5所以,我们创建了这个项目。现在剩下要做的就是编写一些代码并使其运行 :) 首先是第一件事:如果我们想创建一个使用数据库的应用程序,我们绝对不能没有数据库!从这里下载 PostgreSQL (我使用的是版本 9)。PostgreSQL 有一个默认用户“postgres”——您需要在安装时为它想一个密码。不要忘记密码。我们稍后会需要它!(一般来说,在应用程序中使用默认数据库是不好的做法,但我们会这样做是为了通过创建您自己的数据库来减少导致溃疡的数量)。如果您不熟悉命令行和 SQL 查询,那么有个好消息。IntelliJ IDEA 提供了一个完全适合使用数据库的用户界面。 你的第一个 Hibernate 应用程序 - 6(位于 IDEA 的右窗格中,数据库选项卡)。要创建连接,请单击“+”并选择我们的数据源 (PostgeSQL)。填写用户和数据库字段(两者均为“postgres”)并输入在安装 PostgreSQL 期间设置的密码。如有必要,请下载 Postgres 驱动程序。您可以在同一页面上执行此操作。单击“测试连接”以验证数据库连接是否已建立。如果您看到“成功”,则继续。现在我们将创建我们需要的表。一共有两个:用户和汽车。users 表的参数: 你的第一个 Hibernate 应用程序 - 7请注意,id 是主键。如果您不知道 SQL 中的主键是什么,请谷歌一下。这个很重要。汽车表的设置: 你的第一个 Hibernate 应用程序 - 8对于autos表,需要配置一个外键。它将用于链接我们的表格。我建议您阅读更多相关信息。简而言之,它引用了一个外部表,在我们的例子中是用户。如果汽车属于 id = 1 的用户,则汽车的 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 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;
     }
 }
 
 
如您所见,类带有一堆晦涩的注释。让我们开始深入研究它们。对于我们来说,主要的注解是@Entity。在维基百科上阅读它并记住它。这是基础中的基础。这个注解可以让你的 Java 类的对象映射到数据库。要使类成为实体,它必须满足以下要求:
  • 它必须有一个空的构造函数(publicprotected
  • 它不能嵌套,接口或enum
  • 它不能final也不能有final字段/属性
  • 它必须至少有一个@Id 字段。
检查您的实体类:它们是非常受欢迎的搬起石头砸自己脚的地方。很容易忘记一些事情。此外,实体可以执行以下操作:
  • 它可以有非空的构造函数
  • 它可以继承和被继承
  • 它可以有其他方法和实现接口。
如您所见,该类User与用户表非常相似。它有id,nameage领域。位于其上方的注解不需要任何特别的解释:很明显,@Id 表示该字段是该类对象的标识符。类上方的@Table 注解表示写入对象的表名。请注意年龄字段上方的注释:如果类中的字段名称与表名相同,则可以省略@Column 注解,它会起作用。至于大括号中指示的部分(“strategy = GenerationType.IDENTITY”):有几种生成ID的策略。您可以用 Google 搜索它们,但对于我们的应用程序,无需费心。最主要的是,对于我们的对象,id 的值将自动生成。因此,没有 id 的 setter,我们也不在构造函数中设置它。然而,User类确实脱颖而出。它有一个汽车清单! 你的第一个 Hibernate 应用程序 - 11@OneToMany 注释挂在列表上方。就是说几辆车可以对应同一个User类的对象。“mappedBy”元素指的是类的用户字段Auto。因此,汽车和用户是相关的。orphanRemoval 元素指示是否将删除操作应用于不再有关系的实体。如果我们从数据库中删除一个用户,那么与其关联的所有汽车也将被删除。反过来,在Auto类,你会看到带有@ManyToOne注解(一个User可以对应多个Auto)和@JoinColumn注解的user字段。它指示 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("Исключение!" + e);
             }
         }
         return sessionFactory;
     }
 }
 
在这个类中,我们创建了一个新的 Configuration 对象,并将它应该视为实体的类传递给它:UserAuto。注意方法configuration.getProperties()。还有哪些其他属性?他们来自哪里?属性是特殊 hibernate.cfg.xml 文件中指示的休眠设置。 你的第一个 Hibernate 应用程序 - 12Hibernate.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 ("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);
     }
 }
 
 
如您所见,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 ("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);
     }
 }
 
 
有用! 你的第一个 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 ("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);
     }
 }
 
 
我们的表完全是空的(注意控制台——Hibernate 执行的所有请求都将显示在那里)。您可以试用该应用程序并尝试其所有功能。比如创建一个有cars的用户,保存在数据库中,查看分配给用户的id,尝试在main()方法从数据库中获取用户并在控制台上显示其汽车列表。当然,我们只看到了 Hibernate 功能的一小部分。它的功能非常广泛,长期以来一直是 Java 开发的标准行业工具。如果想深入研究,可以推荐《Java Persistence API and Hibernate》这本书。我在之前的文章中回顾过。我希望这篇文章对读者有所帮助。如果您有任何疑问,请在评论中提问。我很乐意回答 :) 另外,不要忘记通过张贴“赞”来支持作者参加比赛。或者更好——“喜欢它”:)祝你学业顺利!
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION