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;
    }
}
相关推荐
NiNg_1_23419 分钟前
SpringSecurity入门
后端·spring·springboot·springsecurity
Lucifer三思而后行1 小时前
YashanDB YAC 入门指南与技术详解
数据库·后端
王二端茶倒水2 小时前
大龄程序员兼职跑外卖第五周之亲身感悟
前端·后端·程序员
计算机-秋大田2 小时前
基于微信小程序的乡村研学游平台设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
LuckyLay2 小时前
Spring学习笔记_36——@RequestMapping
java·spring boot·笔记·spring·mapping
程序员小明z3 小时前
基于Java的药店管理系统
java·开发语言·spring boot·毕业设计·毕设
夜色呦3 小时前
现代电商解决方案:Spring Boot框架实践
数据库·spring boot·后端
爱敲代码的小冰3 小时前
spring boot 请求
java·spring boot·后端
java小吕布4 小时前
Java中的排序算法:探索与比较
java·后端·算法·排序算法
Goboy5 小时前
工欲善其事,必先利其器;小白入门Hadoop必备过程
后端·程序员