持久化API(JPA)系列(四)管理器EntityManager--执行数据库更新

EntityManager是应用访问持久化上下文中的实体的接口,用来对实体Bean进行操作。我们可以使用它来创建、删除、修改持久化的实体,以体现到数据库中;也可以从数据库中查询得到实体或实体列表。所有的这些操作都是通过实体管理器进行的。

本文将首先讲解EntityManager对象的引用方式,然后讲解使用EntityManager的操作函数实现数据库的各种操作,包括以下内容。

持久化实体persist():往数据表中插入数据。

删除实体remove():从数据表中删除记录。

更新实体merge():更新数据表记录。

刷新实体到数据库flush()。

设置Flush刷新模式setFlushMode()。

刷新实体refresh():从数据表中更新。

按主键查询实体find():从数据表中查询记录。

检测实体是否被管理contains()。

分离管理的实体clear()。

=============================================================================

1、 EntityManager对象的引用方式

根据实体管理器应用的场景不同,可以将它分为两种类型。

1)容器托管的EntityManager

容器托管的EntityManager对象必须在EJB容器中运行,而不能在Web容器和Java SE环境中运行。前一节的实例中的EntityManager对象就是通过注入@PersistenceContext注释从容器中获得的,这种获得EntityManager对象的方式就是容器托管。这种方式使用起来最简单,开发人员不需要考虑EntityManager对象的创建、事务等复杂问题,所有这些都交给容器去管理。取得该对象的方式如下:

@PersistenceContext(unitName="demo")

EntityManager em;

2)应用托管的EntityManager

应用托管的EntityManager对象可以在EJB容器中运行,也可以脱离EJB容器,而与任何的Java环境集成,比如说Web容器、Java SE环境等。它需要开发人员手动地控制它的创建、释放、事务等,这些操作都比较复杂。取得该对象的方式如下:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("demo");

EntityManager em = emf.getEntityManager();

因为我们公司的项目是运行在JBoss这个EJB容器中的,因此采用第一种方式来使用它。

==特点:更新并不会立刻同步到数据库=====================================================

1、持久化实体persist()--往数据表中插入数据

DAO层主要的工作就是将EntityManager管理的实体持久化到数据库中保存起来,即将内存中的实体对象写入到数据表中,在表中反应的是新增了一行记录。

持久化的方法是:

em.persist(obj);

类似于执行了以下SQL语句:

insert into student(name, sex, age, birthday, telephone, address) values(‘刘中兵‘, 1, 25, ‘1981-05-04‘, ‘12345678‘, ‘北京‘);

2、删除实体remove()--从数据表中删除记录

当需要删除一个已经被持久化到数据库中的实体对象时

Object obj = em.find(clazz, id);

em.remove(obj);

例如:

Student student = em.find(Student.class, 1);

em.remove(student);

类似于执行了以下SQL语句:

delete from student where id=1;

3、更新实体merge()--更新数据表记录

更新一个已经被持久化的实体对象

Object updatedObj = em.merge(obj);

例如:

Student student = em.find(Student.class, 1);

student.setName("liuzhongbing");

em.merge(student);

类似于执行了以下SQL语句:

update student set name="liuzhongbing" where id=1;

当执行em.merge(student)方法时,有如下两个执行规则:

如果此时容器中已经存在一个受容器管理的具有相同id的student实例,则容器将会把参数student的内容复制进这个受管理的实例,merge()方法返回受管理的实例,但参数student仍然是分离的、不受管理的。容器在决定Flush时把实例同步到数据库中。

容器中不存在具有相同id的student实例。容器根据传进的student参数复制出一个受容器管理的student实例,同时merge()方法会返回出这个受管理的实例,但参数student仍然是分离的、不受管理的。容器在决定Flush时把实例同步到数据库中。

==特点:刷新实体同步到数据库=========================================================

1、刷新实体到数据库flush()

当调用persist()、merge()和remove()这些方法时,更新并不会立刻同步到数据库中,直到容器决定刷新到数据库中时才会执行。在默认情况下,容器决定刷新是在"相关查询"执行前或事务提交时发生的,当然"相关查询"除find()和getReference()之外,这两个方法是不会引起容器触发刷新动作的,如果你需要在事务提交之前将更新刷新到数据库中,你可以直接调用EntityManager.flush()方法。在这种情况下,你可以手动来刷新数据库以获得对数据库操作的最大控制。

