无法将项目列表发送到后端以从列表中删除

时间:2013-10-22 02:45:20

标签: java hibernate java-ee hibernate-mapping

用户将从列表中选择几个要删除的项目。

我有两个选项,可以在内存中传递所选项目的ID或其对象的地址。

第一个问题是,发送所选项目的对象而不是其ID是正确的方法吗?

  <input type="checkbox" name="selectedItems" value="${item}"/> 

   rather than

  <input type="checkbox" name="selectedItems" value="${item.id}"/> 

如果我应该发送项目的ID,当我传递他们的ID时,创建一个对象并设置id我无法从列表中删除它们,最好的方法是什么?

        Item item = new Item();
        item.setID(selectedItems.get(0));

        Basket basket = (Basket) session.get(Basket.class, Long.parseLong(basket_id));
        basket.getItems.remove(item); <<I cant remove them by just setting their ids!!

        session.update(basket);

8 个答案:

答案 0 :(得分:3)

list.remove方法从列表中删除第一次出现的指定元素。下面的代码块是从ArrayList源代码复制的:

for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    // REMOVE ITEM FROM THE LIST
                }
}

使用Object.equals方法检查要从列表中删除的对象的相等性。因此,您需要覆盖equals类中的Item方法,以确定所有items是否相等。当您覆盖equals()时,您始终需要覆盖hashCode(),以便两种方法保持一致

现在,当传递Item的实例从list中移除时,您需要设置用于实现Item的{​​{1}}的所有属性的值方法。

但您不应使用equals来实施database identifier (id)。在保存实体之前,Hibernate不会分配标识符值。因此,如果在保存之前将对象添加到equals(),则它的哈希码会在Set包含时更改(在保存操作时),与Set的契约相反。您可以使用属性组合,这对于java.util.Set的每个实例都是唯一的。

答案 1 :(得分:1)

删除前加载项目对象。

Item item = session.load(Item.class, selectedItems.get(0))

然后致电

basket.getItems.remove(item);

答案 2 :(得分:1)

有几种方法,如果你对hql或sql很满意,我宁愿用查询来做,

  1. 接近一个

    从表中删除其中id为(x,y,z,xy ...);

  2. 优点:您无需从数据库加载任何内容。你只需运行一个sql并获得响应。

    1. 接近两个
    2. 急切地将对象提取到内存中(Ofcoz,从客户端发送ID)迭代项目列表并匹配ID并将其删除。刷新会话。

答案 3 :(得分:0)

在您要删除的对象的课程中,您需要override equals() method。以if all member variables are equal, then the objects are equal的方式编码。 Netbeans IDE中提供了模板实现,它使用了更多检查,例如检查实例。

Otherwise object member variables could all be same but still objects 
will not be equal since they refer to different locations in memory heap.

我的override equals() and toString() methods

几乎总是model classes

答案 4 :(得分:0)

简单明了

不要删除副本,在里面搜索:

for(Iterator<Item> iterator = basket.getItems().iterator(); iterator.hasNext();)
{
    Item currentItem = iterator.next();

    if(selectedItems.contains(currentItem.getId()))
    {
        iterator.remove();
    }
}

但是,如果您没有覆盖value="${item}",请勿使用item.toString()

答案 5 :(得分:0)

你能不能将你的ArrayList更改为HashMap并将对象存储在他们的ID中?然后你可以用一行代码删除它们。

答案 6 :(得分:0)

HQL。

session.createQuery("delete from Item i where i.id in (:iids)").setParameter("iids", item_ids).executeUpdate();

答案 7 :(得分:0)

不要直接渲染对象。不要这样做。那种方式就是痛苦和疯狂。假设你这样做了,并没有覆盖toString()

<input type="checkbox" name="selectedItems" value="${item}"/>

然后发生以下情况:

  • 您将项目提取到List,使用class.name@address的默认toString()实现呈现每个项目。
  • 用户选择要删除的一些项目并提交表单,它会生成新的HTTP请求。项目的原始List已消失,因此这些地址指向......嗯,您不知道他们指向的是什么。

(还有其他问题:如果恶意攻击者检查页面源,他们现在知道你正在运行基于Java的服务器。没有理由自愿提供这些信息。)

现在,您可能会想到“嘿,我会把这些项目放在我的会话中。”现在您遇到了同样的问题:大多数会话处理实现会在将项目存储到会话中时将其序列化,并在检索时将它们反序列化为新的副本。您的对象引用现在毫无意义。

您可以覆盖toString(),但为什么?只需传递ID并将其发送到删除查询中的数据库。这样,如果有人决定更改toString()实施,就不会有任何意外。