Hibernate - сущность, ссылающаяся на себя через таблицу соединений с дополнительным столбцом - PullRequest
1 голос
/ 22 сентября 2011

У меня есть аннотированный объект с именем Part.Он состоит из идентификатора и нескольких других переменных.У меня есть еще одна таблица под названием "bomdefinitions".Эта таблица имеет три столбца (кол-во, родитель, цель) (я понимаю, что цель - это глупое имя, но я не могу изменить его, так как база данных уже существует).Идея состоит в том, что Часть может состоять из многих других частей, а также может использоваться во многих других частях, и таблица "bomdefinitions" сообщает, у какого родителя есть какие "цели" связаны с ним и сколько их использует.

Проблема в том, что, если я закомментирую одно из отношений OneToMany в Part.java и оставлю другое, оно работает нормально, но если они есть в моем коде, попытка получить доступ к любому из них приводит кбесконечный цикл запросов Hibernate.

Я могу найти примеры сопоставления сущности с самим собой, примеры сопоставления сущности с использованием таблицы соединения с дополнительными столбцами и примеры различных способов сделать аннотации, но ничего не делатьвсе это в одном приложении, и отдельные примеры, которые я могу найти, похоже, здесь не помогают.

У кого-то с большим опытом работы в Hibernate есть какие-либо идеи относительно того, что я делаю неправильно?

Редактировать (этот код вызывает бесконечный цикл):

getHibernateTemplate().get(Part.class, id).getParentBomDefinitions();

А вот запрос в выводе - он начинается с:

Hibernate: select part0_.id as id0_3_, childbomde1_.target as target0_5_, childbomde1_.parent as parent5_, childbomde1_.target as target5_, childbomde1_.parent as parent4_0_, childbomde1_.target as target4_0_, childbomde1_.qty as qty4_0_, part2_.id as id0_1_ from parts part0_ left outer join bomdefinitions childbomde1_ on part0_.id=childbomde1_.target left outer join parts part2_ on childbomde1_.parent=part2_.id
Hibernate: select parentbomd0_.parent as parent0_2_, parentbomd0_.parent as parent2_, parentbomd0_.target as target2_, parentbomd0_.parent as parent4_1_, parentbomd0_.target as target4_1_, parentbomd0_.qty as qty4_1_, part1_.id as id0_0_ from bomdefinitions parentbomd0_ left outer join parts part1_ on parentbomd0_.target=part1_.id where parentbomd0_.parent=?

Затем эти 2 запроса повторяются бесконечно:

Hibernate: select parentbomd0_.parent as parent0_2_, parentbomd0_.parent as parent2_, parentbomd0_.target as target2_, parentbomd0_.parent as parent4_1_, parentbomd0_.target as target4_1_, parentbomd0_.qty as qty4_1_, part1_.id as id0_0_ from bomdefinitions parentbomd0_ left outer join parts part1_ on parentbomd0_.target=part1_.id where parentbomd0_.parent=?
Hibernate: select childbomde0_.target as target0_2_, childbomde0_.parent as parent2_, childbomde0_.target as target2_, childbomde0_.parent as parent4_1_, childbomde0_.target as target4_1_, childbomde0_.qty as qty4_1_, part1_.id as id0_0_ from bomdefinitions childbomde0_ left outer join parts part1_ on childbomde0_.parent=part1_.id where childbomde0_.target=?

BomDefinition.java (в значительной степени взято из "Java Persistence with Hibernate")

@Entity
@Table(name = "bomdefinitions")
public class BomDefinition {

@Embeddable
public static class Id implements Serializable {

    @Column(name = "target")
    private String targetId;

    @Column(name = "parent")
    private String parentId;

    public Id() {}
    public Id(String targetId, String parentId) {
        this.targetId = targetId;
        this.parentId = parentId;
    }
    public boolean equals(Object o) {
        if (o != null && o instanceof Id) {
            Id that = (Id) o;
            return this.targetId.equals(that.targetId) && this.parentId.equals(that.parentId);
        } else {
            return false;
        }
    }
    public int hashCode() {
        return targetId.hashCode() + parentId.hashCode();
    }
}

@EmbeddedId
private Id id = new Id();

@Column(name = "qty")
private String quantity;

@ManyToOne
@JoinColumn(name = "parent",
            insertable = false,
            updatable = false)
private Part parent;

@ManyToOne
@JoinColumn(name = "target",
            insertable = false,
            updatable = false)
private Part child;

public BomDefinition() {}

public BomDefinition(String quantity, Part parent, Part child) {
    this.quantity = quantity;
    this.parent = parent;
    this.child = child;

    this.id.parentId = parent.getId();
    this.id.targetId = child.getId();
}

// Getters and Setters
}

Part.java:

@Entity
@Table(name="parts", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
public class Part implements Serializable {

protected final Logger log = Logger.getLogger(getClass());

private String id;
// *** other variables ***

public Part() {}

public Part(String id, /* other variables */) {
    this.id = id;
    // *** other variables ***
}

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public String getId() {
    return this.id;
}
public void setId(String id) {
    this.id = id;
}

private Set parentBomDefinitions = new HashSet(0);
private Set childBomDefinitions = new HashSet(0);

@OneToMany(mappedBy = "parent",
            targetEntity = BomDefinition.class,
            cascade = {CascadeType.PERSIST, CascadeType.MERGE},
            fetch = FetchType.EAGER)
public Set getParentBomDefinitions() {
    return parentBomDefinitions;
}
public void setParentBomDefinitions(Set<BomDefinition> parentBomDefinitions) {
    this.parentBomDefinitions = parentBomDefinitions;
}

@OneToMany(mappedBy = "child",       // target?
            targetEntity = BomDefinition.class,
            cascade = {CascadeType.PERSIST, CascadeType.MERGE},
            fetch = FetchType.EAGER)
public Set getChildBomDefinitions() {
    return childBomDefinitions;
}
public void setChildBomDefinitions(Set childBomDefinitions) {
    this.childBomDefinitions = childBomDefinitions;
}

}
...