当实体正在被容器管理时,你可以调用实体的setXXX()方法对数据进行修改,在容器决定Flush时,更新的数据才会同步到数据库中。如果你希望修改后的数据即时同步到数据库中,则可以执行flush()方法:

em. flush(obj);

该函数将会做两件事:

提交更改的字段到数据库。

刷新数据库中的字段到该实体中。

例如:

Student student = em.find(Student.class, 1);

student.setName("liuzhongbing");

em.flush(student);

这与上面执行merge()的区别如下。

提交的对象不同:flush()是将容器管理的对象提交到数据库,而merge()不仅可以提交容器管理的对象,而且可以提交没有被容器管理的对象。

提交的时机不同:flush()会立即同步到数据库,而merge()只会在容器需要Flush时执行同步。

2、设置Flush刷新模式setFlushMode()

上面的flush()函数是手动调用的,如果不手动调用,则只能依赖于容器的自动刷新。在默认情况下容器是自动刷新的,这是因为它对应了刷新了的AUTO值:

public enum FlushModeType {

AUTO,

COMMIT

}

我们可以调用下面的方法改变刷新模式:

em.setFlushMode(FlushModeType.COMMIT);

这两种模式的区别如下。

AUTO:刷新在查询语句执行前(除了find()和getreference()查询)或事务提交时才发生,适用于在大量更新数据的过程中没有任何查询语句(除了find()和getreference()查询)时执行。

COMMIT:刷新只有在事务提交时才发生,适用于在大量更新数据的过程中存在查询语句(除了find()和getreference()查询)时执行。

这两种模式的区别体现在数据库底层SQL的执行上,即JDBC驱动跟数据库交互的次数。COMMIT模式使更新只在一次网络交互中完成,而AUTO模式可能需要多次交互,它触发了多少次Flush就产生了多少次网络交互。

==特点:获取数据库最新数据,并同步到实体=================================================

1、刷新实体refresh()--从数据表中更新

如果当前被管理的实体已经不是数据库中最新的数据,则可以通过refresh()方法刷新实体,容器会把数据库中的新值重写进实体:

em. refresh(obj);

例如:

Student student = em.find(Student.class, 1);

//如果此时student对应的记录在数据库中已经发生了改变,则可以通过refresh()方法得到最新数据:

em. refresh(student);

==特点:从实体中查询数据=========================================================

1、按主键查询实体find()--从数据表中查询记录

一旦将对象持久化到数据库中,它就会产生一个主键,我们可以通过这个主键来查询它。查询的方法很简单,只需要指定要查询的id和查询后对象的实体类,就可以取得该记录的实例。

Object obj = em.find(clazz, id);

其中clazz为实体Bean的类名。

还有一个方法getReference(),用法与find()方法相同,不同的是当数据库中没有找到记录时,该方法将会抛出异常不同。

例如:

Student student = em.find(Student.class, 1);

类似于执行了以下SQL语句:

select * from student where id=1;

==特点:查看、分离被容器管理的实体====================================================

1、检测实体是否被管理contains()

前文中的flush()和merge()分别针对实体是否被容器所管理进行了区分,所谓的被管理,就是实体管理器管理中的实体,没有被管理,就是不在实体管理器容器范围内,即没有经过实体管理器的各种操作函数进行持久化。

实体管理器提供了一个方法contains(),用来检查实体是否被管理。形式如下:

boolean b = em.contains(obj);

contains()方法使用一个实体作为参数,如果这个实体对象当前正被持久化内容管理,则返回值为true,否则为false。

例如:

Student student = em.find(Student.class, 1);

if (em.contains(person)){

//正在被持久化内容管理

}else{

//已经不受持久化内容管理

}

2、分离管理的实体clear()

当处理了大量的实体后,这些实体都会存在于实体管理器中,这将会消耗大量的内存,使程序运行变慢。如果要减少消耗,则可以使用clear()方法,将正在被管理的实体从持久化内容中分离出来。如下所示:

em.clear();

如果调用clear()方法,则之前对实体所做的任何改变都将会被丢失,所以在调用clear()方法之前先调用flush()方法保存更改。

时间: 2024-08-04 16:38:39

持久化API(JPA)系列(四)管理器EntityManager--执行数据库更新的相关文章

Ansible Tower系列 四(使用tower执行一个命令)【转】

