【发布时间】:2014-09-12 17:00:59
【问题描述】:
我已经建立了单向 OneToMany 关系,如 JPA 2.1 规范第 2.10.5.1 节中的示例:
@Entity
public class Client implements Serializable {
...
@OneToMany
private List<ServiceOrder> activeServiceOrders;
public void setActiveServiceOrders( List<ServiceOrder> activeServiceOrders ) {
this.activeServiceOrders = activeServiceOrders;
}
public List<ServiceOrder> getActiveServiceOrders() {
return activeServiceOrders;
}
}
ServiceOrder 类使用其自动生成的长 id 实现 hashCode 和 equals。它们是由 Eclipse 实现的。
public class ServiceOrder implements Serializable {
@TableGenerator( name = "generator_serviceOrder", table = "SEQUENCE_TABLE", pkColumnName = "SEQ_NAME", valueColumnName = "LAST_VALUE_GEN", pkColumnValue = "SERVICE_ORDER_SEQ", allocationSize = 1, initialValue = 0 )
@Id
@GeneratedValue( strategy = GenerationType.TABLE, generator = "generator_serviceOrder" )
private long id;
...
@Override
public boolean equals( Object obj ) {
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( getClass() != obj.getClass() )
return false;
ServiceOrder other = (ServiceOrder ) obj;
if ( id != other.id )
return false;
return true;
}
...
}
表格都是按预期自动生成的。然后,当我想建立关系时,我会这样做:
...
Client client = entityManager.find(...);
ServiceOrder so = entityManager.find(...);
client.getActiveServiceOrders().add( so );
...
到目前为止一切都很好,事务提交成功。当我尝试删除关系时问题就开始了(在另一个事务中,另一个时刻):
...
Client sameClient = entityManager.find(...);
ServiceOrder sameSo = entityManager.find(...);
log.info(sameClient.getActiveServiceOrders().size()); // "1", OK
log.info(sameClient.getActiveServiceOrders().contains(so)); // "false". Why?
sameClient.getActiveServiceOrders().remove(so); // does nothing, returns false
...
我调试并发现ServiceOrder.equals()中出现以下错误:
...
if ( getClass() != obj.getClass() ) // different probably because JPA (Hibernate) proxies one of the objects
return false; // returns
...
我找到了两个临时解决方案:
- 删除 ServiceOrder equals() 和 hashCode(); 或
- 使关系双向(当然,每次添加/删除都会更新双方);
我不明白这种行为。如果关系是单向的或双向的,为什么会有不同的待遇?另外,如果我在同一事务的上下文中获取这些实体,第一个等于测试将如何失败:
if ( this == obj )
return true;
我正在使用 JPA 2.1 (Wildfly 8.1.0)。
最好的问候,并提前感谢您。 仁南
【问题讨论】:
-
以下是
getClass() != obj.getClass()不起作用的解释:Hibernate equals and proxy -
谢谢,我会尝试解决方案。但我想更好地理解为什么这会发生在单向关系上,但如果我让它成为双向关系就不会发生。这是特定于 Hibernate 还是在所有 JPA 实现中都相同?如果两个引用绑定到同一个 EntityManager(同一个事务),
if ( this == obj ) return true;将如何失败?
标签: java hibernate jpa orm wildfly