一对多的关系,这里通过客户和联系人两个实体来演示:
1、数据库设计字段
2、实体关系
3、建表
customer表:
DROP TABLE IF EXISTS `customer`;
CREATE TABLE `customer` (
`cus_id` bigint(32) NOT NULL AUTO_INCREMENT,
`cus_name` varchar(32) NOT NULL,
`cus_mobile` varchar(32) DEFAULT NULL,
PRIMARY KEY (`cus_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
linkman表:
DROP TABLE IF EXISTS `linkman`;
CREATE TABLE `linkman` (
`lkm_id` bigint(32) NOT NULL AUTO_INCREMENT,
`lkm_name` varchar(32) NOT NULL,
`lkm_sex` char(1) DEFAULT NULL,
`lkm_phone` varchar(16) DEFAULT NULL,
`lkm_cus_id` bigint(32) DEFAULT NULL,
PRIMARY KEY (`lkm_id`),
KEY `fk_cus_lkm` (`lkm_cus_id`),
CONSTRAINT `fk_cus_lkm` FOREIGN KEY (`lkm_cus_id`) REFERENCES `customer` (`cus_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
4、实体与实体映射文件的编写(不要忘记把实体映射文件放置到hibernate.cfg.xml文件中去)
Customer.java
package com.nieshenkuan.model;
import java.util.HashSet;
import java.util.Set;
public class Customer {
// CREATE table customer(
// cus_id BIGINT(32) PRIMARY KEY auto_increment,
// cus_name VARCHAR(32) NOT NULL,
// cus_mobile VARCHAR(32) DEFAULT NULL,
// )ENGINE=INNODB CHARSET=utf8;
private Long cus_id;
private String cus_name;
private String cus_mobile;
private Set<LinkMan> linkMen=new HashSet<>();
public Long getCus_id() {
return cus_id;
}
public void setCus_id(Long cus_id) {
this.cus_id = cus_id;
}
public String getCus_name() {
return cus_name;
}
public void setCus_name(String cus_name) {
this.cus_name = cus_name;
}
public String getCus_mobile() {
return cus_mobile;
}
public void setCus_mobile(String cus_mobile) {
this.cus_mobile = cus_mobile;
}
public Set<LinkMan> getLinkMen() {
return linkMen;
}
public void setLinkMen(Set<LinkMan> linkMen) {
this.linkMen = linkMen;
}
}
Customer.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-12-28 11:22:51 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="com.nieshenkuan.model">
<class name="Customer" table="customer" lazy="true">
<id name="cus_id" >
<column name="cus_id"></column>
<generator class="native"></generator>
</id>
<property name="cus_name"></property>
<property name="cus_mobile"></property>
<!--
级联配置
cascade:
save-update 保存-更新
delete 删除
all save-update+delete
-->
<set name="linkMen" table="linkman" cascade="all" inverse="true" lazy="true" fetch="subselect">
<key>
<column name="lkm_cus_id"></column>
</key>
<one-to-many class="LinkMan"/>
</set>
</class>
</hibernate-mapping>
LinkMan.java
package com.nieshenkuan.model;
public class LinkMan {
// CREATE TABLE linkman(
// lkm_id BIGINT(32) PRIMARY KEY auto_increment,
// lkm_name VARCHAR(32) NOT NULL,
// lkm_sex CHAR(1),
// lkm_phone VARCHAR(16),
// lkm_cus_id BIGINT(32),
// CONSTRAINT fk_cus_lkm FOREIGN KEY(lkm_cus_id) REFERENCES customer(cus_id)
// )ENGINE=INNODB CHARSET=utf8;
private Long lkm_id;
private String lkm_name;
private Character lkm_sex;
private String lkm_phone;
private Customer customer;
public Long getLkm_id() {
return lkm_id;
}
public void setLkm_id(Long lkm_id) {
this.lkm_id = lkm_id;
}
public String getLkm_name() {
return lkm_name;
}
public void setLkm_name(String lkm_name) {
this.lkm_name = lkm_name;
}
public Character getLkm_sex() {
return lkm_sex;
}
public void setLkm_sex(Character lkm_sex) {
this.lkm_sex = lkm_sex;
}
public String getLkm_phone() {
return lkm_phone;
}
public void setLkm_phone(String lkm_phone) {
this.lkm_phone = lkm_phone;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
LinkMan.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-12-28 11:28:55 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="com.nieshenkuan.model">
<class name="LinkMan" table="LINKMAN">
<id name="lkm_id" >
<column name="LKM_ID" />
<generator class="native" />
</id>
<property name="lkm_name" type="java.lang.String">
<column name="LKM_NAME" />
</property>
<property name="lkm_sex" type="java.lang.Character">
<column name="LKM_SEX" />
</property>
<property name="lkm_phone" type="java.lang.String">
<column name="LKM_PHONE" />
</property>
<!--
lazy:
false:立即加载
proxy:代理,由其他元素决定
fetch:
select 单表查询
join 多表查询
-->
<many-to-one name="customer" column="lkm_cus_id" class="Customer" lazy="proxy" fetch="join"></many-to-one>
</class>
</hibernate-mapping>
5、测试
/**
* 添加数据
*/
@Test
public void testOneToMany() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// ---------------------------------------------
Customer customer = new Customer();
customer.setCus_name("阿里巴巴");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("马云");
LinkMan linkMan1 = new LinkMan();
linkMan1.setLkm_name("基哥");
customer.getLinkMen().add(linkMan);
customer.getLinkMen().add(linkMan1);
linkMan.setCustomer(customer);
linkMan1.setCustomer(customer);
session.save(customer);
session.save(linkMan);
session.save(linkMan1);
// ----------------------------------------------
transaction.commit();
session.close();
}
/**
* 查找数据
*/
@Test
public void deleteOneToMany2() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// ---------------------------------------------
// 从cutomer对象查到linkman对象
Customer cus = session.get(Customer.class,1L);
System.out.println(cus);
Set<LinkMan> set = cus.getLinkMen();
if (set.isEmpty()) {
System.out.println("set is null");
} else {
System.out.println("set is not null");
for (LinkMan obj : set) {
System.out.println(obj);
System.out.println(obj.getLkm_id() + ":" + obj.getLkm_name() + ":" + obj.getCustomer().getCus_id());
}
}
// 也能从linkman对象查到customer对象
LinkMan linkMan = session.get(LinkMan.class, 2l);
System.out.println(linkMan.getCustomer().getCus_name());
// ----------------------------------------------
transaction.commit();
session.close();
}
总结
总结:这种一对多的形式,是双向的,即从customer中能得到linkman,也能从linkman中得到customer。
一对多需要建立一个外键,(外键是在多的一方建立的),指向一的一方。
一的一方的实体中要有一个集合放置多的一方的对象,多的一方中的实体要包括一个一的一方的实体对象。
来看一下一的一方的配置文件(实体映射文件):
<set name="linkMen" table="linkman" cascade="all" inverse="true" lazy="true" fetch="subselect">
<key>
<column name="lkm_cus_id"></column>
</key>
<one-to-many class="LinkMan"/>
</set>
详解:set中的name是对应customer中set集合的名字,table对应的是set对象表名(即多的一方在数据中的中表名)。
key:是代表外键
one-to-many中的class是对应多的一方的实体的名字。
接下来看一下多的一方的配置文件:
<many-to-one name="customer" column="lkm_cus_id" class="Customer" lazy="proxy" fetch="join">
</many-to-one>
详解:many-to-one,中的to-one ,就是指一的一方,这里的name就是填写一的一
方的字段名,在多的一方实体里面有一个一的一方的一个对象,就是这个对象名。
然后column是指多的一方在数据库表中的外键,通过这个将两个表连接起来的,很重要。
其次就是class是指to—one的一方的实体名。(并不是对象名)。