1.建立客户表和联系人表,客户和联系人是一对多关系,联系人中有一个lkm_cst_id外键
CREATE TABLE `cst_customer` (
`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
`cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
`cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
`cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
`cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
`cust_address` varchar(128) DEFAULT NULL COMMENT '客户联系地址',
`cust_phone` varchar(64) DEFAULT NULL COMMENT '客户联系电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
CREATE TABLE `cst_linkman` (
`lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
`lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名',
`lkm_gender` varchar(10) DEFAULT NULL COMMENT '联系人性别',
`lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话',
`lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机',
`lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱',
`lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位',
`lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注',
`lkm_cst_id` bigint(32) NOT NULL,
PRIMARY KEY (`lkm_id`),
KEY `FK3deqymsc65sso3qdslytwk20r` (`lkm_cst_id`),
CONSTRAINT `FK3deqymsc65sso3qdslytwk20r` FOREIGN KEY (`lkm_cst_id`) REFERENCES `cst_customer` (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
2.编辑cfg.xml配置文件
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--1.连接数据库的信息-->
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<!--2.hibernate可选配置-->
<!--检测实体类的映射配置和数据库的表结构是否一致,如果不一致,更新表结构-->
<property name="hbm2ddl.auto">update</property>
<!--数据库方言-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!--是否显示hibernate生成的sql语句-->
<property name="hibernate.show_sql">true</property>
<!--是否使用格式化输出sql语句-->
<property name="hibernate.format_sql">true</property>
<!--3.设置hibernate的连接池提供商-->
<property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!--4.映射文件的位置-->
<mapping class="domain.CstCustomerEntity"/>
<mapping resource="domain/CstCustomerEntity.hbm.xml"/>
<mapping class="domain.CstLinkmanEntity"/>
<mapping resource="domain/CstLinkmanEntity.hbm.xml"/>
<!-- DB schema will be updated if needed -->
<!-- <property name="hbm2ddl.auto">update</property> -->
</session-factory>
</hibernate-configuration>
3.使用idea反向映射,生成实体类和hbm映射文件,并在客户表中用Set表示联系人,在联系人表中使用Customer对象表示客户
客户实体
package domain;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
/**
* @Author: David.Xiao
* @Date: 2018/11/10 18:48
* @Description:
*/
@Entity
@Table(name = "cst_customer", schema = "hibernate", catalog = "")
public class CstCustomerEntity {
private long custId;
private String custName;
private String custSource;
private String custIndustry;
private String custLevel;
private String custAddress;
private String custPhone;
private Set<CstLinkmanEntity> cstLinkmanEntitySet = new HashSet<>(0);
public Set<CstLinkmanEntity> getCstLinkmanEntitySet() {
return cstLinkmanEntitySet;
}
public void setCstLinkmanEntitySet(Set<CstLinkmanEntity> cstLinkmanEntitySet) {
this.cstLinkmanEntitySet = cstLinkmanEntitySet;
}
@Id
@Column(name = "cust_id")
public long getCustId() {
return custId;
}
public void setCustId(long custId) {
this.custId = custId;
}
@Basic
@Column(name = "cust_name")
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
@Basic
@Column(name = "cust_source")
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
@Basic
@Column(name = "cust_industry")
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
@Basic
@Column(name = "cust_level")
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
@Basic
@Column(name = "cust_address")
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
@Basic
@Column(name = "cust_phone")
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CstCustomerEntity that = (CstCustomerEntity) o;
return custId == that.custId &&
Objects.equals(custName, that.custName) &&
Objects.equals(custSource, that.custSource) &&
Objects.equals(custIndustry, that.custIndustry) &&
Objects.equals(custLevel, that.custLevel) &&
Objects.equals(custAddress, that.custAddress) &&
Objects.equals(custPhone, that.custPhone);
}
@Override
public int hashCode() {
return Objects.hash(custId, custName, custSource, custIndustry, custLevel, custAddress, custPhone);
}
@Override
public String toString() {
return "CstCustomerEntity{" +
"custId=" + custId +
", custName='" + custName + '\'' +
", custSource='" + custSource + '\'' +
", custIndustry='" + custIndustry + '\'' +
", custLevel='" + custLevel + '\'' +
", custAddress='" + custAddress + '\'' +
", custPhone='" + custPhone + '\'' +
'}';
}
}
客户hbm映射文件,配置set标签,并根据情况添加inverse和cascade配置
<?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="domain">
<class name="CstCustomerEntity" table="cst_customer" schema="hibernate">
<id name="custId" column="cust_id">
<generator class="increment"></generator>
</id>
<property name="custName" column="cust_name"/>
<property name="custSource" column="cust_source"/>
<property name="custIndustry" column="cust_industry"/>
<property name="custLevel" column="cust_level"/>
<property name="custAddress" column="cust_address"/>
<property name="custPhone" column="cust_phone"/>
<!--一对多关系映射-->
<!--set:配置set集合 name:实体中set集合名称 table:从表名称,在一对多配置时可以不写-->
<!--级联操作时要设置cascade属性,级联更新保存设置为save-update、级联删除时设置为delete-->
<set name="cstLinkmanEntitySet" table="cst_linkman" inverse="true" cascade="save-update,delete">
<!--key:配置外键字段 column:从表中外键字段名-->
<key column="lkm_cst_id"></key>
<!--one-to-many:建立一对多的映射配置 class:从表实体类名称 -->
<one-to-many class="CstLinkmanEntity"></one-to-many>
</set>
</class>
</hibernate-mapping>
联系人实体
package domain;
import javax.persistence.*;
import java.util.Objects;
/**
* @Author: David.Xiao
* @Date: 2018/11/10 18:48
* @Description:
*/
@Entity
@Table(name = "cst_linkman", schema = "hibernate", catalog = "")
public class CstLinkmanEntity {
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 long lkmCstId;
private CstCustomerEntity cstCustomerEntity = new CstCustomerEntity();
public CstCustomerEntity getCstCustomerEntity() {
return cstCustomerEntity;
}
public void setCstCustomerEntity(CstCustomerEntity cstCustomerEntity) {
this.cstCustomerEntity = cstCustomerEntity;
}
@Id
@Column(name = "lkm_id")
public long getLkmId() {
return lkmId;
}
public void setLkmId(long lkmId) {
this.lkmId = lkmId;
}
@Basic
@Column(name = "lkm_name")
public String getLkmName() {
return lkmName;
}
public void setLkmName(String lkmName) {
this.lkmName = lkmName;
}
@Basic
@Column(name = "lkm_gender")
public String getLkmGender() {
return lkmGender;
}
public void setLkmGender(String lkmGender) {
this.lkmGender = lkmGender;
}
@Basic
@Column(name = "lkm_phone")
public String getLkmPhone() {
return lkmPhone;
}
public void setLkmPhone(String lkmPhone) {
this.lkmPhone = lkmPhone;
}
@Basic
@Column(name = "lkm_mobile")
public String getLkmMobile() {
return lkmMobile;
}
public void setLkmMobile(String lkmMobile) {
this.lkmMobile = lkmMobile;
}
@Basic
@Column(name = "lkm_email")
public String getLkmEmail() {
return lkmEmail;
}
public void setLkmEmail(String lkmEmail) {
this.lkmEmail = lkmEmail;
}
@Basic
@Column(name = "lkm_position")
public String getLkmPosition() {
return lkmPosition;
}
public void setLkmPosition(String lkmPosition) {
this.lkmPosition = lkmPosition;
}
@Basic
@Column(name = "lkm_memo")
public String getLkmMemo() {
return lkmMemo;
}
public void setLkmMemo(String lkmMemo) {
this.lkmMemo = lkmMemo;
}
@Basic
@Column(name = "lkm_cst_id")
public long getLkmCstId() {
return lkmCstId;
}
public void setLkmCstId(long lkmCstId) {
this.lkmCstId = lkmCstId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CstLinkmanEntity that = (CstLinkmanEntity) o;
return lkmId == that.lkmId &&
lkmCstId == that.lkmCstId &&
Objects.equals(lkmName, that.lkmName) &&
Objects.equals(lkmGender, that.lkmGender) &&
Objects.equals(lkmPhone, that.lkmPhone) &&
Objects.equals(lkmMobile, that.lkmMobile) &&
Objects.equals(lkmEmail, that.lkmEmail) &&
Objects.equals(lkmPosition, that.lkmPosition) &&
Objects.equals(lkmMemo, that.lkmMemo);
}
@Override
public int hashCode() {
return Objects.hash(lkmId, lkmName, lkmGender, lkmPhone, lkmMobile, lkmEmail, lkmPosition, lkmMemo, lkmCstId);
}
@Override
public String toString() {
return "CstLinkmanEntity{" +
"lkmId=" + lkmId +
", lkmName='" + lkmName + '\'' +
", lkmGender='" + lkmGender + '\'' +
", lkmPhone='" + lkmPhone + '\'' +
", lkmMobile='" + lkmMobile + '\'' +
", lkmEmail='" + lkmEmail + '\'' +
", lkmPosition='" + lkmPosition + '\'' +
", lkmMemo='" + lkmMemo + '\'' +
", lkmCstId=" + lkmCstId +
'}';
}
}
联系人hbm映射文件,配置many-to-one标签,并根据情况配置cascade属性
<?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">
<!--package:导包,下面就不用再写全限定类名-->
<hibernate-mapping package="domain">
<class name="CstLinkmanEntity" table="cst_linkman" schema="hibernate">
<id name="lkmId" column="lkm_id">
<generator class="increment"></generator>
</id>
<property name="lkmName" column="lkm_name"/>
<property name="lkmGender" column="lkm_gender"/>
<property name="lkmPhone" column="lkm_phone"/>
<property name="lkmMobile" column="lkm_mobile"/>
<property name="lkmEmail" column="lkm_email"/>
<property name="lkmPosition" column="lkm_position"/>
<property name="lkmMemo" column="lkm_memo"/>
<!--<property name="lkmCstId" column="lkm_cst_id"/>-->
<!--建立多对一的映射配置-->
<!--name:引用的主表实体的对象的名称-->
<!--class:引用的主表实体的类的名称-->
<!--column:从表中外键字段的名称-->
<many-to-one name="cstCustomerEntity" class="CstCustomerEntity" column="lkm_cst_id"></many-to-one>
</class>
</hibernate-mapping>
4.写一对多的级联CRUD方法,直接操作java对象即可
package dao;
import domain.CstCustomerEntity;
import domain.CstLinkmanEntity;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import java.util.Set;
import static org.junit.Assert.*;
/**
* @Author: David.Xiao
* @Date: 2018/11/10 19:40
* @Description:
*/
public class HibernateOne2ManyTest {
@Test
public void openSession() {
Session session = HibernateUtil.openSession();
}
/**
* 保存联系人
* 创建一个新的联系人,需要关联一个客户
*/
@Test
public void saveLinkman()
{
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
CstCustomerEntity customerEntity = session.get(CstCustomerEntity.class,1L);
CstLinkmanEntity linkmanEntity = new CstLinkmanEntity();
linkmanEntity.setCstCustomerEntity(customerEntity);
linkmanEntity.setLkmName("张老五");
session.save(linkmanEntity);
tx.commit();
}
/**
* 级联保存:在set或many-to-one标签中配置cascade属性
* 保存有关联关系的两个表
* 保存客户和联系人
*/
@Test
public void saveCascade()
{
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
//1.创建客户
CstCustomerEntity customerEntity = new CstCustomerEntity();
customerEntity.setCustName("王老三");
customerEntity.setCustSource("南京大学");
customerEntity.setCustIndustry("阿里");
customerEntity.setCustLevel("vip");
customerEntity.setCustAddress("北京市海淀区");
customerEntity.setCustPhone("132456789");
//2.创建联系人
CstLinkmanEntity linkmanEntity = new CstLinkmanEntity();
linkmanEntity.setLkmName("王老三联系人");
linkmanEntity.setLkmGender("男");
linkmanEntity.setLkmPhone("132465789");
linkmanEntity.setLkmMobile("321654987");
linkmanEntity.setLkmEmail("jsdhfj@163.com");
linkmanEntity.setLkmPosition("北京市朝阳区");
linkmanEntity.setLkmMemo("1");
//3.建立客户和联系人之间的双向关系
linkmanEntity.setCstCustomerEntity(customerEntity);
customerEntity.getCstLinkmanEntitySet().add(linkmanEntity);
//4.对哪个对象进行级联保存,就在哪个实体对应的hbm文件中,添加cascade属性
//选择一个
session.save(customerEntity);
session.save(linkmanEntity);
tx.commit();
}
/**
* 级联更新
* 查询一个客户,并给他添加一个新的联系人
*/
@Test
public void updateCascade()
{
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
//1.创建客户
CstCustomerEntity customerEntity = session.get(CstCustomerEntity.class,1L);
//2.创建联系人
CstLinkmanEntity linkmanEntity = new CstLinkmanEntity();
linkmanEntity.setLkmName("李老大联系人2");
linkmanEntity.setLkmGender("男");
linkmanEntity.setLkmPhone("132465789");
linkmanEntity.setLkmMobile("321654987");
linkmanEntity.setLkmEmail("jsdhfj@163.com");
linkmanEntity.setLkmPosition("北京市朝阳区");
linkmanEntity.setLkmMemo("1");
//3.建立客户和联系人之间的双向关系
linkmanEntity.setCstCustomerEntity(customerEntity);
customerEntity.getCstLinkmanEntitySet().add(linkmanEntity);
//4.对客户对象进行级联更新
session.update(customerEntity);
tx.commit();
}
/**
* 查询一个客户,并删除(联系人中有对它的引用)
* 普通删除:
* 在删除时,hibernate会更新从表中的行,将这一行的外键设为null,然后删除主表中的行
* 前提:外键字段不能设置非空
* 级联删除:在set标签中配置cascade属性为delete
* 外键字段没有非空限制:在删除时,hibernate会删除从表中的行,然后删除主表中的行
* 外键字段有非空限制:仍然想级联删除,则要在set中配置inverse=true
*/
@Test
public void deleteCascade()
{
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
//1.创建客户
CstCustomerEntity customerEntity = session.get(CstCustomerEntity.class,4L);
//2.对客户对象进行级联删除
session.delete(customerEntity);
tx.commit();
}
/**
* 对象导航查询
* hibernate中的查询方式:OID查询、HQL查询、QBC查询、SQL查询、对象导航查询
* 通过调用getXXX方法查询
*
* 关于一对多的立即查询和延迟查询:
* class标签的lazy:load方法是否是延迟加载
* set标签的lazy:查询关联的集合对象是否是延迟加载
* many-to-one的lazy:查询关联的主表实体是否是立即加载
*/
@Test
public void queryCascade()
{
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
//注意避免嵌套调用toString的问题
//查询某客户对应的联系人
CstCustomerEntity customerEntity = session.get(CstCustomerEntity.class,5L);
Set<CstLinkmanEntity> linkmanEntitySet = customerEntity.getCstLinkmanEntitySet();
for (CstLinkmanEntity linkman:linkmanEntitySet) {
System.out.println(linkman.toString());
}
//查询某联系人对应的客户
CstLinkmanEntity linkmanEntity = session.get(CstLinkmanEntity.class,9L);
CstCustomerEntity cstCustomerEntity = linkmanEntity.getCstCustomerEntity();
System.out.println(cstCustomerEntity.toString());
tx.commit();
}
}