[{ALLOW view All}] [{ALLOW edit Authenticated}] !Mapping a many-to-many join table with extra column(s) using JPA As of 23.02.2010 There seams to be only following two blogs in the web where this is described: [boris.kirzner.info/blog/archives/2008/07/19|http://boris.kirzner.info/blog/archives/2008/07/19/hibernate-annotations-the-many-to-many-association-with-composite-key/] [sieze.wordpress.com/2009/09/04|http://sieze.wordpress.com/2009/09/04/mapping-a-many-to-many-join-table-with-extra-column-using-jpa/] But this solution does not work with EclipseLink, because obvioulsy EclipseLink does only allow simple Java types as primary key fields in the Embeddable class. I am still a newby in JPA and had some difficulties to solve it, so I tried to use some tools: !Database Tools Though owned by Oracle now, I still use MySql. My choice for designing tables and relations\\ is [MySql Workbench|http://www.mysql.de/products/workbench/]. You can easily syncronize your model with the database (Menu > Database).\\ So I "Reverse Engineer..." my few database tables so far into a new model, changed it and "Synchronize Model..." back to the database.\\ To validate what happens on the database I used additionally [Squirrel|http://squirrel-sql.sourceforge.net/] for SQL. !Eclipse In Eclipse you can create a "JPA Project". This comes from a project called [Dali|http://www.eclipse.org/webtools/dali/] and is part of the WTP (Web Tools Plattform). You can update Eclipse with following update source:\\ __http://download.eclipse.org/webtools/updates/__ Please make sure to use the latest Dali update, otherwise it will not create the additional properties in the join table (see below)! When you created a JPA Project, you can find \\ __Context Menu > New > Entities From Table__ Then a wizard comes up, where you can select your table and adjust your mappings. Then Eclipse created all entity classes with all annotations. Perfect stuff - now I don't need to rack my brain about this!\\ The nice thing is that you can test various models and see how this would look with JPA. I tried also the model from the links above and this came out.\\ "color", "isAdmin" and "name" are the (stupid) additional properties\\ in ProductItem. !Item [{Java2HtmlPlugin package ebel; import java.io.Serializable; import javax.persistence.*; import java.util.List; /** * The persistent class for the item database table. * */ @Entity @Table(name="item") public class Item implements Serializable { private static final long serialVersionUID = 1L; @Id @SequenceGenerator(name="ITEM_ITEMID_GENERATOR" ) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ITEM_ITEMID_GENERATOR") @Column(name="item_id") private int itemId; private String name; //bi-directional many-to-one association to ProductItem @OneToMany(mappedBy="item") private List<ProductItem> productItems; public Item() { } public int getItemId() { return this.itemId; } public void setItemId(int itemId) { this.itemId = itemId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public List<ProductItem> getProductItems() { return this.productItems; } public void setProductItems(List<ProductItem> productItems) { this.productItems = productItems; } } }] !Product [{Java2HtmlPlugin package ebel; import java.io.Serializable; import javax.persistence.*; import java.util.List; /** * The persistent class for the product database table. * */ @Entity @Table(name="product") public class Product implements Serializable { private static final long serialVersionUID = 1L; private int productId; private String name; private List<ProductItem> productItems; public Product() { } @Id @SequenceGenerator(name="PRODUCT_PRODUCTID_GENERATOR" ) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PRODUCT_PRODUCTID_GENERATOR") @Column(name="product_id") public int getProductId() { return this.productId; } public void setProductId(int productId) { this.productId = productId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } //bi-directional many-to-one association to ProductItem @OneToMany(mappedBy="product") public List<ProductItem> getProductItems() { return this.productItems; } public void setProductItems(List<ProductItem> productItems) { this.productItems = productItems; } } }] !ProductItem [{Java2HtmlPlugin package ebel; import java.io.Serializable; import javax.persistence.*; /** * The persistent class for the product_item database table. * */ @Entity @Table(name="product_item") public class ProductItem implements Serializable { private static final long serialVersionUID = 1L; private ProductItemPK id; private String color; private byte isAdmin; private String name; private Item item; private Product product; public ProductItem() { } @EmbeddedId public ProductItemPK getId() { return this.id; } public void setId(ProductItemPK id) { this.id = id; } public String getColor() { return this.color; } public void setColor(String color) { this.color = color; } public byte getIsAdmin() { return this.isAdmin; } public void setIsAdmin(byte isAdmin) { this.isAdmin = isAdmin; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } //bi-directional many-to-one association to Item @ManyToOne @JoinColumn(name="item_id") public Item getItem() { return this.item; } public void setItem(Item item) { this.item = item; } //bi-directional many-to-one association to Product @ManyToOne @JoinColumn(name="product_id") public Product getProduct() { return this.product; } public void setProduct(Product product) { this.product = product; } } }] !ProductItemPk [{Java2HtmlPlugin package ebel; import java.io.Serializable; import javax.persistence.*; /** * The primary key class for the product_item database table. * */ @Embeddable public class ProductItemPK implements Serializable { //default serial version id, required for serializable classes. private static final long serialVersionUID = 1L; private int itemId; private int productId; public ProductItemPK() { } @Column(name="item_id") public int getItemId() { return this.itemId; } public void setItemId(int itemId) { this.itemId = itemId; } @Column(name="product_id") public int getProductId() { return this.productId; } public void setProductId(int productId) { this.productId = productId; } public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof ProductItemPK)) { return false; } ProductItemPK castOther = (ProductItemPK)other; return (this.itemId == castOther.itemId) && (this.productId == castOther.productId); } public int hashCode() { final int prime = 31; int hash = 17; hash = hash * prime + this.itemId; hash = hash * prime + this.productId; return hash; } } }]