首页 > 解决方案 > 如何保存复制实体JPA?

问题描述

我有一个配置文件实体,我使用 SerializationUtils 制作了这个实体的副本,记下一些值并希望将其作为新记录保存到数据库中,但由于某种原因,我正在更新我制作的原始记录复制,我做错了什么?

Profile profile = profileRepository.findByProfileId(profileId).orElseThrow(() -> {
                            throw new NullPointerException(String.format("profile with  id=%s not found", profileId.toString()));
                        });
Profile newProfile = SerializationUtils.clone(profile);
entityManager.detach(profile);
newProfile.setId(null);
newProfile.setProfileId(UUID.randomUUID());
newProfile.setSnils(profileWithValidationSuccessBySnils.getSnils());                            
entityManager.persist(newProfile);

标签: javajpaspring-data-jpa

解决方案


您使用 SerializationUtils 所做的很可能会导致您的副本与原始对象具有相同的 Hibernate/JPA 代理,从而导致 Hibernate 将其视为原始对象(iow,与您刚刚完成“Profile newProfile = profile ;"

因为我不知道您的 SerializationUtils 实际做了什么以及它是如何实现的,所以很难说,但如果我写它,我会在其实现中考虑 Hibernate 代理。

最好的方法是从头开始创建一个新实体,并将原始实体中的数据字段减去@Id 字段提供给它。

例如,您可以使用复制构造函数来执行此操作(我知道,这在 Java 中是一个肮脏的词)。

这样,您就可以保证拥有一个全新的实体,该实体未链接到持久存储中的任何内容,因此应始终创建新记录。

对于我们的一个项目,我们为这种情况编写了我们所谓的“DeHibernator”(更具体地说,是从需要传输到内存受限设备的对象中剥离 Hibernate 代理,而我们无法加载 Hibernate 只是为了能够传输代理并让它们在这些设备上工作)。


推荐阅读