大家好,今天,我们将讨论 Hibernate 和 JPA 架构。
在开始我们的文章之前,我想回答一个重要的问题:为什么我们需要使用 Hibernate、Eclipse Link、EF core 等 ORM 工具?
事实上,这是一个非常好的问题。我们开发人员通常有几个月的时间来创建一个新项目,或者有两周的时间来为我们的业务逻辑添加新功能。当我们考虑这个时间表时,为我们的业务逻辑编写 SQL 代码需要花费时间;因此,ORM 工具的创建者认为这将使开发人员的 CRUD 操作更容易。
ORM工具可以防止重复的SQL代码和代码复杂性,并提供代码的可读性和清晰度。
另一方面,生活中每件好事都是有代价的。ORM 工具就是其中之一。不幸的是,我们直到面对结果才意识到我们付出了代价,就像在生活中一样。显然,这些工具在后台执行许多操作,例如映射和转换 SQL 命令。这就是大多数 ORM 工具的性能比本机 SQL 查询更差的原因。
鉴于这些想法,这完全取决于需求。如果您拥有大型系统和复杂关系,则应该选择本机查询。这里的基本问题是您的优先事项是什么?是性能还是清晰度和可读性?
最后,缓存机制是选择 Hibernate 实体缓存的最大原因,它使以数据为中心的应用程序具有高性能,即使应用程序远离数据库。
什么是 Hibernate
Hibernate 是一个 ORM(对象关系映射)工具,它提供了一个框架将 OOP 领域模型映射到 Spring Boot 应用程序中的关系数据库表。
什么是 ORM
ORM 是一种使用 OOP 语言与数据库交互的技术。因此,它简化了创建、读取、更新和删除等不同的数据库操作。
什么是 JPA 和 Spring Data JPA
JPA 是一种从非易失性存储系统中持久保存和检索信息的标准,将 Java 对象映射到数据库中的表。
- 实体管理器 API 可以从数据库中持久化、更新、检索或删除对象。
- 实体管理器 API 可以提供 ORM,而无需 JDBC 或 SQL 代码。
- JPA 提供了一种查询语言,无需编写大量 SQL 查询即可检索对象
Spring Data JPA 使用 JPA 将数据存储在关系数据库中。Hibernate 是 JPA 的实现。
可以使用 Hibernate、Explips Link 或任何其他 JPA 提供程序。Spring Data 不是实现或 JPA 提供程序;它只是一种抽象,可以显著减少样板代码。
JPA不是一个框架。它是一个标准和概念。
Hibernate 是 JPA 提供程序,而 Spring Data JPA 不是 JPA 提供程序。它只是一个抽象,可以与 Hibernate、Eclipse Link 等一起使用。
存储库模式
基本上,存储库模式在 BaseRepository 类中管理基本的 CRUD 操作。让我在图中讨论一下这一点。
存储库模式涉及创建一个通用 BaseRepository 接口,其中包含数据库的基本 CRUD 操作。除了此接口之外,还有一个具体的 BaseRepositoryImpl 类,它使用 EntityManager 实现这些操作。
为了对实体执行这些常见操作,我们为 User 实体创建抽象类(如 UserRepository)。这些抽象类定义与实体相关的自定义操作。此外,我们还有具体类(如 UserRepositoryImpl),它们扩展了 BaseRepositoryImpl 和相应的抽象 UserRepository。
这种方法有几个好处。首先,它将常见的数据库操作封装在 BaseRepository 中,从而提高代码重用性和可维护性。其次,通过扩展 UserRepository 等抽象类,我们可以定义实体操作,同时从基础存储库继承通用 CRUD 功能。总体而言,这种结构促进了应用程序内数据库交互的模块化、抽象和高效管理。
让我们看看下面的代码
java
package com.beratyesbek.basicjparepositorypattern.repository.base;
import com.beratyesbek.basicjparepositorypattern.model.BaseEntity;
import java.util.List;
public interface BaseRepository<E extends BaseEntity, I> {
void save(E entity);
void update(E entity, I id);
List<E> findAll();
E findById(I id);
}
java
package com.beratyesbek.basicjparepositorypattern.repository.base;
import com.beratyesbek.basicjparepositorypattern.model.BaseEntity;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public class BaseRepositoryImpl<E extends BaseEntity, I> implements BaseRepository<E, I> {
@PersistenceContext
private EntityManager entityManager;
private final Class<E> entityClass;
public BaseRepositoryImpl(Class<E> entityClass) {
this.entityClass = entityClass;
}
@Override
@Transactional
public void save(E entity) {
entityManager.persist(entity);
}
@Override
@Transactional
public void update(E entity, I id) {
E result = entityManager.find((Class<E>) entity.getClass(), id);
if (result != null) {
entityManager.merge(result);
}
}
@Override
@Transactional
public List<E> findAll() {
return entityManager.createQuery("SELECT e FROM " + entityClass.getSimpleName() + " e", entityClass).getResultList();
}
@Override
@Transactional
public E findById(I id) {
return entityManager.find(entityClass, id);
}
}
java
package com.beratyesbek.basicjparepositorypattern.repository;
import com.beratyesbek.basicjparepositorypattern.model.User;
import com.beratyesbek.basicjparepositorypattern.repository.base.BaseRepository;
public interface UserRepository extends BaseRepository<User, Integer> {
}
java
package com.beratyesbek.basicjparepositorypattern.repository;
import com.beratyesbek.basicjparepositorypattern.model.User;
import com.beratyesbek.basicjparepositorypattern.repository.base.BaseRepositoryImpl;
import org.springframework.stereotype.Component;
@Component
public class UserRepositoryImpl extends BaseRepositoryImpl<User, Integer> implements UserRepository{
public UserRepositoryImpl() {
super(User.class);
}
}
JPA 存储库模式
JPA 存储库模式包含使我们更方便的数据库操作。同时,JPA 存储库可以与 Hibernate、Eclipse Link 等配合使用。它只是一个抽象。
JPA 在底层使用了类似的存储库模式。
如您所见,我们有实体,每个实体都有自己的存储库,这些存储库已在后台从 JpaRepository 接口扩展。JPA 存储库与 EntityManager 配合使用,它与 Hibernate 配合使用,后者与 JDBC 配合使用。
Hibernate 具有分层架构,可帮助用户执行操作而无需接触任何底层内容。Hibernate 为持久性服务提供 ORM。
配置对象
通常,配置对象在应用程序生命周期内创建一次;此外,它是第一个创建的 Hibernate 对象。它代表数据库和其他配置。
SessionFactory 对象
SessionFactory 对象是使用配置对象创建的。SessionFactory 对象是一个重量级对象。它通常在应用程序初始化时创建。此外,SessionFactory 是一个线程安全的对象,并由其他线程使用。
会话对象
会话对象用于提供数据库连接。它被设计为轻量级对象,每次需要数据库交互时都会创建它。此外,SessionObject 不建议保留以供以后使用,因为它不是线程安全的。
交易对象
每当我们想要对实体执行操作,根据结果提交或回滚更改时,都会使用 Transaction 对象。
查询对象
查询对象使用 SQL 或 HQL(Hibernate 查询语言)从数据库中检索数据。通过调用属于 Session 对象的 createQuery 方法获取查询实例。
Criteria 对象
它通常使用从 Session 对象获取的动态查询。
休眠代理
休眠涉及两种获取类型的策略:延迟加载和预先加载。
想想看:您有拥有数千个登录历史记录的用户。显然,当您想要从数据库中检索用户时,由于关联的登录历史记录实体,大量数据将付出代价。这就是为什么 Hibernate 使用延迟加载作为默认策略,这意味着检索数据直到需要它为止。这将提高应用程序的性能。Hibernate 使用代理实体来管理这种现象。
总之,Hibernate 代理是一种避免在需要之前检索大量数据的方法。
惰性获取类型
当业务逻辑从数据库加载用户时,JPA 会加载其 ID 名称和电子邮件。但是,登录历史记录仅在调用时加载。如果实体包含如此多涉及大量数据的关系,则 Lazy Fetch 类型将提高应用程序的性能。
即时获取类型
当业务逻辑从数据库加载用户时,JPA 会加载其 ID、姓名、电子邮件以及所有相关实体,例如登录历史记录。这会以牺牲应用程序性能为代价,并且会消耗内存资源。预加载对于一对一实体关系非常有用。