JPA insertable = false updatable = false id在创建时未更新

时间:2015-08-09 10:11:23

标签: java spring hibernate jpa hql

我们有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;
   ...
}

3 个答案:

答案 0 :(得分:1)

Hibernate不会在实时填充实体字段' (当你改变其他一些领域或类似的时候)。它也不会在persist / flush上执行它(例外是一些特殊字段,如id和version)。

从DB中获取实体实例时,将填充不可插入/不可更新的字段。因此,要使Hibernate在同一事务中初始化/刷新这些字段,在该事务中对其映射到的基础列执行更改,您应首先刷新会话,然后执行以下任一操作:

  1. 清除会话并重新阅读实体;
  2. 或,refresh您希望反映此类更改的实体。

答案 1 :(得分:0)

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

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

A)使用cascade

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

(或使用CascadeType.ALL

B)手动持续entityA

entityManager.persist(entityA);

答案 2 :(得分:0)

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

如果你想要处理hibernate,请删除insertable = false updatable = false