【问题标题】:JPA insertable = false updatable = false id not updated on creationJPA 可插入 = 假 可更新 = 假 id 在创建时未更新
【发布时间】:2015-11-01 09:29:52
【问题描述】:

我们有 2 个实体具有 @ManyToOne 关系。

当我们在 @Transactional 方法中创建 EntityB 的实例时,entityAId (insertable = false updatable = false) 不会自动更新 - 即使 entityA 实例已被持久化。

有没有办法解决这个问题?我们是否必须在 ctor 中手动更新它?

@Entity
public class EntityA {

    @Id
    @GeneratedValue
    private Long id;

    public EntityA() {
       super();
    }
    ...
}

@Entity
public class EntityB {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(optional = true, fetch = FetchType.LAZY)
    private EntityA entityA;
    @Column(name = "entityA_id", insertable = false, updatable = false)
    private Long entityAId;    

    public EntityB() {
        super();
    }

    public EntityB(EntityA entityA) {
        super();
        this.entityA = EntityA;
    }
    ...
}

编辑:还尝试了以下操作,但事务中的 entityAId = null 仍然存在(即使之前保留了 entityA)。

@Entity
public class EntityB {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "entityA_id", insertable = false, updatable = false)
    private EntityA entityA;
    @Column(name = "entityA_id")
    private Long entityAId;
   ...
}

【问题讨论】:

  • 您如何将EntityBEntityA 关联起来?请编辑答案以添加代码。如果您使用其构造函数创建 entityB 并传递 entityA,则发布的第一个代码 sn-p 应该可以工作,所以我认为问题与逻辑和事务有关。另一条评论,如果您没有设置正确的entityAId 值,您发布的第二个代码将不会保持关系。

标签: java spring hibernate jpa hql


【解决方案1】:

要更新id 字段,需要对对象执行持久化操作。默认情况下,entityA字段中的对象在持久化EntityB的对象时不会自动持久化。

我看到了两种可能的解决方案:

A) 使用cascade

@ManyToOne(optional = true, fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST})
private EntityA entityA;

(或使用CascadeType.ALL

B) 手动坚持entityA

entityManager.persist(entityA);

【讨论】:

  • 感谢您的回答,在我们创建 entityB 之前,entityA 是否已经被持久化到数据库中?(在不同的事务中)
【解决方案2】:

在我看来,您的映射看起来不正确。 @ManyToOne 或实体之间定义的任何其他关联,但您已在 entityAId 上定义它。理想情况下它应该是实体(在这里你应该使用insertable = false updatable = false)并且你应该有单独的字段entityAId 并在其上定义@column。现在您应该自己更新此字段。

如果你想为你处理休眠,删除insertable = false updatable = false

【讨论】:

    【解决方案3】:

    Hibernate 不会“即时”填充实体字段(当您更改一些其他字段或类似字段时)。它也不会在持久化/刷新上执行(例外是一些特殊字段,如 id 和版本)。

    从数据库中获取实体实例时会填充不可插入/不可更新的字段。因此,要使这些字段在同一个事务中由 Hibernate 初始化/刷新,在该事务中您对它们映射到的基础列执行更改,您应该首先刷新会话,然后:

    1. 清除会话并重新读取实体;
    2. refresh您要反映此类更改的实体。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-16
      • 2011-03-19
      • 1970-01-01
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      • 2012-08-19
      • 1970-01-01
      相关资源
      最近更新 更多