当前位置: 首页 > 知识库问答 >
问题:

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

刁丰羽
2023-03-14

我试图找出如何在会话缓存中保持数据同步。我举了以下例子:

@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);

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

当插入/删除带有某些翻译的新翻译时,语言实例中的翻译列表不会在会话缓存中更新。对此我找不到任何满意的答案。这是最接近的一个:在JPA中删除孩子时保持实体关系同步。

谢谢。

共有1个答案

荆炳
2023-03-14

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

这给了你两个解决问题的选择:

>

  • 自己维护关系的双方,例如通过实现<code>Translatable。添加方法,使其更新语言。翻译翻译。语言

    在调用< code > language repository . get one(" en ")之前,通过驱逐或关闭会话(即事务)来强制重新加载< code>language

  •  类似资料:
    • 我正在尝试开发一个小型电子商务项目。我有一个篮子和篮子项目实体。我只是想当我为客户保存购物篮时,我想把购物篮项目保存在数据库中。我认为我不应该为篮子项目创建存储库。我应该能够保存篮子项目,同时使用篮子存储库保存篮子。 在这里,我试图通过篮子服务获得一个篮子项目,并将其设置为篮子实体并保存它。 我有什么问题?我有个例外。

    • 我有一个实体CandidateTransaction和CandidateTransactionRepository扩展了CrudRepository 我正在使用CrudRepository的save方法来保存所述实体的对象。当实体没有行时,它将创建一个自动生成的键并将其插入ID列,而不需要Java端的干预。 而且,由于CrudRepository的save()方法检查实体是否是新的,如果是新的,它

    • 我使用此代码制作实体的副本: 所以问题是-如果我从这个创建的副本中创建一个新副本,它们都指向实体管理器缓存中最后创建的副本! 复制方法执行后的evictAll()使其颠倒-现在id=2和id=3都指向id=2的原始副本。我假设这与以下事实有某种联系Java我们不会使用构造函数创建新对象,并且变量保持不变,而数据库中存在两个实体。

    • 1)我想从缓存中获得数据,如果缓存中没有数据,那么应该从数据库中获取数据。 2)如果我点击/api/cacherefresh,控制器将刷新所有表。