2014-10-29 106 views
0

我將帶有註解映射的NHibernate XML映射轉換爲Java的一些C#,並且存在一個我試過轉換沒有成功的實體。我們有一個MAIN_TABLE,一個JOIN_TABLE和一個THIRD_TABLE。來自MAIN_TABLE的一條記錄可以有許多來自THIRD_TABLE,並且它們的關係存儲在JOIN_TABLE中,JOIN_TABLE只有三列:由MAIN_TABLE和THIRD_TABLE中的鍵組成的主鍵,以及包含一些不相關的附加數據的第三行。原來這是NHibernate的XML映射:使用帶註釋的複合主鍵進行元素映射

<class name="MainTable" table="MAIN_TABLE" mutable="false"> 
<id name="Id" column="rvcplc" type="int" length="10"> 
    <generator class="assigned"/> 
</id> 
<bag name="JoinedRecords" table="JOIN_TABLE" order-by="main_table_id"> 
    <key column="main_table_id" not-null="true"/> 
    <composite-element class="JoinTable"> 
    <parent name="parentRecord"/> 
    <many-to-one name="ThirdTable" column="third_table_id"/> 
    </composite-element> 
</bag> 

這是我的代碼的當前狀態:

@Entity() 
@Table(name="MAIN_TABLE") 
@Immutable 
public class MainTable extends BusinessEntity implements IMainTable 
{ 
    @Id 
    @Type(type = "LongToNull") 
    @Column(name = "id") 
    private long id; 

    @ElementCollection 
    @CollectionTable(name="JOIN_TABLE", joinColumns={@JoinColumn(name="main_table_id")}) 
    private List<IJoinTable> joinedRecords = new ArrayList<IJoinTable>(); 
} 

@Embeddable() 
@Table(name = "JOIN_TABLE") 
@Immutable 
public class JoinTable implements Serializable, IJoinTable 
{ 
    @SuppressWarnings("unused") 
    @Id 
    private JoinTablePK pkId; 

    @Parent 
    @Column(name = "main_table_id") 
    private IMainTable parentRecord; 

    @ManyToOne(targetEntity = ThirdTable.class) 
    @JoinColumn(name = "third_table_id") 
    private IThirdTable thirdTable; 

    public static class JoinTablePK implements Serializable 
    { 
      // foo 
    } 
} 

當我嘗試單元測試這種關聯,只需加載已知MainTable實體,並聲稱它在其集合中有三個子JoinTable對象失敗,出現「無法初始化集合」錯誤。不過,這是我最好的代碼,因爲其他嘗試已經使我所有的測試都失敗了,因爲它在映射錯誤時發生。

回答

2

這就是我將如何做到這一點(我將在代碼中使用簡單的類,希望超類和接口與問題無關)。

有兩種選擇。首先,更容易的是,如果JOIN_TABLE中的「無關附加數據」與模型真的無關。

@Entity 
@Table(name="MAIN_TABLE") 
public class MainTable { 
    @Id 
    @Type(type = "LongToNull") 
    private long id; 

    @ManyToMany 
    @JoinTable(name = "JOIN_TABLE", joinColumns = @JoinColumn(name = "JOIN_TABLE_ID"), 
     inverseJoinColumns = @JoinColumn(name = "THIRD_TABLE_ID") 
    private List<ThirdTable> thirdTableRecords = new ArrayList<ThirdTable>(); 
} 

@Entity 
@Table(name="THIRD_TABLE") 
public class ThirdTable { 
    @Id 
    @Type(type = "LongToNull") 
    private long id; 

    @ManyToMany(mappedBy = "thirdTableRecords") 
    private List<MainTable> mainTableRecords = new ArrayList<MainTable>(); 

    ... 
} 

如果「無關的附加數據」仍然需要進行建模,則實體將是這個樣子

@Entity 
@Table(name="MAIN_TABLE") 
public class MainTable { 
    @Id 
    @Type(type = "LongToNull") 
    private long id; 

    @OneToMany(mappedBy = "mainTable") 
    private List<JoinTable> joinTableRecords = new ArrayList<JoinTable>(); 
} 

@Entity 
@Table(name="THIRD_TABLE") 
public class ThirdTable { 
    @Id 
    @Type(type = "LongToNull") 
    private long id; 

    @OneToMany(mappedBy = "thirdTable") 
    private List<JoinTable> joinTableRecords = new ArrayList<joinTable>(); 

    ... 
} 

@Entity 
@Table(name="JOIN_TABLE") 
public class JoinTable { 
    @EmbeddedId 
    private JoinTablePK pkId; 

