(经典)Hibernate的一对多关系映射(三)

一对多关系是表提出来的概念,两张表之间会存在这种,前提是有外键关联。

例如:省份和城市

如果设计类,怎样描述省份和城市之间的一对多关系

省份类里包含多个城市对象,使用 Set集合来描述

城市类里包含一个省份对象。

使用Hibernate开发时,如果表中存在一对多关系,而且这些表一起选择生成映射,则会自动生成包含一对多关系的类。

这里建立两张表(省份和城市)

CREATE TABLE province (
       id                   number(8)         primary key ,
       title                varchar2(20)      not null
);
INSERT INTO province VALUES (1,'江苏');
INSERT INTO province VALUES (2,'北京');
INSERT INTO province VALUES (3,'广东');
CREATE TABLE city (
       id                   number(8)         primary key ,
       title                varchar2(50)      not null,
       province_id          int               not null,
       foreign key (province_id) references province (id) on delete cascade
);
INSERT INTO city VALUES (1,'南通',1);
INSERT INTO city VALUES (2,'南京',1);
INSERT INTO city VALUES (3,'海淀区',2);
INSERT INTO city VALUES (4,'朝阳区',2);
INSERT INTO city VALUES (5,'广州',3);
INSERT INTO city VALUES (6,'深圳',3);
commit;
在MyEclipse中,两张表一起选择,生成映射

选择使用自增长方式来加入主键。

注意,要两张表一起。

生成好的类中存在了一对多的关系,看下vo类,这里get/set方法省略

public class City implements java.io.Serializable {

	private Integer id;
	private Province province;
	private String title;
}
public class Province implements java.io.Serializable {

	private Integer id;
	private String title;
	private Set cities = new HashSet(0);
}

映射文件中也说明了这个关系。

province映射:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="org.liky.otm.pojo.Province" table="PROVINCE" schema="SUNXUN">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="8" scale="0" />
            <generator class="increment" />
        </id>
        <property name="title" type="java.lang.String">
            <column name="TITLE" length="20" not-null="true" />
        </property>
        <!-- 
        	在Province中包含一个名称为cities的Set集合.
        -->
        <set name="cities" inverse="true">
        	<!-- 
        		关联外键是PROVINCE_ID
        	-->
            <key>
                <column name="PROVINCE_ID" precision="22" scale="0" not-null="true" />
            </key>
            <!-- 
            	当前类(Province)于City类存在一对多关系
            -->
            <one-to-many class="org.liky.otm.pojo.City" />
        </set>
    </class>
</hibernate-mapping>

注:Inverse=”true”在这里的意思是:关联关系交给对方对象进行维护。

Province和City之间的关联关系是由外键字段province_id来维护的,该字段在city表中,修改city表时,才能修改该字段。

因此可以说,关联关系是由City表来维护的。因此,对于Province来说,关联关系是交给对方(City)来维护的。

city映射:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="org.liky.otm.pojo.City" table="CITY" schema="SUNXUN">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="8" scale="0" />
            <generator class="increment" />
        </id>
        <!-- 
        	表示当前类(City)与Province存在多对一关系,关联的变量名为province,关联字段名为PROVINCE_ID
        -->
        <many-to-one name="province" class="org.liky.otm.pojo.Province" fetch="select">
            <column name="PROVINCE_ID" precision="22" scale="0" not-null="true" />
        </many-to-one>
        <property name="title" type="java.lang.String">
            <column name="TITLE" length="50" not-null="true" />
        </property>
    </class>
</hibernate-mapping>
注: Fetch表示Session的get和load的关联查询方式。

当使用Session.get来按主键查询City对象时,会自动关联查询出Province,fetch则是关联查询是通过inner join还是分开两条sql完成。

Fetch=”select”时,分开两条sql语句,分别查询两张表数据,而且默认使用懒汉式加载。

Fetch=”join”时,则一次将数据全部查询出来。

如果查询省份或城市信息,可以自动关联取得其他的内容。

例如:

根据省份,查询所有省份下的城市列表。

public class Test {
	public static void main(String[] args) {
		// City c = (City) HibernateSessionFactory.getSession().get(City.class,
		// 3);
		// System.out.println(c.getTitle());
		// System.out.println(c.getProvince().getTitle());

		String hql = "FROM Province";
		Query query = HibernateSessionFactory.getSession().createQuery(hql);
		List<Province> all = query.list();
		Iterator<Province> iter = all.iterator();
		while (iter.hasNext()) {
			Province p = iter.next();
			System.out.println(p.getTitle());
			Iterator<City> iter2 = p.getCities().iterator();
			while (iter2.hasNext()) {
				City c = iter2.next();
				System.out.println(" |-" + c.getTitle());
			}
		}
	}
}

实现省份城市的下拉列表选择:

先实现省份的查询全部的后台方法。只需要在ProvinceDAO写一个findAll的方法并实现

然后在页面上加入超连接,进入Action,完成查询

<span style="white-space:pre">		</span><center>
			<a href="province!list.action">省份城市关联列表</a>
		</center>

完成Action中的list方法。

public class ProvinceAction extends ActionSupport {

	private List<Province> allProvince;

	public String list() throws Exception {
		allProvince = ServiceFactory.getIProvinceServiceInstance().list();

		return "list";
	}
配置struts:

<span style="white-space:pre">	</span><package name="root" namespace="/" extends="struts-default">
		<action name="province" class="org.liky.otm.action.ProvinceAction">
			<result name="list">/pages/province/province_list.jsp</result>
		</action>
	</package>

完成页面的列表显示功能。

两层嵌套循环

<span style="white-space:pre">	</span><select>
		<c:forEach var="p" items="${allProvince}">
			<option value="${p.id }">${p.title }</option>
			<c:forEach var="c" items="${p.cities}">
				<option value="${c.id }">  |- ${c.title }</option>
		<span style="white-space:pre">	</span></c:forEach>
		</c:forEach>
	</select>

出现懒汉式加载异常。

解决方法:

1)  不关连接(不推荐)

2)  不使用懒汉式,需要修改映射文件。

<set name="cities" lazy="false" order-by="id desc" inverse="true">   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值