@OrderColumn映射 - 错误地删除列表的第一个元素

时间:2015-05-12 15:46:00

标签: hibernate jpa

我有一个父实体维护一个有序的项目列表:

@Entity
public class ActionList  {

    private String id;
    private String actionId;
    private String name;
    private List<ActionItem> items = new ArrayList<ActionItem>();

    @Id
    public String getId() {
        return this.id;
    }

    public void setId(final String id) {
        this.id = id;
    }

    @Column(nullable = false)
    public String getActionId() {
        return this.actionId;
    }

    public void setActionId(final String actionId) {
        this.actionId = actionId;
    }

    @Column(nullable = false)
    public String getName() {
        return this.name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "actionlist")
    @OrderColumn(name = "position")
    public List<ActionItem> getItems() {
        return this.items;
    }

    public void setItems(final List<ActionItem> items) {
        this.items = items;
    }

    @Override
    public boolean equals(final Object obj) {

        if (obj == null) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof ActionList)) {
            return false;
        }
        final ActionList other = (ActionList) obj;

        return getActionId().equals(other.getActionId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getActionId());
    }
}

这是项目的类:

@Entity
public class ActionItem {

    private String id;
    private ActionList actionList;
    private int position = 0;
    private String name;

    @Id
    public String getId() {
        return this.id;
    }

    public void setId(final String id) {
        this.id = id;
    }

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "actionList_id", nullable = false)
    public ActionList getActionList() {
        return this.actionList;
    }

    public void setActionList(final ActionList actionList) {
        this.actionList = actionList;
    }

    @Column(name = "position")
    public Integer getPosition() {
        return this.position;
    }

    public void setPosition(final Integer position) {
        this.position = position;
    }

    public String getName() {
        return this.name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    @Override
    public boolean equals(final Object obj) {

        if (obj == null) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof ActionItem)) {
            return false;
        }
        final ActionItem other = (ActionItem) obj;

        if (StringUtils.isNotEmpty(getId()) && StringUtils.isNotEmpty(other.getId())) {
            return getId().equals(other.getId());
        }
        return getActionList().equals(other.getActionList()) && getPosition().equals(other.getPosition());
    }

    @Override
    public int hashCode() {

        if (StringUtils.isNotEmpty(getId())) {
            return Objects.hash(this.getId());
        } else {
            return Objects.hash(this.getActionList(), this.getPosition());
        }
    }
}

我的问题是,当我在添加一些项目后从项目集合中删除时,第一个元素也会被删除...

以下是我一直在使用的测试:

@Test
public void testAddAndDelete() {

    final ActionList actionList = new ActionList();
    actionList.setActionId("testActionList");
    actionList.setName("testActionList");

    eManager.persist(actionList);

    final String actionListId = actionList.getId();

    ActionList actionListFromDB = eManager.getById("ActionList", actionListId);

    ActionItem itemToRemove = null;

    for (int f = 0; f < 5; f++) {

        final ActionItem newItem = new ActionItem();
        newItem.setActionList(actionListFromDB);
        newStep.setName("itemname" + f);
        actionListFromDB.getItems().add(newItem);

        eManager.persist(newItem);

        eManager.merge(actionListFromDB);
        if (f == 3) {
            itemToRemove = newItem;
        }
    }

    eManager.commit();

    actionListFromDB = eManager.getById("ActionList", actionListId);
    actionListFromDB.getItems().remove(itemToRemove);

    eManager.merge(actionListFromDB);
    eManager.commit();
}

如果我在删除之前查看数据库,我会在ActionItem表中查看:

ID                                      ACTIONLIST_ID                           POSITION    NAME
fbb3ddae-f8b7-11e4-8d6c-b9778e934988    f51846ca-f8b7-11e4-8d6c-1ba6d68e492d    0           itemname0
fbb56453-f8b7-11e4-8d6c-dfaa3c092bd0    f51846ca-f8b7-11e4-8d6c-1ba6d68e492d    1           itemname1
fbb60098-f8b7-11e4-8d6c-154d56d0c562    f51846ca-f8b7-11e4-8d6c-1ba6d68e492d    2           itemname2
fbb675cd-f8b7-11e4-8d6c-21a3cc2b3c81    f51846ca-f8b7-11e4-8d6c-1ba6d68e492d    3           itemname3
fbb71212-f8b7-11e4-8d6c-8f7c1ecfd151    f51846ca-f8b7-11e4-8d6c-1ba6d68e492d    4           itemname4

然后我检查了ActionList对象,它的集合在删除后肯定有4个项目(这是正确的),它们的位置属性是不正常的(我希望自从中间删除)。

但是一旦我让删除后的提交通过,表格最终会显示:

ID                                      ACTIONLIST_ID                           POSITION    NAME
fbb56453-f8b7-11e4-8d6c-dfaa3c092bd0    f51846ca-f8b7-11e4-8d6c-1ba6d68e492d    1           itemname1
fbb60098-f8b7-11e4-8d6c-154d56d0c562    f51846ca-f8b7-11e4-8d6c-1ba6d68e492d    2           itemname2
fbb71212-f8b7-11e4-8d6c-8f7c1ecfd151    f51846ca-f8b7-11e4-8d6c-1ba6d68e492d    3           itemname4

因此,删除了正确的元素,但是:

  1. 它也删除了第一个
  2. 位置属性不再正确(从1到3而不是从0开始)。
  3. 我知道现在支持带有mappedBy的@OrderColumn,所以我不认为这是 - 我怀疑hashCode()有些可疑,但事实上该集合在ActionList对象中看起来没问题坚持有点奇怪......

    我在日志中没有从Hibernate获得任何异常。

1 个答案:

答案 0 :(得分:0)

与以往一样,是一个映射问题。

将ActionItem上的映射更改为:

   @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
   @JoinColumn(name = "actionList_id", nullable = false)
   public ActionList getActionList() {
     return this.actionList;
   }

修正了它。