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. POJ 2135 Farm Tour(最小费用最大流)

    Description When FJ's friends visit him on the farm, he likes to show them around. His farm comprise ...

  2. 【解决】Node JS Error: ENOENT

    The Node Beginner Book 书中的实例代码当上传图片时会报Error: ENOENT, 原因:图片默认会选择系统的缓存文件夹下,在windows下无权访问C盘,所以就报错了.. 解决 ...

  3. Elasticsearch 监控和部署

    Elasticsearch: ! [ https://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/_cluster_health. ...

  4. 基于twemproxy和vip实现redis集群的无感知弹性扩容

    目标是实现redis集群的无感知弹性扩容 关键点 1.是无感知,即对redis集群的用户来说服务ip和port保持不变 2.弹性扩容,指的是在需要时刻可以按照业务扩大redis存储容量. 1.业务场景 ...

  5. java正则表达式 3 -- 查找

    用正则表达式执行查找命令,则需要用正则对象,其规则和执行顺序如下: 指定为字符串的正则表达式必须首先被便以为此类的实例.然后,可将得到的正则对象匹配任意的字符串用于创建Mather对象,执行匹配所涉及 ...

  6. DataGridView加载gif图片

    当我们想加载图片时,一般情况下都会使用picturebox控件,这个控件可以加载各种格式的图片,当然也包括gif图片.但是有时,我们也希望一些数据展示控件也可以加载图片,比如说DataGridView ...

  7. To Chromium之VS调试追踪

    启动的code: for(;;){...WaitForWork()}base.dll!base::MessagePumpForUI::DoRunLoop                         ...

  8. 通过NTP(Network Time Protocal)协议进行时间同步

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAwUAAAKOCAYAAAD3ZbXWAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjw

  9. 感觉自己应该重新读一次Javascript

    我自己也有一本Javascript书籍,是自己上大学的时候学校给提供的,现在,我依旧带着这本书.我决定要把这本书在重新温习一下.然后,开启下面的Javascript之旅.这是我看到博客园一位园友写的, ...

  10. OJ 列表

    维护一个 OJ 列表.(这件事似乎没啥意义?) AtCoder hihoCoder Codeforces DMOJ CodeChef CS Academy HackerRank HackerEarth ...