【发布时间】:2012-04-13 19:32:10
【问题描述】:
我有一个类 User,它充当数据库中用户表的持久性模型:
public class User {
@Id
@Basic(optional = false)
@Column(name = "USER_ID")
private Long userId;
@JoinColumn(name = "LAST_CHANGED_USER_ID", referencedColumnName = "USER_ID")
@ManyToOne(fetch = FetchType.LAZY)
private User lastChangedUser;
...
@Override
public int hashCode() {
int hash = 0;
hash += (userId != null ? userId.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof User)) {
return false;
}
User other = (User) object;
if ((this.userId == null && other.userId != null) ||
(this.userId != null && !this.userId.equals(other.userId))) {
return false;
}
return true;
}
@Override
public String toString() {
return "User[userId=" + userId + "]";
}
}
每当对 User 实例进行更改时,都会更新字段 lastChangedUser。考虑以下方法:
private void setUsername(string username, User lastChangedUser){
this.username = username;
this.lastChangedUser = lastChangedUser;
}
public void updateUserName(Long userId, Long lastChangedUserId, String username){
EntityManager em = PersistenceManager.getPersistenceManager()
.getEntityManager();
EntityTransaction transaction = em.getTransaction();
User user = em.find(User.class, userId);
User lastChangedUser = em.find(User.class, lastChangedUserId);
transaction.begin();
user.setUsername(username, lastChangedUser);
transaction.commit();
}
和单元测试:
public void testUpdateUsername(){
UserFacade instance = new UserFacade();
User john = instance.getUserByUserId(new Long(1));
User jane = instance.getUserByUserId(new Long(2));
// make the update and persist
instance.updateUsername("JANE M. DOE", jane.userId, john.userId);
// assert that john made the change to jane
jane = instance.getUserByUserId(new Long(2));
assertTrue(jane.username.equals("JANE M. DOE"));
User actual = jane.lastChangedUser;
User expected = john;
// this assertion passes...
assertTrue(actual.equals(expected));
// yet this assertion fails!
assertTrue(expected.equals(actual));
// this fails as well.
assertEquals(expected, actual);
}
使用Netbeans 7.1.1,测试结果界面返回错误信息:
FAILED: expected: User[id=1], but was: User[id=1].
经检查,对象actual 不是User 类型,而是代理对象的类型。我认为这是由于 LAZY fetch 注释。因此,对象的用户 ID 的值为 null,expected.equals(actual) 返回 false。然而,actual.equals(expected) 返回true。更让我困惑的是,失败消息显示actual.userId 不是null,而是等于预期的 id!
Hibernate 或 JUnit 的什么怪癖导致实际的 User 对象在失败后出现?
【问题讨论】:
-
为清楚起见,假设
setUsername方法位于User类中。 -
PersistenceManager.getPersistenceManager().getEntityManager();在这种情况下是否总是返回相同的实体管理器?来自不同 EntityManagers 实例的实体可能彼此不喜欢。 -
我猜你已经在你的实体上覆盖了
equals()。你的equals()方法是什么样的? -
ɲeuroburɳ,
getEntityManager()方法并不总是返回相同的EntityManager实例。这个因素如何影响这种情况? Tim,equals方法被覆盖;请参阅实现的第一个代码块。
标签: hibernate jakarta-ee jpa junit persistence