如何使会话缓存中各个实体之间的数据与JPA保持同步?

时间:2019-02-21 17:22:01

标签: spring-data-jpa hibernate-mapping

我正在尝试弄清楚如何使数据在会话缓存中保持同步。我有以下示例:

@Table (name = "language")
@Entity
public class Language
{
    @Id
    @Column (name = "key", unique = true, nullable = false)
    private String key;

    @Column (name = "name", unique = true, nullable = false)
    private String name;

    @OneToMany (mappedBy = "language", cascade = { CascadeType.DETACH, CascadeType.REFRESH, CascadeType.REMOVE })
    private Set<Translation> translations;
}


@Table (name = "translation")
@Entity
public class Translation 
{
    @Id
    @GeneratedValue (strategy = GenerationType.SEQUENCE)
    private Long id;

    @ManyToOne(optional = false)
    private Language language;

    @ManyToOne (optional = false)
    @JoinColumn(referencedColumnName = "key")
    private TranslatableEntity translatable;

    @Column(name = "value")
    private String value;
}


@Table (name = "translatable")
@Entity
public class Translatable
{
    @Id
    @GeneratedValue (strategy = GenerationType.SEQUENCE)
    private Long id;

    @NotNull
    @Size (max = 255)
    @Column (name = "key", unique = true, nullable = false)
    private String key;

    @OneToMany (mappedBy = "translatable", cascade = { CascadeType.DETACH, CascadeType.REFRESH, CascadeType.REMOVE, CascadeType.PERSIST })
    @MapKey (name = "language")
    private Map<Language, Translation> translations;
}

所以基本上我会这样做:

// Print current translations for en language
Language language = languageRepository.getOne("en");
printTranslations(language);

// Add new translatable object with translation for english language
Translatable translatable = new Translatable();
translatable.addTranslation("en", "...")
translatableRepository.saveAndFlush(translatable)

// Again print translations for en language
// This still prints outdated information
language = languageRepository.getOne("en");
printTranslations(language);

所以我的问题是如何保持数据一致。

在插入/删除带有某些翻译的新翻译时,“语言”实例中的翻译列表不会在会话缓存中更新。 我找不到任何令人满意的答案。这个最接近:Keeping entity relationship in sync when deleting child in JPA

谢谢

1 个答案:

答案 0 :(得分:1)

JPA不会为您维护双向关系的两个方面。 一级缓存的目的是在事务实体中仅加载一次。

这为您提供了两个解决问题的方法:

  1. 自己维护关系的两端,例如,通过实现Translatable.add方法,以便它更新Language.translationsTranslation.language

  2. 通过调用language

  3. 之前驱逐它或关闭会话(即交易)来强制重新加载languageRepository.getOne("en")