【问题标题】:Making @IndexedEmbedded Entity as Read Only relationship in Hibernate Search在 Hibernate Search 中将 @IndexedEmbedded 实体设为只读关系
【发布时间】:2020-07-29 12:40:47
【问题描述】:

下面是我们两个实体的映射。它们包含多对一关系。

实体 A:

@ManyToOne(targetEntity = First.class)
    @JoinColumns({
            @JoinColumn(name = "seq", referencedColumnName = "seq", insertable = false, updatable = false),
            @JoinColumn(name = "addrSeq", referencedColumnName = "addrSeq", insertable = false, updatable = false) })
    @IndexedEmbedded 
    private Second second;


public Second getSecond() {
            return second;
        }
    
        public void setSecond(Second second) {
            this.second= second;
        }

实体 B:

@OneToMany(mappedBy="second", targetEntity = First.class)
    @ContainedIn
    private Set<First> first;

JPA 详细信息: 使用org.springframework.data.jpa.repository.JpaRepository的save()方法来持久化数据。

作为: 回购类:

public interface FirstRepository extends JpaRepository<First, FirstID>{}

然后在控制器中我们首先设置.. First 实体的所有数据设置器,然后:

repository.save(first);

现在的问题是,当尝试持久化第一个实体时,hibernate 会尝试持久化第二个实体,当它发现对象为空白时,它会为第二个实体抛出以下错误:

对象引用了一个未保存的瞬态实例 - 保存瞬态 刷新前的实例

是否可以在第一个实体和第二个实体之间仅出于休眠搜索(弹性索引)目的而建立只读关系。 因为我只需要弹性索引中第一个实体中的第二个实体的索引数据,并且在第一个实体上执行这些操作时永远不会添加/更新/删除第二个实体。此外,我们使用 JPA 来持久化第一个实体。

此外,我们不会在 Elastic 上索引第二个实体。但它确实包含@Field 带注释的字段,并且这些字段被嵌入到索引中的父字段中(这工作正常)。

另外,如果我在运行时向第一个实体内的第二个实体提供数据,然后再持久化第一个实体,它就可以工作。但它不会在持久化时自动拾取关系。

我已经尝试过的几件事:

  1. 使用 Cascade 和 Fetch 类型属性。
  2. @IndexedEmbedded private Second second; 上使用@Transient,则没有遇到问题,但第二个实体的索引上没有数据。

【问题讨论】:

  • "对象引用了一个未保存的瞬态实例——在刷新之前保存瞬态实例" => 这通常表明当你持久化它时你的实体有问题。这可能与您的映射无关,但与您调用的 getter/setter 无关。您能否澄清一下:“但它不会在持久性时自动拾取关系”?
  • @yrodiere,我已经用我的 getter/setter 更新了这个问题。请看看这些是否不正确或者需要更多的东西来做,我正在尝试做什么。进一步通过“但在持久性时它没有自动获取关系”我的意思是,当我在调试中检查第一个实体时,第二个实体是完全空的。我认为这很好,并且可能是休眠在持久化时创建了这种关系
  • getter/setter 的实现并不重要,我完全期望它们会以这种方式实现。重要的是调用这些 setter 和调用 entityManager.persist() 的代码。
  • @yrodiere,我已经用我们正在使用的 JPA 存储库更新了答案。我们直接使用“org.springframework.data.jpa.repository”的save()方法进行持久化。有没有我应该研究或与您分享的特定领域,以便您对此有更清晰的了解。请为我分享路线。此外,在保留父第一个实体之前,我没有为第二个实体调用任何设置器(这就是您所说的“重要的是调用这些设置器的代码”)

标签: hibernate jpa hibernate-search


【解决方案1】:

双向 JPA 关联具有“所有者”端和“非所有者”端。您通常可以通过映射中的“mappedBy”属性识别“非所有者”端(例如@OneToMany(mappedBy = ...))。

这里,First 是所有者,Second 是非所有者。

成为“所有者”是什么意思?粗略地说,这意味着First 表将包含一个具有指向Second 表的外键的列。

因此,当您创建First 时,如果您将其关联填充到Second,则Second 必须已经存在于数据库中。否则在First 表中插入行将失败,因为外键不能指向不存在的 ID。

因此,您的代码应该调用save(second),然后才应该调用save(first)。这将允许您持久保存您的两个实体而不会出现任何故障。

您还应该注意填充关联的双方。

然后 Hibernate Search 将正确索引您的实体。

【讨论】:

  • 谢谢你,我第一次保存时没有第二个的所有数据,只有关键部分可用。将不得不从数据库中获取完整数据。我相信这应该可以自动工作,因为我有 @indexed@contained in 关系。并请解释“因此,当您创建第一个时,如果您填充它与第二个的关联,”。按照你的回答,我相信我们不可能有一个只读的关系,用于 ES 索引。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-10
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多