【问题标题】:store spring JPA repository find data to variable before save?存储spring JPA存储库在保存之前查找数据到变量吗?
【发布时间】:2022-02-03 10:59:28
【问题描述】:

我想在保存之前存储 spring JPA 存储库对象。

在函数更新中,我想将旧记录数据存储到 dbDomain 但突然在 repository.save(updated) 之后,dbDomain 更改为新的更新数据。

有人知道如何解决这个问题吗?谢谢

package com.test.admintool.userauth.services;

import java.text.SimpleDateFormat;
import java.util.*;

import com.test.admintool.engine.common.AdminToolFunction;
import com.test.admintool.engine.common.AuditTrailMessage;
import com.test.admintool.engine.common.CopyUtil;
import com.test.admintool.engine.service.AdminService;
import com.test.admintool.engine.service.AuditTrailEventService;
import com.test.admintool.engine.utils.SecurityUtil;
import com.test.admintool.userauth.entity.User;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.GenericTypeResolver;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;

import com.test.admintool.engine.AdminEntity;
import com.test.admintool.engine.exception.EntityNotFoundException;
import com.test.admintool.engine.repository.AdminRepository;
import com.querydsl.core.types.Predicate;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Table;

@Slf4j
public abstract class AdminServiceImpl<T extends AdminEntity<T>> implements AdminService<T> {

    private static final String AUDIT_ACTION_CREATE = "CREATE";
    private static final String AUDIT_ACTION_UPDATE = "UPDATE";
    private static final String AUDIT_ACTION_DELETE = "DELETE";
    private final AdminRepository<T> repository;

    private final AuditTrailEventService auditTrailEventService;

    protected AdminServiceImpl(AdminRepository<T> repository, AuditTrailEventService auditTrailEventService) {
        this.repository = repository;
        this.auditTrailEventService = auditTrailEventService;
    }

    public T get(Long id) throws EntityNotFoundException {
        return repository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException(String.format("Product %s not found", id)));
    }

    @Transactional
    public T update(T updated) throws EntityNotFoundException {
        T dbDomain = get(updated.getId());
        T updatedData = repository.save(updated);
        produceAuditMessageUpdate(dbDomain, updatedData, AUDIT_ACTION_UPDATE);
        return updatedData;
    }
}

【问题讨论】:

    标签: java spring spring-boot hibernate jpa


    【解决方案1】:

    我假设您正在将一个分离的实体实例传递给update 方法,并且在进入该方法时(通过spring 事务性aop 代理)启动一个新事务。
    (否则,dbDomain 条目将从休眠一级缓存解析到传递的实体实例updated,因此不会有任何属性差异。)

    当将分离实例updated传递给save方法时,实体管理器会将其合并到持久化上下文中。因此,它还将检查同一实体(相同 ID)的另一个已附加实例,并通过将所有值从新传递的实例复制到另一个附加实例来保持该实体的另一个实例同步:
    @987654321 @
    (这是有道理的,否则您最终会在附加实体上获得不同的值,并且您无法决定在事务结束时将哪些值持久化到数据库中。)

    为防止您的 dbDomain 实例被更新,您可以在调用 save(updated) 之前手动将其从持久性上下文中分离:

    T dbDomain = get(updated.getId());
    entityManager.detach(dbDomain); // <--
    T updatedData = repository.save(updated);    
    

    或者,您也可以深度复制相关的dbDomain 属性值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-22
      • 2015-06-19
      • 2017-05-26
      • 2020-09-09
      • 2020-03-18
      • 1970-01-01
      • 2016-06-19
      • 2021-04-16
      相关资源
      最近更新 更多