java - Spring 批处理鸡肉和鸡蛋 : transient JPA reference

标签 java spring spring-data-jpa spring-batch

我有一个 Spring-Batch 进程,它从 Bar 读取来创建一个新的 Foo:

/* My Foo Step */
class FooStepConfig {
    ItemReader<Bar> reader; // Reads records from Bar
    ItemProcessor<Bar, Foo> processor; // Determines whether to create a new Foo or update an existing Foo
    ItemReader<Foo> writer; // Created/Updated Foos are persisted
    // ...
}

此外,当创建或更新Foo时,我还需要保存 FooNotification引用 Foo:

// During processor step, this is saved
@Entity
public FooNotification {
    @Id Long id;
    @ManyToOne Foo foo; // @Entity class Foo { ... };
    @Enumerated NotificationType nt; // new, updated, removed, etc... 
                                     // (removal is a soft delete with "Foo.isActive" column) 
}

ItemProcessor :

class MyItemProcessor extends ItemProcessor<Foo, Bar> {
    ...
    public Foo process(Bar bar) { 
        Foo foo = fromBar(bar); // some supporting method defined elsewhere.
        ...
        // does not work as foo is still transient at this point and id is null as it is generated on persist from a Database Sequence.
        fooNotificationRepository.save(new FooNotification(foo,...));
        ...
        return Foo;
    }
}

如上面评论中所述,当批处理运行时,我收到以下异常:

java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException:↩ 
  ↪object references an unsaved transient instance - save the transient↩ 
  ↪instance before flushing : com.example.FooNotification.foo -> com.example.Foo

两者Foo创造/突变和FooNotification创建应该是原子的。我不希望其中一个单独存在,因此将两者分成单独的步骤并不理想。还有FooNotification可以包含有关哪些字段发生更改和以前的值的信息,因此在更新时进行计算会更加有效。

我知道我可以通过创建 ItemProcessor<Bar, FooNotification> 来解决这个问题ItemWriter<FooNotification>因为保存会通过适当的配置级联,并且 Foo每种类型都应该始终存在。但从概念上讲,这不是该步骤的目的,并且感觉很尴尬。 FooNotification s 是主产品 Foo 的副产品创建而不是主要批处理步骤的目标。

  • 是否有另一种更明智的方式可以确保 Foo 的创建之前FooNotification
  • 我需要“预先创建”Foo为了使引用成为有效的 orm 托管实体而未完成?

最佳答案

两种解决方案:

  1. 一个listener
  2. 将通知创建移至写入阶段:使用单个写入器或复合写入器;第一个用于 Foo ,最新的用于 FooNotification

关于java - Spring 批处理鸡肉和鸡蛋 : transient JPA reference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46597738/

相关文章:

java - 多个构造函数将不起作用

java - 如何在 Spring Security 中使用电子邮件作为用户名?

Spring启动运行报错

java - 在执行流式查询时修改 MySql 数据库

java - 自定义 Spring Data JPA 构造函数异常

java - 如何重用 Spring Data JpaRepository 接口(interface)

Java - 将复杂的 List#toString 转换为列表

java - request.getparameter 没有给出字符串数组的正确答案

java - 将 ByteBuffer 的内容写入 DataOutput?

java - Spring上下文中引用 "auto detected"bean