【SSH (八)】hibernate one-to-many例子

首先按照【SSH (七)】 struts2整合hibernate3 搭建一个SSH的空框架出来。


下面说一下hibernate的多对一映射。

数据库实体之间通常会存在关联,其中一种就是多对一关联,比如用户User和邮件地址Address两个实体,一个用户会有多个邮件地址,而一个邮件地址只会属于一个用户,也就是说用户会对应多个地址。在这里,用户就是“一”的一方,而地址是“多”的一方。关于多和一的区别,最好是画一个图出来,那么用户会有很多箭头指向不同的地址,用户就是一,地址就是多。


多对一关联进一步可分为单向和双向,先看单向。


1,单向多对一:在数据库建表层面,肯定是两张表一个是User一个是Address,然后Address里面存一个指向User的外键,数据库的表结构肯定是这样的。

然而实体的映射文件却有两种方式,为什么这里会有两种方式呢?这涉及到一个维护映射关系的概念,这个上升到了面向对象层面。比如我这里要为user1添加一个地址,我可以在User类中加一个set,然后set.add(address),也可以在address类中添加一个user的引用,然后就是address.setuser(user),前者是由user来维护关联,后者是address来维护关联,下面具体结合程序来说明:

首先建立数据库:刚才说了,不管采用什么关联方式,数据库底层的表是不变的,关联关系是应用层的话题:

user表:只需要有user自己的信息即可。


address表:不仅要有自己的信息,还有外键。id,address是address表本身的信息字段,userId是外键字段。


(1)由User来维护关联:

User实体类:需要添加一个集合存储拥有的地址。

package com.bean;

import java.util.HashSet;
import java.util.Set;

public class User {

	private int id;
	private String username;
	private String password;
	private String info;
	private Set<Address> addresses = new HashSet<>();
	
	public User(){
		
	}
	
    public User(String username,String password,String info){
		this.username = username;
		this.password = password;
		this.info = info;
	}

	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getInfo() {
		return info;
	}
	public void setInfo(String info) {
		this.info = info;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String toString(){
		return this.username+"  "+this.password+" "+this.info;
	}

	public Set<Address> getAddresses() {
		return addresses;
	}

	public void setAddresses(Set<Address> addresses) {
		this.addresses = addresses;
	}
	
}
映射文件:

<?xml version="1.0" encoding='GBK'?>    
<!DOCTYPE hibernate-mapping PUBLIC    
                            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    
                            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >    
    
<hibernate-mapping package="com.bean">
	<class name="User" table="[user]">
		<id name="id" column="id">
			<generator class="identity"></generator>
		</id>
		<property name="username" column="username" type="java.lang.String"
			length="16"></property>
		<property name="password" column="password" type="java.lang.String"
			length="16"></property>
		<property name="info" column="info" type="java.lang.String"
			length="16"></property>
		<set name="addresses" cascade="all">
		    <key column="userId" ></key>
		    <one-to-many class="com.bean.Address"></one-to-many>
		</set>
	</class>   
</hibernate-mapping>

<set>就是对集合属性的映射,<key>表示外键的名称,cascade级联设置记得。


Address实体类:既然让User实体类维护关联,那么Address类就只要包含自己本身的信息就可以,好像并不知道关联这回事。

package com.bean;

public class Address {

	private int id;
	private String address;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

}

映射文件:

<?xml version="1.0" encoding='GBK'?>    
<!DOCTYPE hibernate-mapping PUBLIC    
                            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    
                            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >    
    
<hibernate-mapping package="com.bean">
	<class name="Address" table="address">
		<id name="id" column="id">
			<generator class="identity"></generator>
		</id>
		<property name="address" column="address" type="java.lang.String"
			length="16"></property>
	</class>   
</hibernate-mapping>


应用层调用方法:

Address address1 = new Address();
		address1.setAddress("xianlin");
		Address address2 = new Address();
		address2.setAddress("zhujianglu");
		
		User user1 = new User();
		user1.setUsername("hehehehe");
		//因为由user来维护关联关系,所以,这里要让user自己添加address实例
		user1.getAddresses().add(address1);
		user1.getAddresses().add(address2);
		session.save(user1);
		
		transaction.commit();
	    session.close();
	    sessionFactory.close();

运行结果:



hibernate语句:


(2)由address类维护关联:

User实体类:不维护关联,所以都是自己本身的字段。

public class User{
	private int id;
	private String username;
	private String password;
	private String info;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getInfo() {
		return info;
	}
	public void setInfo(String info) {
		this.info = info;
	}
	
}
配置文件:

<class name="User" table="[user]">
		<id name="id" column="id">
			<generator class="identity"></generator>
		</id>
		<property name="username" column="username" type="java.lang.String"
			length="16"></property>
			<property name="password" column="password" type="java.lang.String"
			length="16"></property>
			<property name="info" column="info" type="java.lang.String"
			length="16"></property>
	</class>


Address实体类:

public class Address {

	private int id;
	private String address;

	private User user;
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

}
配置文件:

<class name="Address" table="address">
		<id name="id" column="id">
			<generator class="identity"></generator>
		</id>
		<property name="address" column="address" type="java.lang.String"
			length="16"></property>
		<many-to-one name="user" column="userId" cascade="all"></many-to-one>
	</class> 
应用层调用方法:

User user1 = new User();
		user1.setUsername("hehehehe");
		
		Address address1 = new Address();
		address1.setAddress("xianlin");
		//因为由address自己维护,所以address自己设置user
		address1.setUser(user1);
		Address address2 = new Address();
		address2.setAddress("zhujianglu");
		address2.setUser(user1);
		
		session.save(address1);
		session.save(address2);


运行结果:



总结:

对于单向的多对一关联,画图确定哪一方是多哪一方是1。

多对一对于数据库而言只有一种实现方式,就是在多的一方添加外键,至于关联的维护方这是应用层层面要考虑的问题,只是应用层存储关联关系时的方式不同而已。这也是因为hibernate ORM的原因,hibernate是将原生的sql api封装起来,提供了面向对象的访问方式,这才导致了有两种方式的多对一,如果不用ORM,用原生的sql,我们就不会遇到这样的问题了。

两种方式也被称为多对一和一对多。

项目源码:http://pan.baidu.com/s/1c0LReLE


至于双向,就是二者的结合了,配置文件一个加one-to-many另一个加many-to-one,实体类一个加set一个加引用。


更加详细的类图和对比可以参照http://blog.youkuaiyun.com/yanmei_yao/article/details/7596163

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值