2

在过去的 4 个小时里,我一直在拼命地尝试使以下映射工作。

@Entity
public class Foo {

    @Basic
    private String bar;

    @Id
    @Column(name = "FOO_ID")
    @Type(type = "foo.bar.OracleGuidType")
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    private UUID id;

    @ManyToMany(mappedBy = "parentFoos", fetch = FetchType.EAGER)
    @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
    @MapKeyColumn(name = "NESTED_FOO_KEY")
    private Map<String, Foo> nestedFoos = new
            HashMap<String, Foo>();

    @ManyToMany
    @JoinTable(
            name = "FOO_RELATIONSHIP",
            joinColumns = @JoinColumn(name = "NESTED_FOO_ID",
                                      referencedColumnName = "FOO_ID"),
            inverseJoinColumns = @JoinColumn(name = "PARENT_FOO_ID",
                                             referencedColumnName = "FOO_ID")
    )
    private Set<Foo> parentFoos = new HashSet<Foo>();
    //getters/setters

}

映射可能很复杂,但这就是要求。

问题是当我尝试执行以下操作时

    Foo parent = new Foo();
    parent.setWhatever("parent");
    Foo child = new Foo();
    child.setWhatever("child");

    Session currentSession = sessionFactory.getCurrentSession();
    Transaction tx = currentSession.getTransaction();
    tx.begin();
    currentSession.saveOrUpdate(child);
    tx.commit();

    currentSession = sessionFactory.getCurrentSession();
    tx = currentSession.getTransaction();
    tx.begin();
    child.getParentFoos().add(parent);
    parent.getNestedFoos().put("ASDF_KEY", child);
    currentSession.saveOrUpdate(parent);
    tx.commit();

我得到的是:
Hibernate:插入 Foo(whatever,FOO_ID)值(?,?)
Hibernate:插入 Foo(whatever,FOO_ID)值(?,?)
Hibernate:更新 Foo 设置whatever=?FOO_ID=?
Hibernate:插入 FOO_RELATIONSHIP (NESTED_FOO_ID, PARENT_FOO_ID) 值 (?, ?)

似乎休眠忽略了mapkeycolumn(尽管它通过hbm2ddl创建了一个),接下来我得到的是这个异常

原因:java.sql.BatchUpdateException: ORA-01400: 无法将 NULL 插入 ("BAR"."FOO_RELATIONSHIP"."NESTED_FOO_KEY")

我相信,这个实体是可以映射的。请帮我解决这个问题。

4

1 回答 1

1

我设法通过引入一个中间实体“映射”来解决这个问题。

这是我设法完成的工作。

@Entity
@Table(name = "FOO")
public class Foo {

    @Basic
    private String bar;

    @Id
    @Column(name = "FOO_ID")
    @Type(type = "foo.bar.OracleGuidType")
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    private UUID id;

    @OneToMany(mappedBy = "parentEntity", fetch = FetchType.EAGER,
            cascade = CascadeType.ALL)
    private Set<Mapping> nestedFoos = new HashSet<>();

    @OneToMany(mappedBy = "childEntity", fetch = FetchType.EAGER,
            cascade = CascadeType.ALL)
    private Set<Mapping> parentFoos = new HashSet<>();

    @Transient
    private Map<String, Foo> _nestedFoos = new HashMap<>();

    @Transient
    private Set<Foo> _parentFoos = new HashSet<>();

    @PostLoad
    @PostUpdate
    @PostPersist
    private void fillTransientFields() {
        _nestedFoos.clear();
        _parentFoos.clear();
        for (Mapping mapping : nestedFoos) {
            _nestedFoos.put(mapping.getMappingKey(), mapping.getChildEntity());
        }
        for (Mapping mapping : parentFoos) {
            _parentFoos.add(mapping.getParentEntity());
        }
    }

    public Map<String, Foo> geNestedFoos() {
        return Collections.unmodifiableMap(_nestedFoos);
    }

    public Set<Foo> getParentFoos() {
        return Collections.unmodifiableSet(_parentFoos);
    }

    public void addParent(String key, Foo parent) {
        Mapping mapping = new Mapping();
        mapping.setMappingKey(key);
        mapping.setChildEntity(this);
        mapping.setParentEntity(parent);
        parentFoos.add(mapping);
    }

    public void addChild(String key, Foo child) {
        Mapping mapping = new Mapping();
        mapping.setMappingKey(key);
        mapping.setChildEntity(child);
        mapping.setParentEntity(this);
        nestedFoos.add(mapping);
    }

    public void removeChild(String key) {
        for (Mapping mapping : nestedFoos) {
            if (mapping.getMappingKey().equals(key)) {
                nestedFoos.remove(mapping);
            }
        }
    }
}

@Entity
@Table(name = "FOO_MAPPING_TABLE",
        uniqueConstraints = {@UniqueConstraint(columnNames =
                {"MAPPING_KEY", "PARENT_ENTITY_ID"})})
class Mapping {

    @Basic
    @Column(name = "MAPPING_KEY")
    private String mappingKey;

    @Id
    @GenericGenerator(name = "generator", strategy = "increment")
    @GeneratedValue(generator = "generator")
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "PARENT_ENTITY_ID", nullable = false, updatable = false)
    private Foo parentEntity;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CHILD_ENTITY_ID", nullable = false, updatable = false)
    private Foo childEntity;
}

请注意,由于以下错误,这在 Hibernate 3.6.9.Final 中不起作用

于 2013-09-29T19:28:01.810 回答