我的问题是我无法保存我的实体,因为它包含另一个实体,该实体由一个键映射,该键也是该表主键的一部分。该表如下所示:
table C:
+-----+------+
| id_A | id_B |
+-----+------+
..其中 idA 是表 AEntityA
的主键,idB 是表 B 的主键EntityB
。
所以它基本上是一个n对m的关系。这是我用于表 C 的实体:
@Entity
public class EntityC {
private long idA;
private EntityB b;
@Id
@Column(name = "id_A")
public long getIdA() {
return idA;
}
@Id
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "id_B")
public EntityB getB() {
return b;
}
...setters are here...
}
请注意,id_A
按原样映射(id),而id_B
映射为其对象表示,EntityB
. 这就是我想要做的:
EntityC c = new EntityC();
c.setIdA(123);
c.setB(new EntityB());
em.persist(c);
tx.commit();
em.close();
EntityB
只有当我能坚持时,我才想坚持EntityC
。
tx.commit()
我得到这个例外:org.hibernate.TransientObjectException: object references an unsaved transient instance
我想这是因为部分主键 ,id_B
没有保存。但是我将级联设置为所有,所以应该没有问题!
为什么这不起作用?
编辑:
当我这样做时:
em.persist(c.getB());
em.persist(c);
有用。但是 Hibernate/JPA 不能自动做到这一点吗?我认为这就是级联的好处。
编辑2:
添加了一个 embeddedId 而不是 id_A 和 id_B:
@Embeddable
public class EntityCID implements Serializable {
public long idA;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "id_B", referencedColumnName = "id")
public EntryB b;
}
EntityC 现在看起来像:
@Entity
public class EntityC implements Serializable {
private EntityCID id;
...
@EmbeddedId
public void getId() {
return id;
}
}
但如果我em.persist(c.getId().b);
之前不这样做,我仍然会得到瞬态对象异常em.persist(c)
。坚持这一点,虽然它是丑陋的。
@Trein:它不是双向的。实体B代码:
@Entity
public class EntityB implements Serializable {
public long id;
public String text;
}