    private String irrelevantData; 

    @ManyToOne 
    @JoinColumn(name = "MAIN_TABLE_ID", insertable = false, updateable = false) 
    private MainTable mainTable; 

    @ManyToOne 
    @JoinColumn(name = "THIRD_TABLE_ID", insertable = false, updateable = false) 
    private ThirdTable thirdTable; 

    ... 
} 

@Embeddable 
public class JoinTablePK { 
    @Column(name = "MAIN_TABLE_ID") 
    private Long mainTableId; 

    @Column(name = "THIRD_TABLE_ID") 
    private Long thirdTableId; 

    // getters and setters 
} 

insertable = falseupdateable = false在那裏,因爲你映射兩個字段相同的列,一列只能有一個可寫字段。

我沒有測試代碼,所以如果它可以正常工作,我會感到很驚訝,但希望它能給你一些指導方針,並且你至少可以在解決方案上多走幾步。 。

+0

首先,感謝您的回答。可悲的是,「不相關的附加數據」必須進行映射,因爲它與關係無關,但包含的數據必須在代碼中使用。所以我試過你的第二個例子,我得到一個「AnnotationException:JoinTable $ JoinTablePK沒有持久性id屬性」任何想法? – CMPerez 2014-11-03 09:39:06

+0

我知道它不會工作,因爲它:)通過查看類似的問題,你有'getTablePK'類,'mainTableId'和'thirdTableId'的getter和setter? – 2014-11-03 10:06:11

+0

@Picacodigos我已經添加了'JoinTablePK'代碼以供參考,以獲得完整的圖片和下一次嘗試的完整基礎 – 2014-11-03 10:43:31

0

除了Predrag Maric建議的方法外,還有另一種方法。這裏詳細說明:http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/

我已經添加了這個回覆,以防鏈接對其他人有用。這是我的完整代碼:

@Entity() 
@Table(name="MAIN_TABLE") 
@Immutable 
public class MainTable extends BusinessEntity implements IMainTable 
{ 
    @Id 
    @Type(type = "LongToNull") 
    @Column(name = "MAIN_TABLE_ID") 
    private long id; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.parentRecord", targetEntity =  JoinTable.class) 
    private List<IJoinTable> joinedRecords = new ArrayList<IJoinTable>(); 
} 

@Entity 
@Table(name = "JOIN_TABLE") 
@AssociationOverrides({ 
    @AssociationOverride(name="pk.parentMainTable", joinColumns = @JoinColumn(name="MAIN_TABLE_ID")), 
    @AssociationOverride(name="pk.parentThirdTable", joinColumns = @JoinColumn(name="THIRD_TABLE_ID")) 
     }) 
public class JoinTable implements Serializable, IJoinTable 
{ 
    private JoinTablePK pkId; 
    private BigDecimal irrelevantData; 

    // Ctor 
    public JoinTable(MainTable mainTable, ThirdTable thirdTable) 
    { 
     pk = new JoinTablePK(mainTable, thirdTable); 
    } 

    @EmbeddedId 
    public JoinTablePK getPk() 
    { 
     return pk; 
    } 

    // here goes the setter, no annotations 

    @Transient 
    public IMainTable getMainTable() 
    { 
     return getPk().getMainTable(); 
    } 

    // here goes the setter, no annotations 

    @Transient 
    public IThirdTable getThirdTable() 
    { 
     return getPk().getThirdTable(); 
    } 

    // here goes the setter, no annotations 

    @Column(name = "JOIN_TABLE_IRRELEVANT_DATA") 
    public BigDecimal getIrrelevantData() 
    { 
     return irrelevantData; 
    } 

    // here goes the setter, no annotations 

    /** 
    * PRIMARY KEY CLASS 
    */ 
    @Embeddable 
    public static class JoinTablePK implements Serializable 
    { 
     private MainTable parentMainTable; 

     @ManyToOne 
     public MainTable getParentMainTable() 
     { 
     return parentMainTable; 
     } 

     // here goes the setter, no annotations 

     private ThirdTable parentThirdTable; 

     @ManyToOne 
     public ThirdTable getParentThirdTable() 
     { 
     return parentThirdTable(); 
     } 

     // here goes the setter, no annotations 

     // empty ctor 
     public JoinTablePK() {} 

     // ctor with parameters 
     public JoinTablePK(MainTable parentMainTable, ThirdTable parentThirdTable) 
     { 
     this.parentMainTable = parentMainTable; 
     this.parentThirdTable = parentThirdTable; 
     } 

     // rest of the class, implement equals() and hashCode() 
    } 
}