2013-09-26 101 views
2

在過去的4個小時裏,我一直在拼命試圖進行以下映射工作。Hibernate無法將Map集合映射到ManyToMany

@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(); 

什麼,我得到的是這樣的:
休眠:(?)插入到富(不管,FOO_ID)值
休眠:insert into Foo(whatever,FOO_ID)values(?,?)
Hibernate:update Foo set whatever =?其中FOO_ID =?
休眠:插入FOO_RELATIONSHIP(NESTED_FOO_ID,PARENT_FOO_ID)值

似乎休眠忽略mapkeycolumn(雖然它創建一個先得用hbm2ddl)和我所得到的未來是這樣的例外

(?,?) java.sql.BatchUpdateException:ORA-01400:

致無法將NULL插入( 「BAR」, 「FOO_RELATIONSHIP」 「NESTED_FOO_KEY」。)

我相信,這個實體可以映射。請幫我解決這個問題。

+0

請張貼表結構。 –

回答

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工作,因爲以下Bug