Java Persistence API (JPA) 之 EntityManager

EntityManager 是 Java Persistence API (JPA) 中的核心接口之一,它是应用程序与持久化层(即数据库)之间进行交互的主要入口点。EntityManager 提供了一系列方法,用于执行与对象-关系映射(ORM)相关的操作,如创建、读取、更新、删除(CRUD)实体对象,以及执行查询等。以下是 EntityManager 接口的主要职责和功能:

  • 实体管理:

persist(): 将一个新创建的实体对象添加到持久化上下文中,标记为待保存状态。当事务提交时,该实体将被保存到数据库中。
merge(): 更新一个已在数据库中存在的实体对象,或者将一个游离(detached)状态的实体重新与持久化上下文关联并同步其状态。
remove(): 从持久化上下文中移除一个实体,并在事务提交时将其从数据库中删除。
find(): 根据给定的实体类和主键值从数据库中加载一个实体对象到持久化上下文。

  • 查询操作:

createQuery(): 创建一个基于JPA Criteria API的查询对象,用于执行复杂的类型安全查询。
createNamedQuery(): 根据预定义的命名查询(在实体类或XML元数据中声明)创建一个查询对象。
createNativeQuery(): 创建一个基于原生SQL查询的对象,返回结果可以映射到实体类或基本类型。

  • 事务管理:

EntityManager 与 Transaction 接口紧密协作,提供对数据库事务的支持。通常通过 EntityManager.getTransaction() 获取当前事务,并使用 begin(), commit(), rollback() 等方法进行事务控制。

  • 缓存管理:

EntityManager 内部维护了一级缓存(Persistence Context),它是一个对象的集合,代表了当前与数据库的一致视图。对实体的操作首先发生在一级缓存中,只有在特定时刻(如事务提交)才会与数据库进行同步。

  • 锁定与版本控制:

提供方法如 lock() 用于对实体进行悲观或乐观锁定,以防止并发修改冲突。
支持实体的版本属性管理,自动检测并处理并发更新问题。

  • 其他辅助功能:

flush(): 强制将当前持久化上下文中所有未同步的更改立即写入数据库。
clear(): 清除持久化上下文中的所有实体,释放资源。
close(): 关闭 EntityManager 实例,释放与数据库的连接。
通常情况下,EntityManager 由 EntityManagerFactory 创建,并在每次操作完成后关闭或由依赖注入框架(如Spring)管理其生命周期。在实际应用中,推荐使用依赖注入和Spring Data JPA的JpaRepository、CrudRepository等更高层次的抽象来操作 EntityManager,以简化开发并更好地融入Spring生态系统。
        总结来说,EntityManager 是 JPA 提供的一个关键接口,它封装了与数据库交互的所有必要操作,使得开发者可以通过面向对象的方式来操作数据库,而无需直接编写SQL。通过合理使用 EntityManager,可以实现对数据库的高效、类型安全且易于维护的访问。

让我们对 EntityManager 的一些核心功能和使用细节进行更深入的探讨:

实体管理

  • 持久化新实体(persist())

当调用 entityManager.persist(entity) 时,entity 被标记为新创建的、待持久化的状态。这意味着它会被加入到当前 EntityManager 的一级缓存(Persistence Context)中。
实际的数据库插入操作并不立即发生,而是延迟到事务提交时。这样可以批量处理多个插入操作,提高效率。
如果实体已经存在于数据库中(即具有唯一标识符),persist() 方法不会抛出异常,但也不会执行任何操作。对于已存在的实体,应使用 merge() 方法。

  • 更新实体(merge())

entityManager.merge(entity) 用于将一个游离(detached)状态的实体重新与持久化上下文关联,并同步其状态。游离状态的实体是指那些曾经是持久化状态,但由于 EntityManager 关闭或清除等原因不再与任何 EntityManager 关联的实体。
merge() 方法会查找数据库中是否存在与传入实体具有相同标识符的记录。如果存在,将实体的属性值合并到数据库中的记录,并返回一个与当前 EntityManager 关联的实体副本。如果不存在,则相当于执行一次 persist() 操作。
merge() 后返回的实体是持久化上下文中的最新版本,应使用这个返回值进行后续操作,而不是原来的传入实体。

  • 删除实体(remove())

