Java Hibernate、@ManyToOne inserts和ehCache

Java Hibernate、@ManyToOne inserts和ehCache,java,hibernate,jpa,ehcache,Java,Hibernate,Jpa,Ehcache,我有一个父->子关系,有一个@ManyToOne/@OneToMany关系 我正在处理对父级的更新,代码大致如下: 找到父母 从中检索(按顺序-ehCache、db或create(如果找不到) 处理更新,如果未找到,则在父级上创建子级 保存到数据库 存储在缓存中 在运行时,我发现出现了以下顺序 第一次更新完成-父级和子级都创建了缓存 第二次更新-从缓存中检索父级,添加新的子级 当第二次更新完成时,子项的id仍然为空。但是,更新成功完成。(根据hibernate日志和数据库进行验证)

我有一个父->子关系,有一个
@ManyToOne
/
@OneToMany
关系

我正在处理对父级的更新,代码大致如下:

  • 找到父母
    • 从中检索(按顺序-ehCache、db或create(如果找不到)
  • 处理更新,如果未找到,则在父级上创建子级
  • 保存到数据库
  • 存储在缓存中
在运行时,我发现出现了以下顺序

  • 第一次更新完成-父级和子级都创建了缓存
  • 第二次更新-从缓存中检索父级,添加新的子级
    • 当第二次更新完成时,子项的id仍然为空。但是,更新成功完成。(根据hibernate日志和数据库进行验证)
  • 第三次更新-
    DataIntegrityViolationException
    被抛出,因为第二次更新的子项被再次插入
我假设这一定与父级缓存的事实有关,而不是从数据库返回。我不确定这里的正确流程应该是什么

有关资料:

  • 正确定义和注释了父子返回引用
  • 在初始插入父级之后,我尝试从数据库中重新获取父级,并缓存它,以查看它是否起到了作用——它没有
  • 事务边界必须在这里发挥作用,因为这在我的测试中最初并没有失败,而我的测试被标注为
    @Transactional
    。(刻苦学习的一课)
正确的处理方法是什么?特别是,避免每次都必须从db加载父对象,同时仍然正确跟踪子实体

代码示例如下所示

@Entity // Parent
class Fixture {

    @OneToMany(cascade=CascadeType.ALL, mappedBy="fixture", fetch=FetchType.EAGER) @Getter @Setter
    @MapKey(name="instrumentPriceId")
    private Map<String,Instrument> instruments = Maps.newHashMap();

    private Instrument addInstrument(Instrument instrument)
    {
        instruments.put(instrument.getInstrumentPriceId(), instrument);
        instrument.setFixture(this);
        log.info("Created instrument {}",instrument.getInstrumentPriceId());
        return instrument;
    }

    /**
     * Returns an instrument with the matching instrumentId.
     * If the instrument does not exist, it is created, appended to the internal collection,
     * and then returned.
     * 
     * This method is guaranteed to always return an instrument.
     * This method is thread-safe.
     * 
     * @param instrumentId
     * @return
     */
    public Instrument getInstrument(String instrumentId)
    {
        if (!instruments.containsKey(instrumentId))
        {
            addInstrument(new Instrument(instrumentId));
        }
        return instruments.get(instrumentId);
    }
}

@Entity // Child
public class Instrument {

    @Column(unique=true)
    @Getter @Setter
    private String instrumentPriceId;

    @ManyToOne(optional=false)
    @Getter @Setter @JsonIgnore
    private Fixture fixture;

    public Instrument(String instrumentPriceId)
    {
        this.instrumentPriceId = instrumentPriceId;
    }
}

}这个问题的答案简单得令人沮丧

update
方法中,我忽略了
save()
操作的结果。 通常,如果您不打算再次使用对象,这是很好的。(这是很常见的,因为您在工作单元结束时保存了)

但是,当我再次继续使用“父项”时,我需要观察返回值:

因此:

fixtureRepository.save(fixture);
fixtureCache.put(new Element(fixtureId, fixture));      
变成这样:

fixture = fixtureRepository.save(fixture);
fixtureCache.put(new Element(fixtureId, fixture));      
fixture = fixtureRepository.save(fixture);
fixtureCache.put(new Element(fixtureId, fixture));