1. 数据库中表关系
- 一对一
- 一对多(多对一)
- 多对多
2. 如何确立和实现数据库中的表关系
- 一对多:
一般把一的一方称为主表,多的一方称为从表
外键:
从表中有一列,该列的取值除了null之外,只能来源于主表的主键。默认情况下,外键字段的值是可以重复的。 - 多对多:
使用中间表
中间表只有两个外键,引用两个多对多表的主键。中间表主键应该采用联合主键。这两个字段都是外键,不能有其他字段信息。
任何一个多方的表和中间表去比较,都是一对多的关系
一对一的表关系在数据库中如何实现:
- 建立外键的方式:
外键约束、唯一约束、非空约束
把外键加了非空和唯一约束,从而实现一对一 - 使用主键的方式:
让其中一张表既是主键,又是外键。(从表来)
确立两张表的关系:
找外键,此种方式能解决确立表关系中90%的情况,其他10%涉及项目阶段的打断设计
3. 学习多表映射配置要遵循的步骤
- 确定两张表之间的关系
- 在数据库实现两张表之间的关系建立
- 在映射配置文件中建立两个实体和两张表之间的关系
- 在实体类中描述出两个实体之间的关系
4. 一对多关系映射配置及操作
示例:客户和联系人两张表
- 一个客户可以包含多个联系人,多个联系人可以属于同一个客户,所以客户和联系人之间一对多。
- 实现一对多靠的是外键,客户表是主表,联系人表是从表,我们需要在联系人表中添加外键。
- 主表的实体类应该包含从表实体类的集合引用
从表实体类应该包含主表实体类的对象引用 -
配置文件
Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 在实体类的包下,创建xml文件,该文件命名为实体类+.hbm
导入dtd约束
-->
<!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.itheima.domain">
<class name="Customer" table="cst_customer">
<id name="custId" column="cust_id">
<!-- 指定主键的生成方式,取值是固定几个选一个 native使用本地数据库的自动增长能力-->
<generator class="native"></generator>
</id>
<property name="custName" column="cust_name"></property>
<property name="custSource" column="cust_source"></property>
<property name="custIndustry" column="cust_industry"></property>
<property name="custLevel" column="cust_level"></property>
<property name="custAddress" column="cust_address"></property>
<property name="custPhone" column="cust_phone"></property>
<!-- 一对多关系映射:主表实体的映射配置
标签:set 用于配置set集合属性
属性:name:指定实体类set集合的属性名称
table:指定从表的名称,在一对多配置时可以不写
key:映射外键字段
column:指定外键字段名称
one-to-many:用于建立一对多的映射配置
属性;class:用于指定从表实体的名称
-->
<set name="linkmans" table="cst_linkman">
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan"/>
</set>
</class>
</hibernate-mapping>
LinkMan.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!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.itheima.domain">
<class name="LinkMan" table="cst_linkman">
<id name="lkmId" column="lkm_id">
<!-- 指定主键的生成方式,取值是固定几个选一个 native使用本地数据库的自动增长能力-->
<generator class="identity"></generator>
</id>
<property name="lkmName" column="lkm_name"></property>
<property name="lkmGender" column="lkm_gender"></property>
<property name="lkmPhone" column="lkm_phone"></property>
<property name="lkmMobile" column="lkm_mobile"></property>
<property name="lkmEmail" column="lkm_email"></property>
<property name="lkmPosition" column="lkm_position"></property>
<property name="lkmMemo" column="lkm_memo"></property>
<!-- 多对一关系映射,从表实体的映射配置
标签:many-to-one 建立多对一的映射配置
属性:name:从表实体中引用主表实体对象引用的名称
class:指定属性所对应的实体类,导包了
column:指定从表外键字段的名称
-->
<many-to-one name="customer" class="Customer" column="lkm_cust_id"></many-to-one>
</class>
</hibernate-mapping>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/day55_hibernate01</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">suntong</property>
<!-- 数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 可选配置 -->
<!-- 是否显示hibernate生成的sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 是否使用格式化输出sql到控制台 -->
<property name="hibernate.format_sql">false</property>
<!-- 配置让hibernate采用何种方式生成ddl语句 -->
<property name="hibernate.hbm2ddl.auto">update</property><!-- update表示检测实体类的映射配置和数据库的表结构是否一致,如果不一致,更新表结构 -->
<!-- 设置hibernate的连接池提供商 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- 把Session和线程绑定,从而实现一个线程只有一个Session -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 映射配置 -->
<mapping resource="com/itheima/domain/Customer.hbm.xml"/>
<mapping resource="com/itheima/domain/LinkMan.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Customer.java
package com.itheima.domain;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/*
* 客户的实体类
* */
public class Customer implements Serializable {
private Long custId;
private String custName;
private String custSource;
private String custIndustry;
private String custLevel;
private String custAddress;
private String custPhone;
//一对多关系,一的一方
//主表实体应该包含从表实体的集合引用
//只分配地址,不分配空间,用来防止空指针异常,0
private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);
/**
* @return linkmans
*/
public Set<LinkMan> getLinkmans() {
return linkmans;
}
/**
* @param linkmans 要设置的 linkmans
*/
public void setLinkmans(Set<LinkMan> linkmans) {
this.linkmans = linkmans;
}
// public Customer() {
// super();
// // TODO 自动生成的构造函数存根
// }
// public Customer(Long custId, String custName) {
// super();
// this.custId = custId;
// this.custName = custName;
// }
/**
* @return custId
*/
public Long getCustId() {
return custId;
}
/**
* @param custId 要设置的 custId
*/
public void setCustId(Long custId) {
this.custId = custId;
}
/**
* @return custName
*/
public String getCustName() {
return custName;
}
/**
* @return custSource
*/
public String getCustSource() {
return custSource;
}
/**
* @return custIndustry
*/
public String getCustIndustry() {
return custIndustry;
}
/**
* @return custAddress
*/
public String getCustAddress() {
return custAddress;
}
/**
* @return custPhone
*/
public String getCustPhone() {
return custPhone;
}
/**
* @param custName 要设置的 custName
*/
public void setCustName(String custName) {
this.custName = custName;
}
/**
* @param custSource 要设置的 custSource
*/
public void setCustSource(String custSource) {
this.custSource = custSource;
}
/**
* @param custIndustry 要设置的 custIndustry
*/
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
/**
* @param custAddress 要设置的 custAddress
*/
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
/**
* @param custPhone 要设置的 custPhone
*/
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
/**
* @return custLevel
*/
public String getCustLevel() {
return custLevel;
}
/**
* @param custLevel 要设置的 custLevel
*/
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
//不要to关联对象
/* (非 Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
+ ", custIndustry=" + custIndustry + ", custLevel=" + custLevel + ", custAddress=" + custAddress
+ ", custPhone=" + custPhone + "]";
}
}
LinkMan.java
package com.itheima.domain;
import java.io.Serializable;
/*
* 联系人的实体类
* */
public class LinkMan implements Serializable {
private Long lkmId;
private String lkmName;
private String lkmGender;
private String lkmPhone;
private String lkmMobile;
private String lkmEmail;
private String lkmPosition;
private String lkmMemo;
//一对多关系,多的一方,从表实体包含主表实体的对象引用
private Customer customer;
/**
* @return lkmId
*/
public Long getLkmId() {
return lkmId;
}
/**
* @return lkmName
*/
public String getLkmName() {
return lkmName;
}
/**
* @return lkmGender
*/
public String getLkmGender() {
return lkmGender;
}
/**
* @return lkmPhone
*/
public String getLkmPhone() {
return lkmPhone;
}
/**
* @return lkmMobile
*/
public String getLkmMobile() {
return lkmMobile;
}
/**
* @return lkmEmail
*/
public String getLkmEmail() {
return lkmEmail;
}
/**
* @return lkmPosition
*/
public String getLkmPosition() {
return lkmPosition;
}
/**
* @return lkmMemo
*/
public String getLkmMemo() {
return lkmMemo;
}
/**
* @param lkmId 要设置的 lkmId
*/
public void setLkmId(Long lkmId) {
this.lkmId = lkmId;
}
/**
* @param lkmName 要设置的 lkmName
*/
public void setLkmName(String lkmName) {
this.lkmName = lkmName;
}
/**
* @param lkmGender 要设置的 lkmGender
*/
public void setLkmGender(String lkmGender) {
this.lkmGender = lkmGender;
}
/**
* @param lkmPhone 要设置的 lkmPhone
*/
public void setLkmPhone(String lkmPhone) {
this.lkmPhone = lkmPhone;
}
/**
* @param lkmMobile 要设置的 lkmMobile
*/
public void setLkmMobile(String lkmMobile) {
this.lkmMobile = lkmMobile;
}
/**
* @param lkmEmail 要设置的 lkmEmail
*/
public void setLkmEmail(String lkmEmail) {
this.lkmEmail = lkmEmail;
}
/**
* @param lkmPosition 要设置的 lkmPosition
*/
public void setLkmPosition(String lkmPosition) {
this.lkmPosition = lkmPosition;
}
/**
* @param lkmMemo 要设置的 lkmMemo
*/
public void setLkmMemo(String lkmMemo) {
this.lkmMemo = lkmMemo;
}
/**
* @return customer
*/
public Customer getCustomer() {
return customer;
}
/**
* @param customer 要设置的 customer
*/
public void setCustomer(Customer customer) {
this.customer = customer;
}
//不要to关联对象
/* (非 Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "LinkMan [lkmId=" + lkmId + ", lkmName=" + lkmName + ", lkmGender=" + lkmGender + ", lkmPhone="
+ lkmPhone + ", lkmMobile=" + lkmMobile + ", lkmEmail=" + lkmEmail + ", lkmPosition=" + lkmPosition
+ ", lkmMemo=" + lkmMemo + "]";
}
}