调用 entityManager.remove(entity) 可以从持久化上下文中移除一个实体,并在事务提交时将其从数据库中删除。
删除操作同样发生在事务提交时,如果在事务提交前调用 em.find() 加载同主键的实体,仍能获取到该实体。这是因为删除操作尚未传播到数据库。
如果尝试删除一个未被管理(非持久化状态)的实体,remove() 方法会抛出 IllegalArgumentException。
查询操作
基于Criteria API的查询(createQuery())
entityManager.createQuery(criteraQuery) 使用JPA Criteria API创建一个类型安全的查询对象。Criteria API允许通过程序构造查询条件,适用于动态构建查询的情况。
查询结果可以是实体列表、单个实体或标量值。例如:

  CriteriaBuilder cb = entityManager.getCriteriaBuilder();
  CriteriaQuery<User> cq = cb.createQuery(User.class);
  Root<User> user = cq.from(User.class);
  cq.where(cb.equal(user.get("username"), "john.doe"));
  List<User> users = entityManager.createQuery(cq).getResultList();
  

基于命名查询(createNamedQuery())
entityManager.createNamedQuery(queryName) 根据在实体类或XML元数据中预先定义的命名查询字符串创建查询对象。

命名查询的优势在于将SQL-like查询语句与Java代码分离,提高了可读性和可维护性。例如,在实体类中声明:

  @Entity
  @NamedQueries({
      @NamedQuery(name = "User.findByUsername", query = "SELECT u FROM User u WHERE u.username = :username")
  })
  public class User {
      // ...
  }
  
然后在代码中使用:  
TypedQuery<User> query = entityManager.createNamedQuery("User.findByUsername", User.class);
  query.setParameter("username", "john.doe");
  List<User> users = query.getResultList();
  

原生SQL查询(createNativeQuery())
entityManager.createNativeQuery(sql, resultClass) 或 createNativeQuery(sql, resultSetMapping) 允许直接使用原生SQL语句进行查询。
结果可以映射到实体类或通过ResultSetMapping定义的映射关系。原生查询在需要利用数据库特定功能(如存储过程、特定SQL语法)时非常有用。
事务管理
JPA 本身并不直接管理事务,而是通过与底层JTA(Java Transaction API)或JDBC事务协调来实现事务支持。
通常通过 entityManager.getTransaction() 获取当前事务对象,然后使用 begin(), commit(), rollback() 等方法进行事务控制。例如:

  EntityTransaction tx = entityManager.getTransaction();
  tx.begin();
  try {
      // 执行数据库操作...
      tx.commit();
  } catch (Exception e) {
      tx.rollback();
      throw e;
  }
  

        在Spring环境下,通常推荐使用@Transactional注解或PlatformTransactionManager来管理事务,让Spring容器负责事务的开启、提交和回滚,避免在业务代码中显式处理事务。

  • 缓存管理

EntityManager 内部维护的一级缓存(Persistence Context)是一个对象的集合,它代表了当前与数据库的一致视图。对实体的操作首先发生在一级缓存中,只有在特定时刻(如事务提交)才会与数据库进行同步。
一级缓存的作用包括:
读取缓存:当通过 find()、getReference() 或查询方法加载实体时,如果一级缓存中已有相同标识符的实体,直接返回缓存中的实体,避免重复从数据库查询。
写入缓存:对实体的持久化操作(如 persist()、merge()、remove())先更新一级缓存中的实体状态,延迟到事务提交时再同步到数据库。
实体状态跟踪:管理实体的瞬时(transient)、持久(persistent)、游离(detached)和删除(removed)四种状态,确保实体状态的一致性。
锁定与版本控制

  • 悲观锁定(lock())

entityManager.lock(entity, LockModeType) 用于对实体进行悲观锁定,防止并发修改冲突。
LockModeType.WRITE:在执行查询时立即获取写锁,阻止其他事务读取或修改该实体,直到当前事务结束。
LockModeType.READ:在执行查询时立即获取读锁,阻止其他事务获取写锁,但允许其他事务获取读锁。
悲观锁定可能导致数据库死锁,应谨慎使用,并确保在短时间内完成操作并提交事务。

  • 乐观锁定

JPA支持乐观锁定,通常通过在实体类中添加一个版本字段(如 @Version 注解的 Long version)实现。
当两个事务同时修改同一实体时,提交时会检查版本号是否与开始时一致。如果不一致(即有其他事务修改过该实体),则抛出 OptimisticLockException,提示并发修改冲突。
其他辅助功能

  • 刷新缓存(flush())

