JPA数据库操作EntityManager状态管理

什么是EntityManager

在JPA规范里,EntityManager扮演着执行持久化操作的关键角色。

只有当普通Java对象被EntityManager持久化后,它们才能转变为持久化对象。

EntityManager 负责管理O/R映射,即实体类与底层数据源之间的关系。它不仅可以管理和更新Entity Bean,还可以基于主键查询Entity Bean,甚至通过JPQL语句进行实体查询。

java 复制代码
**
 * Interface used to interact with the persistence context.
 *//这里讲述了EntityManager的作用!!!
 * <p> An <code>EntityManager</code> instance is associated with
 * a persistence context. A persistence context is a set of entity
 * instances in which for any persistent entity identity there is
 * a unique entity instance. Within the persistence context, the
 * entity instances and their lifecycle are managed.
 * The <code>EntityManager</code> API is used
 * to create and remove persistent entity instances, to find entities
 * by their primary key, and to query over entities.
 *
 * <p> The set of entities that can be managed by a given
 * <code>EntityManager</code> instance is defined by a persistence
 * unit. A persistence unit defines the set of all classes that are
 * related or grouped by the application, and which must be
 * colocated in their mapping to a single database.
 *
 * @see Query
 * @see TypedQuery
 * @see CriteriaQuery
 * @see PersistenceContext
 *
 * @since Java Persistence 1.0
 */
public interface EntityManager {
//...
}

Java Persistence API (JPA) 中的 EntityManager 是一个接口,它主要负责数据库操作的核心功能。以下是其主要作用:

  1. 创建和删除数据库记录EntityManager 提供了 persist()remove() 方法来插入和删除数据库记录。

  2. 查询数据库记录EntityManager 提供了 find()createQuery() 等方法来查询数据库记录。

  3. 更新数据库记录EntityManager 提供了 merge() 方法来更新数据库记录。

  4. 管理实体的生命周期EntityManager 能够跟踪实体对象的状态,并在适当的时候进行持久化操作。

  5. 事务管理EntityManager 提供了 getTransaction() 方法来获取当前事务,然后可以对事务进行提交或回滚。

总的来说,EntityManager 是 JPA 中的核心接口,它提供了一种抽象的方式来管理数据库操作,使得开发者可以更加专注于业务逻辑的开发,而不需要关心底层的 SQL 语句。

数据状态管理

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

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

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

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

数据操作

EntityInformation 是 Spring Data JPA 中的一个接口,它提供了关于实体类的元数据。这些信息包括实体类的 ID 类型、实体类类型等。以下是 EntityInformation 的主要作用:

  1. 获取实体类的 IDEntityInformation 提供了 getId(entity) 方法来获取实体对象的 ID。

  2. 获取实体类的 ID 类型EntityInformation 提供了 getIdType() 方法来获取实体类 ID 的 Java 类型。

  3. 获取实体类的类型EntityInformation 提供了 getJavaType() 方法来获取实体类的 Java 类型。

  4. 检查实体是否为新的EntityInformation 提供了 isNew(entity) 方法来检查实体是否为新的(即还未持久化到数据库中)。

总的来说,EntityInformation 提供了一种抽象的方式来获取和操作实体类的元数据,这对于编写通用的、可重用的数据访问代码非常有用。

具体实现

java 复制代码
package cn.soboys.springbootjpa.jpa;

import cn.soboys.springbootjpa.jpa.conditions.Wrapper;
import cn.soboys.springbootjpa.jpa.config.JpaDaoHelper;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.util.Assert;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.Transactional;
import java.io.Serializable;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/7/24 18:31
 * @webSite https://github.com/coder-amiao
 */
public class CustomBaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {
    /**
     * 实体类
     */
    private final Class<T> entityClass;
    /**
     * 实体类名
     */
    private final String entityName;
    /**
     * 实体管理器
     */
    private final EntityManager entityManager;

    private final JpaEntityInformation<T, ?> entityInformation;

    @SuppressWarnings("all")
    public CustomBaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        Assert.notNull(entityInformation, "JpaEntityInformation must not be null!");
        Assert.notNull(entityManager, "EntityManager must not be null!");
        this.entityInformation = entityInformation;
        this.entityManager = entityManager;
        this.entityName = entityInformation.getEntityName();
        this.entityClass = entityInformation.getJavaType();
        JpaDaoHelper.setEntityManager(entityManager);
    }

    @Override
    @Transactional
    public T updateById(T entity) {
        entityInformation.getRequiredId(entity);
        return entityManager.merge(entity);
    }

    @Override
    @Transactional
    public T saveOrUpdate(T entity) {
        if (entityInformation.isNew(entity)) {
            entityManager.persist(entity); //保存
            return entity;
        } else {
            return entityManager.merge(entity); //更新
        }
    }

    @Override
    @Transactional
    public T update(Wrapper<T> updateWrapper) {
       //this.entityManager.createQuery()
        return null;
    }
}
相关推荐
wn53111 分钟前
【Go - 类型断言】
服务器·开发语言·后端·golang
bjzhang7521 分钟前
SpringBoot开发——集成Tess4j实现OCR图像文字识别
spring boot·ocr·tess4j
flying jiang26 分钟前
Spring Boot 入门面试五道题
spring boot
小菜yh27 分钟前
关于Redis
java·数据库·spring boot·redis·spring·缓存
希冀12334 分钟前
【操作系统】1.2操作系统的发展与分类
后端
GoppViper1 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
爱上语文2 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
荆州克莱2 小时前
springcloud整合nacos、sentinal、springcloud-gateway,springboot security、oauth2总结
spring boot·spring·spring cloud·css3·技术
serve the people2 小时前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端
罗政8 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端