两张表具有相同的复合主键,且一个表的主键是另外一个表的外键
这个问题困扰了我很久,后来在Google上搜索了很久,终于找到了问题的答案,经过测试,确实可以正确使用。在这里记录下来,方便自己和大家。
问题是这样的:
例如两张表 PRODUCTS和TRANSLATIONS
两张表结构的sql语句为:
create table Products ( sku varchar(128) not null, manuf integer not null, catalog varchar(128) not null, primary key (sku, manuf, catalog) ); create table Translations ( sku varchar(128) not null, manuf integer not null, catalog varchar(128) not null, DESC varchar(255), primary key (sku, manuf, catalog) ); alter table Products add constraint FKC8063584DF6EA216 foreign key (sku, manuf, catalog) references Translations;
由于这两个表具有相同的主键,所以两个表的实体类需要相同的联合主键类。对于这两个表的实体类可以这样表示:
首先需要定义好主键类,主键类需要继承java.io.Serializable接口,且需要重写equals和hashcode方法。
ProductId.java
package hello; import java.io.Serializable; /** * Created by orz on 16-2-28. */ public class ProductId implements Serializable { private static final long serialVersionUID = 1L; private String sku; private int manuf; private String catalog; public String getSku() { return sku; } public void setSku(String sku) { this.sku = sku; } public int getManuf() { return manuf; } public void setManuf(int manuf) { this.manuf = manuf; } public String getCatalog() { return catalog; } public void setCatalog(String catalog) { this.catalog = catalog; } public boolean equals(Object other) { if (other == null) return false; if (!this.getClass().equals(other.getClass())) return false; ProductId otherId = (ProductId) other; if (this.catalog.equals(otherId.catalog) && this.manuf == otherId.manuf && this.sku.equals(otherId.sku)) { return true; } else return false; } public int hashCode() { int result; result = catalog.hashCode(); result = 29 * result + manuf; result = 29 * result + sku.hashCode(); return result; } }
package hello; /** * Created by orz on 16-2-28. */ public class Product { private ProductId id; public ProductId getId() { return id; } public void setId(ProductId id) { this.id = id; } public Translation getTranslation() { return translation; } public void setTranslation(Translation translation) { this.translation = translation; } private Translation translation; }
package hello; /** * Created by orz on 16-2-28. */ public class Translation { private ProductId id; private String description; public ProductId getId() { return id; } public void setId(ProductId id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
Product.hbm.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="hello.Product" table="Products"> <composite-id class="hello.ProductId" name="id"> <key-property name="sku" type="string"> <column length="128" name="sku"/> </key-property> <key-property name="manuf" type="int"> <column name="manuf"/> </key-property> <key-property name="catalog" type="string"> <column length="128" name="catalog"/> </key-property> </composite-id> <one-to-one name="translation" constrained="true" class="hello.Translation" cascade="save-update"/> </class> </hibernate-mapping>
Translation.hbm.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="hello.Translation" table="Translations"> <composite-id class="hello.ProductId" name="id"> <key-property name="sku" type="string"> <column length="128" name="sku"/> </key-property> <key-property name="manuf" type="int"> <column name="manuf"/> </key-property> <key-property name="catalog" type="string"> <column length="128" name="catalog"/> </key-property> </composite-id> <property name="description" column="DESC"></property> </class> </hibernate-mapping>好了,这样就可以了。可以用测试类测试一下。
package hello; import org.hibernate.Session; import org.hibernate.Transaction; import persistence.HibernateUtil; import java.util.Iterator; import java.util.List; /** * Created by orz on 16-2-21. */ public class HelloWorld { public static void main(String[] args) { Session productSession1 = HibernateUtil.getSessionFactory().openSession(); Transaction productTransaction1 = productSession1.beginTransaction(); ProductId pid = new ProductId(); pid.setCatalog("catalog"); pid.setManuf(11); pid.setSku("sku"); Translation translation = new Translation(); translation.setId(pid); translation.setDescription("description"); Product testProduct = new Product(); testProduct.setId(pid); testProduct.setTranslation(translation); ProductId pid2 = new ProductId(); pid2.setCatalog("catalog2"); pid2.setManuf(22); pid2.setSku("sku2"); Translation translation2 = new Translation(); translation2.setId(pid2); translation2.setDescription("description2"); Product testProduct2 = new Product(); testProduct2.setId(pid2); testProduct2.setTranslation(translation2); productSession1.save(testProduct); productSession1.save(testProduct2); productTransaction1.commit(); productSession1.close(); Session productSession2 = HibernateUtil.getSessionFactory().openSession(); Transaction productTransaction2 = productSession2.beginTransaction(); List products = productSession2.createQuery("from Product p ").list(); System.out.println(products.size() + " product(s) found"); for (Iterator iter = products.iterator(); iter.hasNext();) { Product product = (Product) iter.next(); System.out.println("Product: " + product.getId().getSku() + ", " + product.getId().getManuf() + ", " + product.getId().getCatalog() +", translation: " + product.getTranslation().getDescription()); } productTransaction2.commit();; productSession2.close(); //Shutting down the application HibernateUtil.shutdown(); } }
package persistence; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * Created by orz on 16-2-21. */ public class HibernateUtil { private static SessionFactory sessionFactory; static { try { sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { //Alternatively,you could look up in JNDI here return sessionFactory; } public static void shutdown() { //Close caches and connection pools getSessionFactory().close(); } }