在主机清单页面中,选择一个主机清单,进入后,选择hosts里的主机 Paste_Image.png 点击 RUN COMMANDS MODULE 选择 commandARGUMENTS 填写 ifconfig eth0MACHINE CREDENTIAL 选择 ssh登陆账号Verbosity 选择 3 (Debug) Paste_Image.png 点击 Launch,查看输出 转自 Ansible Tower系列 四(使用tower执行一个命令) - 简书http://www.jianshu

循序渐进学.Net Core Web Api开发系列【8】:访问数据库(基本功能)

系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇讨论如何连接数据库,包括连接SQL Server 和 连接MySQL,然后做一些基本的数据操作. 二.连接SQL Server 首先通过NuGet添加相关的包: 新建一个实体类: public class Product { [Key] public string Code { get; set; } p

30 ArcGIS 许可管理器常见问题(持续更新中……)

一.[单机版] 1.1.ArcMap 1.2.ArcGIS Pro 错误一 ArcGIS Pro单机许可安装授权,在Configure Authorization界面报“This functionality is not available without the ArcGIS Pro Licensing Service being installed. The service can be installed by running the license service installer l

持久化API(JPA)系列(五)控制实体Bean的生命周期

上篇文章<持久化API(JPA)系列(四)管理器EntityManager--执行数据库更新>中我们讲解了使用实体管理器的各种函数操作数据库的方法. 本文主要讲:控制实体Bean的生命周期. 与会话Bean类似,实体Bean也有自己的生命周期,分别对应不同的状态. 下面我们首先来讲解实体Bean的状态和生命周期事件: 1.实体Bean生命周期的4种状态 2.实体Bean的事件: @PostLoad @PrePersist和@PostPersist @PreUpdate和@PostUpdate

持久化API(JPA)系列(三)实体Bean的开发技术-建议与数据库的连接

在EJB 2.x中,EJB有3种类型的Bean,分别是会话Bean(Session Bean).消息驱动Bean(Message-Driven Bean)和实体Bean(Entity Bean). 随着EJB 3的推出,EJB2.x中的实体Bean逐渐被JPA规范所替代,JPA不仅能在EJB环境中使用,而且能在Java SE.Java EE环境中使用,相对于EJB 2.x中的实体Bean,它的使用范围更广. 但这里我们仍然将其称做实体Bean. 与会话Bean和消息驱动Bean类似,新的实体Be

Spring Data Jpa系列教程--------实体解析和关联关系

Spring Data Jpa是基于HIbernate开发的,所以建立实体建的实体和映射关系需要好好好的去了解一下,本文有以下内容,实体管理器介绍,实体与数据库表的映射介绍,关联关系(一对多,多对多)介绍,SpringDataJpa应用分析 ------实体管理器   实体管理器EntityManager是实体与数据库的桥梁(和事务一起发挥作用),相当于Hibenrtae中的session,Mybatis中的sqlSession.使用方法放个小例子吧 @PersistenceContext pr

Android基础入门教程——10.3 AudioManager(音频管理器)

在多媒体的第一节,我们用SoundPool写了个Duang的示例,小猪点击一个按钮后,突然发出”Duang”的 一声,而且当时的声音很大,吓死宝宝了,好在不是上班时间,上班时间偷偷写博客给经理知道 会作死的~嗯,好的,说到这个声音大小就得介绍下Android为我们提供的(音量大小控制)的API: AudioManager(音频管理器)了,该类位于Android.Media包下,提供了音量控制与铃声模式相关操作!... www.mafengwo.cn/i/4012346.htmlwww.mafen

WebSphere--连接管理器

连接管理器使您可以控制并减少由 Web 应用程序使用的资源.相对于非 Web 应用程序,基于 Web 的应用程序对数据服务器的访问会导致更高的和不可预料的系统开销,这是由于 Web 用户更为频繁的连接和断开.通常连接与断开连接所用的资源大于交互所用的资源.由于 Internet 的"冲浪"性质,用户的交互过程一般都较短.通常,公司外(Internet,而非 intranet)的用户会将使用卷变得很大,并难以预料.连接管理器通过建立用户 Servlet 可用的连接缓冲池将连接的系统开销分

python上下文管理器ContextLib及with语句

http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能(2.5 版本中要通过 from __future__ import with_statement 导入后才可以使用),从 2.6 版本开始缺省可用(参考 What's new in Python 2.6? 中 with 语句相关部分介绍).with 语句适用于对资源进行访问的场合,确保不管使用过程