(三)JPA - EntityManager的使用

本文深入探讨了Java Persistence API (JPA) 中EntityManager的功能与用法,包括如何利用persist、merge、remove和find等方法实现对实体类的增删查改操作。
摘要由CSDN通过智能技术生成

(二)JPA 连接工厂、主键生成策略、DDL自动更新

建议在需要使用时,看看之前的文章,先把环境搭起来。

4、EntityManager

EntityManager 是完成持久化操作的核心对象。

EntityManager 对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过JPQL语句查询实体。

上面测试代码中,已经使用过EntityManager完成持久化操作。

实体类的状态:

新建状态: 新创建的对象,尚未拥有持久性主键;

**持久化状态:**已经拥有持久性主键并和持久化建立了上下文环境;

**游离状态:**拥有持久化主键,但是没有与持久化建立上下文环境;

删除状态: 拥有持久化主键,已经和持久化建立上下文环境,但是从数据库中删除。

4.1 persist 增

persist (Object entity):用于将新创建的 Entity 纳入到 EntityManager 的管理。该方法执行后,传入 persist() 方法的 Entity 对象转换成持久化状态。

如果传入 persist() 方法的 Entity 对象已经处于持久化状态,则 persist() 方法什么都不做。

如果对删除状态的 Entity 进行 persist() 操作,会转换为持久化状态。

如果对游离状态的实体执行 persist() 操作,可能会在 persist() 方法抛出 EntityExistException(也有可能是在flush或事务提交后抛出)。

测试代码:

   @Test
    public void testPersist() {
        // 获取连接
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 开启事务
        entityManager.getTransaction().begin();
        // 新建状态实例 
        Course course = new Course();
        course.setCname("Spring编程实战");
        course.setStart(DateUtil.stringToDate("2022-09-19"));
        course.setEnd(DateUtil.stringToDate("2022-12-30"));
        course.setCredit(2);
        course.setNum(88);
        // 对新建状态 持久化
        entityManager.persist(course);
        // 提交事务
        entityManager.getTransaction().commit();
        // 关闭连接
        JPAEntityFactory.close();
    }
// 日志信息
insert into course (cname, credit, end, num, start) values (?, ?, ?, ?, ?)

如果设置了id,就说明这是一个游离状态的实体类,执行会出现异常

4.2 merge 增\改

merge() 用于处理 Entity的同步。即数据库的插入和更新操作。

image-20220921215136231

测试代码: 传入新建状态的对象

    @Test
    public void testMerge() {
        // 获取连接
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 开启事务
        entityManager.getTransaction().begin();
        Course course = new Course();
        course.setCname("Spring编程实战");
        course.setStart(DateUtil.stringToDate("2022-09-19"));
        course.setEnd(DateUtil.stringToDate("2022-12-30"));
        course.setCredit(2);
        course.setNum(88);
        // 对新建状态 持久化
        entityManager.merge(course);
        // 提交事务
        entityManager.getTransaction().commit();
        // 关闭连接
        JPAEntityFactory.close();
    }

查看日志,可以看到,执行的是插入操作。

insert into course (cname, credit, end, num, start) values (?, ?, ?, ?, ?)

测试代码: 传入游离状态对象

    @Test
    public void testMerge() {
        // 获取连接
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 开启事务
        entityManager.getTransaction().begin();
        Course course = new Course();
        course.setCid(2L);
        course.setCname("Spring编程实战");
        course.setStart(DateUtil.stringToDate("2022-09-19"));
        course.setEnd(DateUtil.stringToDate("2022-12-30"));
        course.setCredit(2);
        course.setNum(88);
        // 对新建状态 持久化
        entityManager.merge(course);
        // 提交事务
        entityManager.getTransaction().commit();
        // 关闭连接
        JPAEntityFactory.close();
    }

查看日志,可以看到,执行的是Update语句

update course set cname=?,credit=?,end=?, num=?, start=? where cid=?
4.3 remove 删

删除实例。如果实例是被管理的,即与数据库实体记录关联,则同时会删除关联的数据库记录。

**注意:**该方法只能移除持久化对象。

 @Test
    public void testRemove() {
        // 获取连接
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 开启事务
        entityManager.getTransaction().begin();
        // 查询
        Course course = entityManager.find(Course.class, 2);
        // 对新建状态 持久化
        entityManager.remove(course);
        // 提交事务
        entityManager.getTransaction().commit();
        // 关闭连接
        JPAEntityFactory.close();
    }

查看日志,可以看到,执行的是Delete语句

delete from course where cid=?
4.4 find 查

find (Class<T> entityClass,Object primaryKey):返回指定的 OID 对应的实体类对象。

第一个参数为被查询的实体类类型,第二个参数为待查找实体的主键值。

如果这个实体存在于当前的持久化环境,则返回一个被缓存的对象;否则会创建一个新的 Entity, 并加载数据库中相关信息;若 OID 不存在于数据库中,则返回一个 null。

    @Test
    public void testFind() {
        // 获取连接
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 开启事务
        entityManager.getTransaction().begin();
        // 查询主键为3L
        Course course = entityManager.find(Course.class, 3L);
        loggerFactory.info("【find查询结果:】{}", course);
        // 提交事务
        entityManager.getTransaction().commit();
        // 关闭连接
        JPAEntityFactory.close();
    }

查看日志信息:【find查询结果:】Course(cid=3, cname=Spring编程实战, start=2022-09-19, end=2022-12-30, credit=2, num=88)

4.5 getReference

getReference (Class<T> entityClass,Object primaryKey):与find()方法类似。

