JPA:在父子关系中->父未更新
Posted
技术标签:
【中文标题】JPA:在父子关系中->父未更新【英文标题】:JPA: in parent child relation -> parent is not updated 【发布时间】:2018-01-29 09:18:55 【问题描述】:在开发我的应用程序时,我曾经在使用数据库中的值时收到 NullPointerException。此值是在父子关系中设置的。经过一番调试,我看到,这个值从未被数据库更新过。 代码如下所示:我有两个实体,首先创建父项,稍后创建子项。并且在创建之后,父级被更新。并且此更新从未由底层数据库执行。 创建的代码是这样的:
...
EntityManager em = Activator.getEntityManager();
Customer c = Customerem.createQuery("SELECT p FROM Customer c WHERE c.name=:arg")
.setParameter("arg", "abc").getSingleResult();
em.getTransaction().begin();
CustomerRelation cr = new CustomerRelation();
cr.setCustomerId("123");
cr.setAccessCode("456");
cr.setCustomer(c);
em.flush();
c.addCustomerRelation(cr);
em.persist(c);
em.persist(cr);
em.getTransaction().commit();
查看数据库日志时,我可以看到 CustomerRelation 的 INSERT 语句,但没有任何关于客户的信息...我在这里错过了什么?
顺便说一句,这里是实体类:
@Entity
public class Customer
@Id
@GeneratedValue
protected int cId;
@OneToMany (mappedBy="customer", cascade=CascadeType.PERSIST, CascadeType.MERGE)
protected List<CustomerRelation> relations;
... other fields, Getter/Setter, etc.
public void addCustomerRelation(CustomerRelation relation)
if (relations == null)
relations = new ArrayList<CustomerRelation>();
if (!this.relations.contains(relation))
this.relations.add(relation);
relation.setPerson(this);
@Entity
public class CustomerRelation
@Id
@GeneratedValue
protected int rId;
@ManyToOne(targetEntity=Person.class)
@JoinColumn(name="PERSON", referencedColumnName="pId")
protected Person person;
@Basic
protected String customerId;
@Basic
protected String accessCode;
... other fields, Getter/Setter, etc.
作为附加信息:我使用 Eclipselink 和 H2 作为数据库...
【问题讨论】:
好吧,测试不会更改映射到客户表的客户的任何属性。你正在使用 persist() 来保存一个已经持久的实体。 我创建了映射到客户的 CustomerRelation。是的,它没有改变,因为它还不存在。我应该使用什么来代替坚持? 客户已经存在。您没有修改 Customer 内部的任何内容,并且您调用 persist() 尽管它已经是持久的。你只是不应该调用persist(c)。而且调用其他任何东西都没有意义,因为您没有修改 Customer 中的任何内容。 好的,我明白了!但我认为我通过调用 c.addCustomerRelation(cr) 来修改客户... 这只是 ManyToOne CustomerRelation.customer 的反面。通过在 CustomerRelation 表中设置连接列(外键)的值,将此关联存储在数据库中。无需更改客户表中的任何内容即可添加与客户的关系。 【参考方案1】:我真的不知道为什么,但现在我有一个可行的解决方案。实在是无奈一整天,终于把实体类的注解注释掉了:
...
//@OneToMany (mappedBy="customer", cascade=CascadeType.PERSIST, CascadeType.MERGE)
protected List<CustomerRelation> relations;
....
在注释掉之后,我最后一次尝试并查看了日志。在那里,我找到了以下几行:
[EL Config]: metadata: 2018-01-29 21:29:52.207--元素[字段 关系] 被默认为一对多映射。
[EL Config]: metadata: 2018-01-29 21:29:52.207--目标实体 (参考)一对多映射元素的类[字段 关系]被默认为:类 de.mho.finpim.persistence.model.CustomerRelation。
所以我向下滚动了一点,发现了这个:
[EL Config]: metadata: 2018-01-29 21:29:52.214--连接表名 对于多对多映射 [字段关系] 默认为: CUSTOMER_CUSTOMERRELATION。
[EL Config]: metadata: 2018-01-29 21:29:52.214--源主键 多对多映射 [字段关系] 的列名正在 默认为:CID。
[EL Config]: metadata: 2018-01-29 21:29:52.214--源外键 多对多映射 [关系] 的列名正在 默认为:Customer_PID。
[EL Config]: metadata: 2018-01-29 21:29:52.214--目标主键 多对多映射 [字段关系] 的列名正在 默认为:RID。
[EL Config]: metadata: 2018-01-29 21:29:52.214--目标外键 多对多映射 [关系] 的列名正在 默认为:relationship_RID。
在这里,我得到了我所期望的实体类中的注释!我完全不明白,为什么在我删除注释后创建连接表,但最后它有帮助......
【讨论】:
以上是关于JPA:在父子关系中->父未更新的主要内容,如果未能解决你的问题,请参考以下文章