java - 为什么我的 equals 方法不起作用?

标签 java collections object jpa-2.0

assertEquals(def.getMengs(), exp.getMengs());

失败,报告: 预期:java.util.HashSet<[...so geht die Legende ... ...legend has it ... ]> 但是是:java.util.HashSet<[...so geht die Legende ... ...传说有它...]>

确实,通过调试器我看到两个集合都只包含一个含义,其中 objId = 1。 我希望 Meaning 类 (@Entity) 中的以下代码能够保证上述工作。

@Override
public boolean equals(Object object) {
   if (!(object instanceof Meaning)) {
        return false;
   }
   Meaning other = (Meaning) object;
   if (other != null && objId == other.objId) return true;
   return false;
}

@Override
public int hashCode() {
    int hash = 7;
    hash = 67 * hash + this.objId;
    return hash;
}

确实,这个测试通过了:

 db.insert(admin);
    final Meaning meng = new Meaning(admin, new Expression("essen"));
    meng.setObjId(11);
    final Meaning meng1  = new Meaning(admin, new Expression("mangiare"));
    meng1.setObjId(11);
    assertEquals(meng,meng1);

那么我的问题可能是什么? Thery都是HashSet,它们的大小都一样,里面的对象也相等。确实

            assertEquals(def.getMengs().iterator().next(), exp.getMengs().iterator().next());

在它过去之前。然而这不会(但我不知道为什么):

assertTrue(def.getMengs().containsAll(exp.getMengs()));

所以,这就是问题所在。

测试代码如下:

try{
            db.insertWords(toEnumMap(mengs[i],admin));
        }catch(Exception e){
            fail(e.getMessage());
        }
        final Expression exp = db.get(Expression.class, mengs[i][0]);
        testGender(exp, mengs[i][2]);

        final Expression def = db.get(Expression.class, mengs[i][1]);
        assertNotNull(def);

        assertEquals(def.getMengs().iterator().next(), exp.getMengs().iterator().next());
        assertEquals(exp.getMengs().size(), def.getMengs().size());
        assertTrue(def.getMengs().containsAll(def.getMengs()));
        assertTrue(def.getMengs().containsAll(exp.getMengs()));
        assertEquals(def.getMengs(), exp.getMengs());

db.get 只是包装了 em.find。 InsertWords 应该保留 def 和 exp。

public void insertWords(EnumMap<Input, MemoEntity> input) throws MultipleMengsException {
    insert(input.get(Input.expression)); //INSERT OR IGNORE
    final boolean isNewDef = insert(input.get(Input.definition));

    final Expression def = get(Expression.class, input.get(Input.definition).getId());
    final Expression exp = get(Expression.class, input.get(Input.expression).getId());
    final MUser usr = get(MUser.class, input.get(Input.user).getId());

    final Set<Meaning> mengs = getMengs(usr,def,isNewDef);
    if (mengs == null) {//is new to the user
        final Meaning meng = new Meaning(usr, exp, def);
        insert(meng);

    } else { //old meaning
        if (mengs.size() > 1) throw new MultipleMengsException(mengs);
        else{
            final Meaning meng = mengs.iterator().next();
            meng.addExp(exp);
            meng.setLastPublishedDate(null); //reschedule
        }
    }
    Logger.getAnonymousLogger().log(Level.INFO, "inserted pair <{0},{1}>", new String[]{exp.getExpression(), def.getExpression()});
}

public boolean insert(final MemoEntity entity) {
        if (em.find(entity.getClass(), entity.getId()) == null) {
            et.begin();
            em.persist(entity);
            et.commit();
            return true;
        }
        return false;
    }

public <MemoEntity> MemoEntity get(final Class<MemoEntity> entityClass, final Object primaryKey) {
        return em.find(entityClass, primaryKey);
    }

最佳答案

实体的 HashCode 和 equals 最好不要使用代理 ID 进行比较,而是使用对象的业务属性或仅使用自然键来实现比较。看这个SO question了解详情。

编辑:至于为什么这不起作用,我唯一的猜测是您在将对象添加到 HashSet 之后修改对象,特别是更改 ID。这将导致 contains 方法失败,因为它使用 hashCode 将对象定位为 hashmap 中的键,如果 ID 已更改,它将在底层 hashMap 中查找错误的位置。

关于java - 为什么我的 equals 方法不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3344381/

相关文章:

java - NoClassDefFoundError Amazon ADM 在 kindle 上的集成

java - 如何使用流重写嵌套列表的查找功能

java - 集合 <接口(interface)> 名称 = null;

java - 用于存储原始整数的集合,允许更快的 contains() 和有序迭代

Java - ArrayList 构造函数的线程安全

带有 httpServer 的 Java 应用程序在退出前挂起 45 秒

java - SimpleDateFormat 在 java 中返回一个奇怪的值

javascript - 我们如何使用 javascript 将 HTML 字符串转换为对象?

javascript - 动态属性值而不是函数?

html - HTML对象嵌入音量