Hibernate在做多对多映射的时候,除了原先的两张表外,会多出一个中间表做关联,根据中间表的会有两种不同的配置情况:

1.中间表不需要加入额外数据。

2.中间表有其他字段,需记录额外数据。

下面,我们就以address、person这两张表根据这两种情况做下相应的配置:

情况1:

我们需要建三张表,一张address表,一张person表,一张中间表(其实中间表可以不用建,配置好后运行会自动生成),如下:

delimiter $$

CREATE TABLE `address` (
`address_id` int(11) NOT NULL,
`address_name` varchar(50) default NULL,
PRIMARY KEY (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$ delimiter $$ CREATE TABLE `person` (
`person_id` int(11) NOT NULL,
`person_name` varchar(20) default NULL,
PRIMARY KEY (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$ delimiter $$ CREATE TABLE `person_address` (
`person_id` int(11) NOT NULL,
`address_id` int(11) NOT NULL,
PRIMARY KEY (`address_id`,`person_id`),
KEY `FK23F8B90AAAA29DA8` (`person_id`),
KEY `FK23F8B90AB52F16EC` (`address_id`),
CONSTRAINT `FK23F8B90AB52F16EC` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`),
CONSTRAINT `FK23F8B90AAAA29DA8` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

表建好后,我们需要写相应的实体类:

public class Address {

    private int addressId;
private String addressName;
private Set<Person> person; public int getAddressId() {
return addressId;
}
public void setAddressId(int addressId) {
this.addressId = addressId;
}
public String getAddressName() {
return addressName;
}
public void setAddressName(String addressName) {
this.addressName = addressName;
}
public Set<Person> getPerson() {
return person;
}
public void setPerson(Set<Person> person) {
this.person = person;
} } public class Person { private int personId;
private String personName;
private Set<Address> address; public int getPersonId() {
return personId;
}
public void setPersonId(int personId) {
this.personId = personId;
} public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public Set<Address> getAddress() {
return address;
}
public void setAddress(Set<Address> address) {
this.address = address;
} }

在这里,我们只需要配置两个实体类与相应配置文件即可,中间表无须建实体类与配置文件,hibernate会帮你自动关连。

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.web.model"> <class name="Address" table="address">
<id name="addressId" type="int" >
<column name="address_id" length="11"></column>
</id>
<property name="addressName" type="string" >
<column name="address_name" length="50"></column>
</property>
<set name="person" cascade="all" table="person_address">
<key column="address_id"></key>
<many-to-many class="Person" column="person_id"/>
</set>
</class>
</hibernate-mapping> <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.web.model"> <class name="Person" table="person">
<id name="personId" type="int" >
<column name="person_id" length="11"></column>
</id>
<property name="personName" type="string" >
<column name="person_name" length="20"></column>
</property>
<set name="address" cascade="all" table="person_address">
<key column="person_id"></key>
<many-to-many class="Address" column="address_id"/>
</set>
</class>
</hibernate-mapping>

测试类:

public void insert() {

        Person p = new Person();
p.setPersonId(1);
p.setPersonName("newUser");
Address ad = new Address();
ad.setAddressId(2);
ad.setAddressName("here");
Set<Address> setAd = new HashSet<Address>();
setAd.add(ad);
p.setAddress(setAd);
sf.getCurrentSession().persist(p);
}

以上,便是一般的多对多关系。

情况2:

  当需要向中间表写数据时,单纯的多对多已经满足不了了,所以在这里,我们可以将其设成两个一对多的关系,即person表与person_address是一对多关系,address与person_address表也是一对多关系,这样,但可以完成相应的多对多功能了。在情况2中,我们不单单需要对person表与address表写相应的实体类与配置文件,还需要对person_address表写实体类与配置文件。

在第二种情况中,我们又可以分成两种小的情况:

  1)中间表新增主键,另有两个字段做为外键对应另外两张表。

2)中间表采用复合主键,同时做为外键分别对应另外两张表。

下面我们分别对两种情况做相应配置。

情况1)中间表新增主键,另有两个字段做为外键对应另外两张表。数据表结构为:

delimiter $$

CREATE TABLE `address` (
`address_id` int(11) NOT NULL,
`address_name` varchar(50) default NULL,
PRIMARY KEY (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$ delimiter $$ CREATE TABLE `person` (
`person_id` int(11) NOT NULL,
`person_name` varchar(20) default NULL,
PRIMARY KEY (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$ delimiter $$ CREATE TABLE `person_address` (
`pa_id` int(11) NOT NULL,
`person_id` int(11) default NULL,
`address_id` int(11) default NULL,
`pa_describe` varchar(50) default NULL,
PRIMARY KEY (`pa_id`),
KEY `FK23F8B90AAAA29DA8` (`person_id`),
KEY `FK23F8B90AB52F16EC` (`address_id`),
CONSTRAINT `FK23F8B90AB52F16EC` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`),
CONSTRAINT `FK23F8B90AAAA29DA8` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

对应的类为:

public class Address {

    private int addressId;
private String addressName;
private Set<PersonAddress> pa; public int getAddressId() {
return addressId;
}
public void setAddressId(int addressId) {
this.addressId = addressId;
}
public String getAddressName() {
return addressName;
}
public void setAddressName(String addressName) {
this.addressName = addressName;
}
public Set<PersonAddress> getPa() {
return pa;
}
public void setPa(Set<PersonAddress> pa) {
this.pa = pa;
} } public class Person { private int personId;
private String personName;
private Set<PersonAddress> personAddress; public int getPersonId() {
return personId;
}
public void setPersonId(int personId) {
this.personId = personId;
} public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public Set<PersonAddress> getPersonAddress() {
return personAddress;
}
public void setPersonAddress(Set<PersonAddress> personAddress) {
this.personAddress = personAddress;
}
} public class PersonAddress{ private int paid;
private String paDescribe;
private Person person;
private Address address; public int getPaid() {
return paid;
}
public void setPaid(int paid) {
this.paid = paid;
}
public String getPaDescribe() {
return paDescribe;
}
public void setPaDescribe(String paDescribe) {
this.paDescribe = paDescribe;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
} }

配置文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.web.model"> <class name="Address" table="address">
<id name="addressId" type="int" >
<column name="address_id" length="11"></column>
</id>
<property name="addressName" type="string" >
<column name="address_name" length="50"></column>
</property>
<set name="pa" cascade="all">
<key column="address_id"></key>
<one-to-many class="PersonAddress"/>
</set>
</class>
</hibernate-mapping> <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.web.model"> <class name="Person" table="person">
<id name="personId" type="int" >
<column name="person_id" length="11"></column>
</id>
<property name="personName" type="string" >
<column name="person_name" length="20"></column>
</property>
<set name="personAddress" cascade="all">
<key column="person_id"></key>
<one-to-many class="PersonAddress"/>
</set>
</class>
</hibernate-mapping> <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.web.model"> <class name="PersonAddress" table="person_address">
<id name="paid" type="int">
<column name="pa_id" length="11"></column>
</id>
<property name="paDescribe" type="string" >
<column name="pa_describe" length="50"></column>
</property>
<many-to-one name="person" class="Person" cascade="all">
<column name="person_id" length="11" ></column>
</many-to-one>
<many-to-one name="address" class="Address" cascade="all">
<column name="address_id" length="11" ></column>
</many-to-one>
</class>
</hibernate-mapping>

以上,便完成了相应的配置,进行数据插入时,只需应对相应的保存即可,如:

public void insert() {

        Person p = new Person();
p.setPersonId(1);
p.setPersonName("newUser");
Address ad = new Address();
ad.setAddressId(2);
ad.setAddressName("here");
PersonAddress pa = new PersonAddress();
pa.setPaid(1);
pa.setPerson(p);
pa.setAddress(ad);
pa.setPaDescribe("this is a test");
sf.getCurrentSession().persist(pa);
}

情况2)中间表采用复合主键,同时做为外键分别对应另外两张表。由于采用复合主键,在hibernate模型中,需要有另一个类来对应,并实现Serializable接口:

public class PersonAddressPK implements Serializable{

    /**
*
*/
private static final long serialVersionUID = 1L; private int person;
private int address;
public int getPerson() {
return person;
}
public void setPerson(int person) {
this.person = person;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
} }

Person表与address表不变,主要是在person_address表上做修改,如下:

delimiter $$
 
CREATE TABLE `person_address` (
  `person_id` int(11) NOT NULL,
  `address_id` int(11) NOT NULL,
  `pa_describe` varchar(50) default NULL,
  PRIMARY KEY  (`person_id`,`address_id`),
  KEY `FK23F8B90AAAA29DA8` (`person_id`),
  KEY `FK23F8B90AB52F16EC` (`address_id`),
  CONSTRAINT `FK23F8B90AB52F16EC` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`),
  CONSTRAINT `FK23F8B90AAAA29DA8` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

相应的类:

public class PersonAddress{

    private String paDescribe;
private PersonAddressPK paPK;
private Person person;
private Address address; public String getPaDescribe() {
return paDescribe;
}
public void setPaDescribe(String paDescribe) {
this.paDescribe = paDescribe;
}
public PersonAddressPK getPaPK() {
return paPK;
}
public void setPaPK(PersonAddressPK paPK) {
this.paPK = paPK;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
} }

配置文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.test.web.model"> <class name="PersonAddress" table="person_address">
<composite-id class="PersonAddressPK" name="paPK">
<key-property name="person">
<column name="person_id" length="11"></column>
</key-property>
<key-property name="address">
<column name="address_id" length="11"></column>
</key-property>
</composite-id>
<property name="paDescribe" type="string" >
<column name="pa_describe" length="50"></column>
</property>
<many-to-one name="person" class="Person" column="person_id" insert="false" update="false"/>
<many-to-one name="address" class="Address" column="address_id" insert="false" update="false"/>
</class>
</hibernate-mapping>

插入的时候,需先保存person与address表,再保存person_address表:

public void insert() {

        Person p = new Person();
p.setPersonId(1);
p.setPersonName("newUser");
Address ad = new Address();
ad.setAddressId(2);
ad.setAddressName("here");
sf.getCurrentSession().persist(p);
sf.getCurrentSession().persist(ad);
PersonAddress pa = new PersonAddress();
PersonAddressPK paPK = new PersonAddressPK();
paPK.setPerson(p.getPersonId());
paPK.setAddress(ad.getAddressId());
pa.setPaPK(paPK);
pa.setPaDescribe("this is a test");
sf.getCurrentSession().persist(pa);
}

以上,便是hibernate多对多时可采用的几种方法了。

Hibernate多对多两种情况的更多相关文章

  1. Hibernate实现有两种配置,xml配置与注释配置

    hibernate实现有两种配置,xml配置与注释配置. (1):xml配置:hibernate.cfg.xml (放到src目录下)和实体配置类:xxx.hbm.xml(与实体为同一目录中) < ...

  2. java项目打jar包的两种情况

    链接地址:http://jingyan.baidu.com/article/6b97984d8a6ddc1ca2b0bfa0.html 本文介绍一下java项目打jar包时的两种情况各怎么操作   方 ...

  3. Day6------------磁盘用满的两种情况

    1.文件包含元数据和写入的内容 元数据:存在硬盘中的inode ls -i /etc/passwd.bak 查看inode df -i 查看inode 2.磁盘用满的两种情况 1).内容太多 2).空 ...

  4. JS获取元素宽高的两种情况

    JS获取元素宽高分两种情况, 一.内联样式,也就是直接把width和height写在HTML元素中的style里: 这种情况使用     document.getElementById('xxx'). ...

  5. hibernate实现有两种配置,xml配置与注释配置。<转>

    <注意:在配置时hibernate的下载的版本一定确保正确,因为不同版本导入的jar包可能不一样,所以会导致出现一些错误> hibernate实现有两种配置,xml配置与注释配置. (1) ...

  6. 导致“mysql has gone away”的两种情况

    导致“mysql has gone away”的两种情况 By Cruise 1.  wait_timeout参数 在开发代理server时, 我使用了jdbc连接数据库,并采用长连接的方式连接数据库 ...

  7. Nginx访问PHP文件的File not found错误处理,两种情况

    这个错误很常见,原有有下面两种几种 1. php-fpm找不到SCRIPT_FILENAME里执行的php文件 2. php-fpm不能访问所执行的php,也就是权限问题 第一种情况 可以在你的loc ...

  8. zoj3228 Searching the String AC自动机查询目标串中模式串出现次数(分可覆盖,不可覆盖两种情况)

    /** 题目:zoj3228 Searching the String 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=34 ...

  9. django-将数据库数据转换成JSON格式(ORM和SQL两种情况)

    最近打算搞一个自动化运维平台,所以在看Django的知识. 在实际项目开发中,遇到一个小问题:前后端发生数据交互主流采用的是JSON.前端传数据到服务器端比较简单,稍微麻烦的是服务器端传JSON到前端 ...

随机推荐

  1. UVa 294 - Divisors 解题报告 c语言实现 素数筛法

    1.题目大意: 输入两个整数L.H其中($1≤L≤H≤10^9,H−L≤10000$),统计[L,H]区间上正约数最多的那个数P(如有多个,取最小值)以及P的正约数的个数D. 2.原理: 对于任意的一 ...

  2. java面笔准备

    这套面试题主要目的是帮助那些还没有java软件开发实际工作经验,而正在努力寻找java软件开发工作的朋友在笔试时更好地赢得笔试和面试.由于这套面试题涉及的范围很泛,很广,很杂,大家不可能一天两天就看完 ...

  3. js调用本地office打开服务器的office文件预览

    本来是想做成直接在网页上在线预览office文件的,但是找了好多,要不是收费,要不就是要调用别人的API不安全,所以纠结了好久还是用调用本地的office预览office文件. 废话不多说,那么怎么调 ...

  4. PokeCats开发者日志(二)

      现在是PokeCats游戏开发的第四天的上午,来记录一下昨天做的事情吧. day3   day3主要是添加音效和优化界面,本以为添加个音效1~2个小时就够了吧,没想到贼不顺,弄了一个下午才搞好. ...

  5. Linux之JDK在线安装及配置

    1.查找java相关得列表  yum -y list java*2.在线安装 yum -y install java-1.6.0-openjdk*3.查看安装目录  ls -l /usr/lib/jv ...

  6. Cache的封装和使用

    ICache 接口 using System; using System.Collections.Generic; using System.Linq; using System.Text; usin ...

  7. 好用的在线pdf转化器

    https://smallpdf.com/cn/compress-pdf

  8. 【bzoj5071】[Lydsy十月月赛]小A的数字 乱搞

    题目描述 有一串数字 A1,A2...An 每次可以进行如下操作,选择一个数字 i ,将 (Ai-1 , Ai , Ai+1) 变为 (Ai-1 + Ai , -Ai , Ai+1 + Ai) ,特别 ...

  9. AGC018D Tree and Hamilton Path(树+树的重心)

    题目大意: 给你一棵n个结点树,然后根据这棵树构造一个完全图,求完全图的一条最长的哈密顿路径. 构造方式是,完全图中的dis(u, v)就等于树上的u和v的距离. 题解: 这...这..不就是杜教的那 ...

  10. [洛谷P3254]圆桌问题

    题目大意:有$m$个单位,每个单位有$r_i$个代表,有$n$张餐桌,每张餐桌可容纳$c_i$个代表.要求同一个单位的代表不在同一个餐桌就餐.若可以,输出$1$以及其中一种方案,否则输出$0$ 题解: ...