请帮忙!它已经花了我一天的时间,而且我没有更接近解决这个问题。我的设置如下:
我正在做的是持久化具有子实体的@OneToOne映射的实体。一旦记录在数据库中,我正在运行一个选择并成功选择新插入的记录。但是,子实体为空。
我的目标是只插入父记录,因为子记录已经在数据库中。
问题:我需要更改什么才能填充子记录?
我有一个我坚持的实体:
EntityManager em = getEntityManager();
try {
em.getTransaction().begin();
em.persist(timeSheet);
em.getTransaction().commit();
}
该实体包含@OneToOne:
@Entity
@Cache(expiry=-1)
@Table(name="TIME_SHEET")
public class TimeSheet implements Serializable {
private static final long serialVersionUID = 1L;
@OneToOne(fetch=FetchType.EAGER)
@JoinColumns({
@JoinColumn(name="PROJECT_ID", referencedColumnName="PROJECT_ID", nullable = false, insertable=false, updatable=false),
@JoinColumn(name="COMPANY_ID", referencedColumnName="COMPANY_ID", nullable = false, insertable=false, updatable=false)
})
private Project project;
public Project getProject() {
return project;
}
子实体是:
@Entity
@Cache(expiry=-1)
@Table(name="PROJECT")
public class Project implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private ProjectPK id;
持久保存并选择“TimeSheet”后,“Project”为空。我该怎么做才能确保填充“项目”?
谢谢!
答案 0 :(得分:1)
嗯,在显示的代码中,你坚持使用TimeSheet而不先在其中设置一个Project,那么为什么你在加载它时会期望它有一个Project?加载它后,你永远不应该期望你的对象模型看起来与你保存它之前的不同。如果它 看起来不一样,那么你就有问题了。
答案 1 :(得分:1)
您应该正确设置级联策略。
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-hibspec-cascade
级联策略规定了在父实体上执行持久性操作时如何处理关联实体。
答案 2 :(得分:0)
正如Ryan指出的那样,您需要将TimeSheet中的引用保留到项目中。这是因为时间表是缓存的。因此,您可以在创建TimeSheet时通过读取现有项目来设置关系,也可以在事务提交后刷新TimeSheet以便构建它。
您显示的代码设置TimeSheet->项目关系字段是只读的,并不显示如何填充foriegn键。确保在通过其他映射插入TimeSheet时实际设置了这些映射,或者可能是TimeSheet合法地没有项目 - 尽管字段似乎具有非空约束。