`

Hibernate中联合主键映射时有一个也是外键的一种解决方法

阅读更多
     昨天遇到一个联合主键的问题,困扰了我很久,最后发现《Hibernate in Action》里有讲到,因为在实际环境中老是报错,也不知配置的对不对,然后回家写了一个DEMO,发现可以保存。
表结构大致如下:
ITEM(ID,NAME)其中id是PK
CATEGORY(ID,NAME),其中ID是PK
CATEGORY_ITEM(ITEM_ID,CATEGORY_ID,THIRD_ID,ADDED_DATE),其中ITEM_ID,CATEGORY_ID分别是ITEM和CATEGORY的外键,而他们与THIRD_ID一起组成CATETORY_ITEM表的联合主键。
下面给出具体实现:
一、Item.java

/**
 * @author Terrence
 *
 */
public class Item implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Integer id;
	private String name;
	private Set<CategorizedItem> categorizedItems = new HashSet<CategorizedItem>();
	/**
	 * 
	 */
	public Item() {
		super();
	}
	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}
	/**
	 * @param id the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @return the categorizedItems
	 */
	public Set<CategorizedItem> getCategorizedItems() {
		return categorizedItems;
	}
	/**
	 * @param categorizedItems the categorizedItems to set
	 */
	public void setCategorizedItems(Set<CategorizedItem> categorizedItems) {
		this.categorizedItems = categorizedItems;
	}
	
	
}

二、Category.java
/**
 * @author Terrence
 *
 */
public class Category implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Integer id;
	private String name;
	private Set<CategorizedItem> categorizedItems = new HashSet<CategorizedItem>();
	
	public Category() {
		super();
	}
	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}
	/**
	 * @param id the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @return the categorizedItems
	 */
	public Set<CategorizedItem> getCategorizedItems() {
		return categorizedItems;
	}
	/**
	 * @param categorizedItems the categorizedItems to set
	 */
	public void setCategorizedItems(Set<CategorizedItem> categorizedItems) {
		this.categorizedItems = categorizedItems;
	}
	
	
}

三、CategorizedItem.java

/**
 * @author Terrence
 *
 */
public class CategorizedItem implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static class Id implements Serializable {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		private Integer thirdId;
		private Integer categoryId;
		private Integer itemId;
		/**
		 * 
		 */
		public Id() {
			super();
		}
		
		/**
		 * @return the thirdId
		 */
		public Integer getThirdId() {
			return thirdId;
		}

		/**
		 * @param thirdId the thirdId to set
		 */
		public void setThirdId(Integer thirdId) {
			this.thirdId = thirdId;
		}

		/**
		 * @return the categoryId
		 */
		public Integer getCategoryId() {
			return categoryId;
		}
		/**
		 * @param categoryId the categoryId to set
		 */
		public void setCategoryId(Integer categoryId) {
			this.categoryId = categoryId;
		}
		/**
		 * @return the itemId
		 */
		public Integer getItemId() {
			return itemId;
		}
		/**
		 * @param itemId the itemId to set
		 */
		public void setItemId(Integer itemId) {
			this.itemId = itemId;
		}
		/* (non-Javadoc)
		 * @see java.lang.Object#hashCode()
		 */
		@Override
		public int hashCode() {
			return this.categoryId.hashCode()+this.itemId.hashCode();
		}
		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object obj) {
			if(obj!=null&&obj instanceof Id){
				Id that = (Id)obj;
				return this.categoryId.equals(that.categoryId)&&this.itemId.equals(that.itemId);
			}else{
				return false;
			}
		}
		
	}
	
	private Id id = new Id();
	private Date dateAdded;
	private Item item;
	private Category category;
	/**
	 * 
	 */
	public CategorizedItem() {
		super();
	}
	/**
	 * @return the id
	 */
	public Id getId() {
		return id;
	}
	/**
	 * @param id the id to set
	 */
	public void setId(Id id) {
		this.id = id;
	}
	/**
	 * @return the dateAdded
	 */
	public Date getDateAdded() {
		return dateAdded;
	}
	/**
	 * @param dateAdded the dateAdded to set
	 */
	public void setDateAdded(Date dateAdded) {
		this.dateAdded = dateAdded;
	}
	/**
	 * @return the item
	 */
	public Item getItem() {
		return item;
	}
	/**
	 * @param item the item to set
	 */
	public void setItem(Item item) {
		this.item = item;
		this.id.itemId = item.getId();
		item.getCategorizedItems().add(this);
	}
	/**
	 * @return the category
	 */
	public Category getCategory() {
		return category;
	}
	/**
	 * @param category the category to set
	 */
	public void setCategory(Category category) {
		this.category = category;
		this.id.categoryId = category.getId();
		category.getCategorizedItems().add(this);
	}
	/**
	 * @return the thirdId
	 */
	public Integer getThirdId() {
		return this.id.getThirdId();
	}

	/**
	 * @param thirdId the thirdId to set
	 */
	public void setThirdId(Integer thirdId) {
		this.id.thirdId = thirdId;
	}
	
}

四、*.hbm.xml,这里节省时间空间写在了一起
<hibernate-mapping package="org.terrence.hrsystem.model">
	<class name="Item" table="ITEM">
      <id name="id" type="integer" column="ITEM_ID">
         <generator class="identity" />
      </id>
      <property name="name" type="string" not-null="true"
         update="false" column="ITEM_NAME" />
      <set name="categorizedItems" cascade="all, delete-orphan"
         inverse="true" lazy="false">
         <key column="ITEM_ID" not-null="true" />
         <one-to-many class="CategorizedItem" />
      </set>
   </class>

<class name="Category" table="CATEGORY">
      <id name="id" type="integer" column="CATEGORY_ID">
         <generator class="identity" />
      </id>
      <property name="name" type="string" column="CATEGORY_NAME" not-null="true"/>
      <set name="categorizedItems" cascade="all, delete-orphan"
         inverse="true" lazy="false">
         <key column="CATEGORY_ID" not-null="true" />
         <one-to-many class="CategorizedItem" />
      </set>
   </class>

<class name="Category" table="CATEGORY">
      <id name="id" type="integer" column="CATEGORY_ID">
         <generator class="identity" />
      </id>
      <class name="CategorizedItem" table="CATEGORIZED_ITEM" mutable="false">
	<composite-id name="id" class="CategorizedItem$Id">
	<key-property name="thirdId" column="THIRD_ID" type="integer"/>
	<key-property name="categoryId" column="CATEGORY_ID"
				type="integer" />
	<key-property name="itemId" column="ITEM_ID" type="integer" />
	</composite-id>
	<property name="dateAdded" column="ADDED_ON" type="timestamp"
			not-null="true" />

	<many-to-one name="item" class="Item" column="ITEM_ID"
			not-null="true" insert="false" update="false" />
	<many-to-one name="category" class="Category" column="CATEGORY_ID"
			not-null="true" insert="false" update="false" />
	</class>
</hibernate-mapping>


五、测试代码
/**   
* @Title: TestDao.java 
* @Package test 
* @Description: TODO(用一句话描述该文件做什么) 
* @author Terrence.zhung 
* @date 2011-3-29 上午02:45:05 
* @version V1.0   
*/ 

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.terrence.hrsystem.dao.CategorizedItemDao;
import org.terrence.hrsystem.dao.CategoryDao;
import org.terrence.hrsystem.dao.ItemDao;
import org.terrence.hrsystem.model.CategorizedItem;
import org.terrence.hrsystem.model.Category;
import org.terrence.hrsystem.model.Item;

/**
 * @author Terrence
 *
 */
public class TestDao {

	/**
	 * @param args
	 */
	private static ItemDao itemDao;
	private static CategoryDao categoryDao;
	private static CategorizedItemDao  categorizedItemDao;
	private static ApplicationContext ctx;
	
	public static void init(){
		if(ctx==null){
			ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext.xml","classpath:daoContext.xml"});
		}
		itemDao = (ItemDao)ctx.getBean("itemDao");
		categoryDao = (CategoryDao)ctx.getBean("categoryDao");
		categorizedItemDao = (CategorizedItemDao)ctx.getBean("categorizedItemDao");
	}
	public static void main(String[] args) throws Exception {
		init();
		saveItem();
		saveCategory();
		saveCategoryItem();
	}
	
	public static void saveItem() throws Exception{
		Item item = new Item();
		item.setName("item2");
		itemDao.save(item);
	}
	
	public static void saveCategory() throws Exception{
		Category category = new Category();
		category.setName("category2");
		categoryDao.save(category);
	}
	
	public static void saveCategoryItem() throws Exception{
		Item item = itemDao.get(1);
		Category category = categoryDao.get(1);
		CategorizedItem categorizedItem = new CategorizedItem();
		categorizedItem.setItem(item);
		categorizedItem.setCategory(category);
		categorizedItem.setDateAdded(new java.util.Date());
		categorizedItem.setThirdId(5);
		categorizedItemDao.save(categorizedItem);
	}

}



六、说明
    因为用了spring,在配置文件配好环境,表可以用hibernate直接生成,不用写SQL语句。
分享到:
评论
3 楼 abcd880129 2011-11-07  
是不是写错了,应该是Item的主键、Category的主键是CategorizedItem的外键,然后又和thirdId组成CategorizedItem的联合主键,看标题让我兴奋了一下,原来不是
2 楼 zhongrf 2011-11-07  
168_ccxx 写道
CategorizedItem 的配置文件貌似没看到啊..

不好意思,贴错了,现在补上了,谢谢哈
1 楼 168_ccxx 2011-10-30  
CategorizedItem 的配置文件貌似没看到啊..

相关推荐

    Hibernate注解

    * 9.increnment 插入数据的时候hibernate会给主键添加一个自增的主键,但是一个hibernate实例就维护一个计数器,所以在多个实例运行的时候不能使用这个方法。 * 例:@GeneratedValue(generator = ...

    Hibernate学习笔记_songjignhao_1

    有代码,包括:一对多双向关联关系、一对多双向自身关联关系、一对一关联关系(主键关联、外键关联)、一对多与一对一结合、多对多关联关系、Map、Set、List与Bag映射关系、查询排序(内存排序和数据库排序)、联合...

    Hibernate 中文 html 帮助文档

    4.1.1. 实现一个默认的(即无参数的)构造方法(constructor) 4.1.2. 提供一个标识属性(identifier property)(可选) 4.1.3. 使用非final的类 (可选) 4.1.4. 为持久化字段声明访问器(accessors)和是否可变的...

    Hibernate注释大全收藏

    整个层次结构中的所有父类和子类属性都映射到同一个表中,他们的实例通过一个辨别符列(discriminator)来区分。 Plane 是父类。@DiscriminatorColumn 注解定义了辨别符列。对于继承层次结构中的每个类, @...

    最全Hibernate 参考文档

    4.1.2. 实现一个默认的(即无参数的)构造方法(constructor) 4.1.3. 提供一个标识属性(identifier property)(可选) 4.1.4. 使用非final的类 (可选) 4.2. 实现继承(Inheritance) 4.3. 实现equals()和...

    Hibernate教程

    5.1.2. 实现一个默认的(即无参数的)构造方法(constructor) 5.1.3. 提供一个标识属性(identifier property)(可选) 5.1.4. 使用非final的类 (可选) 5.2. 实现继承(Inheritance) 5.3. 实现equals()和...

    hibernate3.04中文文档.chm

    5.1.2. 实现一个默认的(即无参数的)构造方法(constructor) 5.1.3. 提供一个标识属性(identifier property)(可选) 5.1.4. 使用非final的类 (可选) 5.2. 实现继承(Inheritance) 5.3. 实现equals()和...

    hibernate 体系结构与配置 参考文档(html)

    实现一个默认的(即无参数的)构造方法(constructor) 4.1.2. 提供一个标识属性(identifier property)(可选) 4.1.3. 使用非final的类 (可选) 4.1.4. 为持久化字段声明访问器(accessors)和是否可变的标志...

    Hibernate3+中文参考文档

    4.1.2. 实现一个默认的(即无参数的)构造方法(constructor) 4.1.3. 提供一个标识属性(identifier property)(可选) 4.1.4. 使用非final的类 (可选) 4.2. 实现继承(Inheritance) 4.3. 实现equals()和...

    Hibernate3的帮助文档

    5.1.2. 实现一个默认的(即无参数的)构造方法(constructor) 5.1.3. 提供一个标识属性(identifier property)(可选) 5.1.4. 使用非final的类 (可选) 5.2. 实现继承(Inheritance) 5.3. 实现equals()和...

    hibernate 框架详解

    实现一个默认的(即无参数的)构造方法(constructor) 5.1.3. 提供一个标识属性(identifier property)(可选) 5.1.4. 使用非final的类 (可选) 5.2. 实现继承(Inheritance) 5.3. 实现equals()和hashCode...

    Hibernate参考文档

    4.1.1. 实现一个默认的(即无参数的)构造方法(constructor) 4.1.2. 提供一个标识属性(identifier property)(可选) 4.1.3. 使用非final的类 (可选) 4.1.4. 为持久化字段声明访问器(accessors)和是否可变的...

    NHibernate中文帮组文档(2008.11月更新)

    5.1.5. (联合主键)composite-id 5.1.6. 鉴别器(discriminator) 5.1.7. 版本(version)(可选) 5.1.8. 时间戳 (可选) 5.1.9. 属性 5.1.10. 多对一 5.1.11. 一对一 5.1.12. 组件(component), 动态组件(dynamic-...

    NHibernate参考文档 2.0.0 chm

    5.1.5. (联合主键)composite-id 5.1.6. 鉴别器(discriminator) 5.1.7. 版本(version)(可选) 5.1.8. 时间戳 (可选) 5.1.9. 属性 5.1.10. 多对一 5.1.11. 一对一 5.1.12. 组件(component), 动态组件(dynamic-...

Global site tag (gtag.js) - Google Analytics