Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JPA在2个不同的模式和会话之间复制项目_Java_Spring_Hibernate_Jpa - Fatal编程技术网

Java JPA在2个不同的模式和会话之间复制项目

Java JPA在2个不同的模式和会话之间复制项目,java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,我想我应该与大家分享我的见解,在两个不同的模式之间复制实体,每个模式都由自己的dataSource/entityManager/Session处理 在我的例子中,目标模式可能有也可能没有该项,因此它可能是插入或更新。 此外,尽管id是自动生成的,但我希望保持源id,避免目标模式生成自己的id 大部分艰苦的工作都由以下人员负责: Session.replicatesourceEntity,ReplicationMode.OVERWRITE 然而,我遇到的挑战是: 必须调用detach方法以避免出现

我想我应该与大家分享我的见解,在两个不同的模式之间复制实体,每个模式都由自己的dataSource/entityManager/Session处理

在我的例子中,目标模式可能有也可能没有该项,因此它可能是插入或更新。 此外,尽管id是自动生成的,但我希望保持源id,避免目标模式生成自己的id

大部分艰苦的工作都由以下人员负责: Session.replicatesourceEntity,ReplicationMode.OVERWRITE

然而,我遇到的挑战是:

必须调用detach方法以避免出现以下错误:org.hibernate.HibernateException:非法尝试将集合与两个打开的会话关联 复制现有项时,如果已从其一些关联子项中删除较新的等效源项,则目标实体仍保留过时的子项-因此我在复制源之前删除了旧的目标实体。 我对自动生成的Id有另一个问题。虽然人们希望复制方法会传输现有的Id,但事实并非如此,并且总是生成一个新的Id。我通过将sessionFactory的DefaultReplicateEventListener替换为自定义的来解决这个问题,这要求从源实体获取Id。 复制副本由以下代码管理:

MyEntity sourceEntity = sourceEntityManager.find(MyEntity.class, sourceEntity.getId());
sourceEntityManager.detach(sourceEntity);
Session hibernateSession = 
targetEntityManager.unwrap(Session.class);
hibernateSession.replicate(sourceEntity, ReplicationMode.OVERWRITE);
在复制现有实体之前,先删除该实体,这有助于清洁复制副本:

MyEntity existingEntity = 
targetEntityManager.find(MealDescription.class, sourceEntity.getId())
targetEntityManager.remove(existingMeal);
通过重写类并替换侦听器替换默认复制侦听器DefaultReplicateEventListener:

public static class IdPreservingReplicateEventListener extends DefaultReplicateEventListener implements Loggable {
    @Override
    protected Serializable performSaveOrReplicate(Object entity, EntityKey key, EntityPersister persister, boolean useIdentityColumn, Object anything, EventSource source, boolean requiresImmediateIdAccess){
        if (key == null) {
            Serializable id = persister.getIdentifier( entity, source );
            key = source.generateEntityKey( id, persister );
            useIdentityColumn = false;
        }

        return super.performSaveOrReplicate(entity, key, persister, useIdentityColumn, anything, source, true);
    }
}
并将其替换为sessionFactory:

EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.REPLICATE).clear();
registry.getEventListenerGroup(EventType.REPLICATE).appendListener(new IdPreservingReplicateEventListener());

您可以尝试将其与SourceEntityManager分离并合并到TargetEntityManager:

final MyEntity sourceEntity = sourceEntityManager.find(MyEntity.class, sourceEntity.getId());
sourceEntityManager.detach(sourceEntity);
targetEntityManager.merge(sourceEntity);

有关更多信息,请参见此答案

分离是解决方案的一部分,但合并失败。似乎我对保留一些相关的收藏有意见。谢谢。我根据我后来的见解编辑了我的问题