不同的是:如果缓存中不存在指定的 Entity, EntityManager 会创建一个 Entity 类的代理,但是不会立即加载数据库中的信息,只有第一次真正使用此 Entity 的属性才加载,所以如果此 OID(主键) 在数据库不存在,getReference() 不会返回 null 值, 而是抛出EntityNotFoundException。

    @Test
    public void testGetReference() {
        // 获取连接
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 开启事务
        entityManager.getTransaction().begin();
        Course course = entityManager.getReference(Course.class, 3L);
        loggerFactory.info("【find查询结果:】{}", course);
        // 提交事务
        entityManager.getTransaction().commit();
        // 关闭连接
        JPAEntityFactory.close();
    }

查看日志信息:【find查询结果:】Course(cid=3, cname=Spring编程实战, start=2022-09-19, end=2022-12-30, credit=2, num=88)

不存在,则会抛出异常:

image-20220921222722234

第一次写博客,那是因为我想与大家分享.Net世界.我原来是ASP程序员,与.Net结缘那是在两年多前.第一次接触它,就喜欢上了.哈哈 接着我给大家分享一下我在项目中用到的数据访问层,这个是我用微软网站上得到的DBHepler数据库访问层的一次改编,让它支持实体类和用表达 式的方式生成SQL,而且更关键的是,他是采用参数的方式传值的,这样就避免了SQL的注入啦.. 以下是这个项目的结构 [SuperDAL] ---DbHelper.cs(来自MSDN的数据访问层) ---EntityManager.cs(实体类管理) ---Expressions.cs(实体类表达式查询) ---Expression.cs(实体类表达式) ---OrderByExpressions.cs(排序表达式查询) ---OrderByExpression.cs(排序表达式) ---ObjectValues -------OrderBy.cs(排序枚举类) ---DBManager.cs(数据访问类管理) ---DbParams.cs(数据库访问类参数) ---DataTableExtensions.cs(这个就是顾名思义啦,DataTable传实体类) 在这里最主要介绍的就是EntityManager这个啦,使用方法如下: 有数据库DB的一张表Customs CREATE TABLE [Customs] ( [Name] [varchar] (20) , [Password] [varchar] (20) , [Email] [varchar] (50) , [Phone] [varchar] (11) NULL , [Old] [int] , [Birthday] [DateTime] ) 有个实体类Customs.cs,结构如下: public class Customs { public string Name {get;set;} public string Password {get;set;} public string Email {get;set;} public string Phone {get;set;} public int Old{get;set} public DateTime Brithday {get;set;} } 数据库表与实体Customs结构是一一对应的.有了实体类CUstoms,下面就可以操作实体类跟操作数据库一样的啦,我们新建一个实体类管理类 CustomsManager.cs public class CustomsManager:EntityManager { public Customs GetByName(string name) { //创建表达式Expressions Expressions exps=new Expressions(); //向表达式添加条件 exps.Eq("name",name); //根据条件查询返回实体类 return EM_GetUnique(exps); } public List SearchByName(string name) { //同样像上面一样建立表达式类 Expressions exps=new Expressions(); exps.Like("name",name);//当然,有年朋友会说如果我要姓为"陈"的,那有些人的名字带陈的怎么办,没关系,可以改为 exps.LeftLike ("name",name); //根据条件查询返回实体类 return EM_GetEntity(exps); } /// /// 登录 /// /// 用户名 /// 密码 public List Login(string name,string password) { Expressions exps=new Expressions(); exps.Eq("name",name); exps.Eq("password",password); return EM_GetEntity(exps); } /// /// 选择年龄大于指定岁数的,并按年龄从小到大排序 /// /// 年龄 public List SelectOlder(int old) { Expressions exps=new Expressions(); exps.Gt("old",old); exp.OrderBys.Add("old", OrderBy.Asc); return EM_GetEntity(exps); } /// /// 选择年龄大于小于指定岁数段的,并按年龄从小到大,姓名从字母升序排序 /// /// 年龄 public List SelectByOld(int oldStart,int oldend) { Expressions exps=new Expressions(); exps.Between("old",oldStart,oldEnd); exp.OrderBys.Add("old", OrderBy.Asc); exp.OrderBys.Add("name",OrderBy.Asc); return EM_GetEntity(exps); } #region 增删改 操作 /// /// 更新操作 /// /// 实体类 public int Update(Customs customs) { return EM_Save(customs);//返回更新的记录数,当然,一般成功执行就会返回1;也可以改上面为public void Update(Customs customs) } /// /// 删除操作 /// /// public int DeleteByName(string name) { Expressions exps=new Expressions(); exps.Eq("name",name); return EM_Delete(exps); } /// /// 删除操作 /// /// 实体类 public int Save(Customs custom) { return EM_Save(custom); } #endregion } 当然还有更多的也就不一一贴出来了 Expressions支持的表达式有 1. Eq (等于)[name=value] 2. NotEq (不等于)[not name = value] 3. Ge (大于等于)[name >=value] 4. Gt (大于)[name>value] 5. Le (小于等于)[name<=value] 6. Lt (小于)[name<value] 7. In (包括)[name in (value)] 8. NotIn (不包括)[not name in (value) 9. IsNotNull (不为NULL)[not name is null] 10. IsNull (等于NULL)[name is null] 11. Between (之间)[name between valueStart and valueEnd] 12. Like (模糊) [name like ‘%value%’ ] 13. LeftLike (左模糊) [name like ‘%value’] 14. RightLike (右模糊) [name like ‘value%’] 其它功能待与Net爱好者探讨啦,希望你有更好的思路
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值