entityManager.flush() 强制将当前持久化上下文中所有未同步的更改立即写入数据库。在某些需要立即看到数据库更新结果的情况下(如查询刚修改过的数据),可能需要手动调用此方法。

  • 清理缓存(clear())

entityManager.clear() 清除持久化上下文中的所有实体,释放资源。清除后,所有先前加载的实体变为游离状态,新的查询将从数据库重新加载数据。

  • 关闭 EntityManager(close())

当不再需要 EntityManager 时,应调用 entityManager.close() 来关闭它,释放与数据库的连接。在Spring环境下,通常由容器自动管理 EntityManager 的生命周期,不需要手动关闭。
总结来说,EntityManager 是 JPA 提供的一个强大而灵活的接口,它封装了与数据库交互的所有必要操作,包括实体的生命周期管理、查询执行、事务控制、缓存管理以及并发控制。深入理解和熟练运用 EntityManager 的各项功能,有助于构建高效、健壮且易于维护的持久化层。在实际项目中,结合使用Spring Data JPA的高级抽象(如 JpaRepository)和 EntityManager 的低级API,可以更好地适应不同场景的需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/571480.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

目标检测——小麦穗头数据集

一、重要性及意义 小麦穗头检测在农业领域具有重要意义&#xff0c;主要体现在以下几个方面&#xff1a; 首先&#xff0c;小麦穗头检测可以帮助农民和植物科学家准确评估作物的健康状况和成熟度。通过对小麦穗部的形态特征进行测量和分析&#xff0c;可以及时发现作物生长过…

应用在防蓝光显示器中的LED防蓝光灯珠

相比抗蓝光眼镜、防蓝光覆膜、软体降低蓝光强度这些“软”净蓝手段&#xff0c;通过对LED的发光磷粉进行LED背光进行技术革新&#xff0c;可实现硬件“净蓝”。其能够将90%以上的有害蓝光转换为450nm以上的长波低能光线&#xff0c;从硬件的角度解决了蓝光危害眼睛的问题&#…

python+django校园社交高校交友网站2x7r5.

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中&#xff0c;方便对数据进行操作本课题基于WEB的开发平台&#xff0c;设计的基本思路是&#xff1a; 前端&#xff1a;vue.jselementui 框架&#…

【机器学习】深度神经网络(DNN):原理、应用与代码实践

深度神经网络&#xff08;DNN&#xff09;&#xff1a;原理、应用与代码实践 一、深度神经网络&#xff08;DNN&#xff09;的基本原理二、DNN的优缺点分析三、DNN的代码实践四、总结与展望 在人工智能与机器学习的浪潮中&#xff0c;深度神经网络&#xff08;Deep Neural Netw…

Spring Boot 集成 EasyExcel 3.x

Spring Boot 集成 EasyExcel 3.x Spring Boot 集成 EasyExcel 3.x 本章节将介绍 Spring Boot 集成 EasyExcel&#xff08;优雅实现Excel导入导出&#xff09;。 &#x1f916; Spring Boot 2.x 实践案例&#xff08;代码仓库&#xff09; 介绍 EasyExcel 是一个基于 Java 的、…

【注解和反射】什么时候类会和不会被初始化?

继上一篇博客【注释和反射】类加载的过程-CSDN博客 目录 四、什么时候类会被初始化&#xff08;主动引用&#xff09;&#xff1f; 测试 五、什么情况下不会发生类的初始化&#xff08;被动引用&#xff09;&#xff1f; 测试 四、什么时候类会被初始化&#xff08;主动引用…

<网络> HTTP

目录 前言&#xff1a; 一、再谈协议 &#xff08;一&#xff09;认识URL &#xff08;二&#xff09;Encode 和 Decode 二、HTTP 协议 &#xff08;一&#xff09;协议格式 &#xff08;二&#xff09;见一见请求 &#xff08;三&#xff09;见一见响应 三、模拟实现响…

模块化 DeFi L2 “Mode” 整合 Covalent Network(CQT),以获 Web3 最大数据集的支持

Covalent Network&#xff08;CQT&#xff09;&#xff0c;作为 Web3 领先的数据层&#xff0c;宣布其统一 API 将与 Mode 集成&#xff0c;以加快其基于以太坊构建的专注于 DeFi 的模块化 Layer2 方案的数据访问速度。这一战略合作将通过为开发者提供更强大的工具和能力&#…

论文浅尝 | LoRA: 大模型的低秩适配

