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

来源:互联网 发布:淘宝上假证哪家好 编辑:程序博客网 时间:2024/06/05 23:53

首先按照【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自己设置useraddress1.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.csdn.net/yanmei_yao/article/details/7596163

0 0
原创粉丝点击