笔记整理&#xff1a;陈一林&#xff0c;东南大学硕士&#xff0c;研究方向为不确定知识图谱规则学习 链接&#xff1a;https://arxiv.org/abs/2106.09685 1、动机 自然语言处理的一个重要范式包括在通用领域数据上进行大规模预训练&#xff0c;然后对特定任务或领域进行适应性…

`THREE.AudioAnalyser` 音频分析

demo案例 THREE.AudioAnalyser 音频分析 入参 (Input Parameters): audio: 一个 THREE.Audio 实例&#xff0c;代表要分析的音频。fftSize: 快速傅里叶变换&#xff08;FFT&#xff09;的大小&#xff0c;用于确定分析的精度和频率分辨率。smoothingTimeConstant: 平滑时间…

[lesson58]类模板的概念和意义

类模板的概念和意义 类模板 一些类主要用于存储和组织数据元素 类中数据组织的方式和数据元素的具体类型无关 如&#xff1a;数组类、链表类、Stack类、Queue类等 C中将模板的思想应用于类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能。 C中的类模板…

如何通过cURL库实现远程控制插座

如何通过cURL库实现远程控制插座呢&#xff1f; 本文描述了使用cURL库调用HTTP接口&#xff0c;实现控制插座&#xff0c;即插即用&#xff0c;先插入插座&#xff0c;再接电器&#xff0c;实现远程控制。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格…

开源文本嵌入模型M3E

进入正文前&#xff0c;先扯点题外话 这两天遇到一个棘手的问题&#xff0c;在用 docker pull 拉取镜像时&#xff0c;会报错&#xff1a; x509: certificate has expired or is not yet valid 具体是下面&#x1f447;这样的 rootDS918:/volume2/docker/xiaoya# docker pul…

油猴脚本:bing 搜索结果居中

文章目录 效果预览脚本使用步骤安装油猴脚本添加脚本 效果预览 脚本 // UserScript // name bing居中 // namespace http://tampermonkey.net/ // version 2024-04-24 // description try to take over the world! // author You // match http…

牛客 题解

文章目录 day4_17**BC149** **简写单词**思路&#xff1a;模拟代码&#xff1a; dd爱框框思路&#xff1a;滑动窗口&#xff08;同向双指针&#xff09;代码&#xff1a; 除2&#xff01;思路&#xff1a;模拟贪心堆代码&#xff1a; day4_17 BC149 简写单词 https://www.now…

缓存神器-JetCache

序言 今天和大家聊聊阿里的一款缓存神器 JetCache。 一、缓存在开发实践中的问题 1.1 缓存方案的可扩展性问题 谈及缓存&#xff0c;其实有许多方案可供选择。例如&#xff1a;Guava Cache、Caffine、Encache、Redis 等。 这些缓存技术都能满足我们的需求&#xff0c;但现…

CPDA|0到1突破:构建高效数据分析体系的秘密武器

在现今信息爆炸的时代&#xff0c;数据已经渗透到了我们生活的方方面面&#xff0c;成为了决策、创新和竞争优势的关键。因此&#xff0c;构建一套高效的数据分析体系&#xff0c;对于企业和个人而言&#xff0c;都是至关重要的。那么&#xff0c;如何在众多的数据海洋中脱颖而…

自动化立体库安全使用管理制度

导语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。专注分享智能仓储物流技术、智能制造等内容。 新书《智能物流系统构成与技术实践》 完整版文件和更多学习资料&#xff0c;请球友到知识星球 【智能仓储物流技术研习社】自行下载 关于自动化立体库安…

Visual Studio导入libtorch(Cuda版)

Visual Studio导入libtorch&#xff08;Cuda版&#xff09; 一、安装 官网&#xff1a;https://pytorch.org/get-started/locally/ 相应地选择并下载 二、环境变量配置 解压zip&#xff0c;得到libtorch文件夹&#xff0c;将libtorch\lib和libtorch\bin对应路径添加到系统环…

如何把视频中的画面保存为图片?免费的工具不用白不用

在数字化时代&#xff0c;截取视频中的珍贵瞬间成为了人们创作、分享和保存回忆的重要方式。 那么&#xff0c;如何迅速捕捉视频中的精彩画面&#xff0c;留存美好瞬间呢&#xff1f;有人说直接截图就可以&#xff0c;如果直接截图就可以&#xff0c;小编就不用写这篇文章了&a…
最新文章