1、表关系分析与创建
2、搭建Hibernate一对多的关系映射
(1)搭建Hibernate基本环境
(2)创建表:
(3)创建实体
一的一方:放的是多的一方的set集合
多的一方:放的是一的一方的对象
3、创建映射文件
客户的映射:
(1)配置主键
(2)配置普通属性
(3)配置关联对象
a)配置set标签
i.配置key标签
ii.配置one-to-many
<?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> <class name="com.lwt.hibernate.domain.Customer"table="cst_customer"> <!-- 配置主键 --> <id name="cust_id" column="cust_id"> <generator class="native"/> </id> <!-- 配置普通属性 --> <property name="cust_name" column="cust_name"/> <property name="cust_source" column="cust_source"/> <property name="cust_industry" column="cust_industry"/> <property name="cust_level" column="cust_level"/> <property name="cust_phone" column="cust_phone"/> <property name="cust_mobile" column="cust_mobile"/>
<!-- 配置关联对象: --> <!-- 配置set标签 * name :多的一方的集合的属性名称 --> <set name="linkMans" cascade="save-update" inverse="true"> <!-- 配置key标签 * column:多的一方的外键的名称 --> <key column="lkm_cust_id"/> <!-- 配置one-to-many * class :多的一方的类的全路径 --> <one-to-many class="com.lwt.hibernate.domain.LinkMan"/> </set> </class> </hibernate-mapping> |
联系人的映射:
<?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> <class name="com.lwt.hibernate.domain.LinkMan"table="cst_linkman"> <!-- 配置主键 --> <id name="lkm_id" column="lkm_id"> <generator class="native"/> </id>
<!-- 普通属性 --> <property name="lkm_name" column="lkm_name"/> <property name="lkm_gender" column="lkm_gender"/> <property name="lkm_phone" column="lkm_phone"/> <property name="lkm_mobile" column="lkm_mobile"/> <property name="lkm_email" column="lkm_email"/> <property name="lkm_qq" column="lkm_qq"/> <property name="lkm_position" column="lkm_position"/> <property name="lkm_memo" column="lkm_memo"/>
<!-- 配置标签:many-to-one * name :关联一的一方的对象的属性名称。 * class :关联一的一方的类的全路径。 * column :表中的外键的名称 --> <many-to-one name="customer" class="com.lwt.hibernate.domain.Customer"column="lkm_cust_id"/> </class> </hibernate-mapping> |
4、编写一对多的测试代码
级联:主控方执行操作,关联对象也执行相同操作。
(1)保存客户级联保存联系人
在一的一方设置级联:
@Test /* * 保存客户级联联系人 */ public void demo2() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction();
// 创建一个Customer对象 Customer customer1 = new Customer(); customer1.setCust_name("张三"); // 创建一个联系人 LinkMan linkMan1 = new LinkMan(); linkMan1.setLkm_name("丫蛋");
// 建立关系 linkMan1.setCustomer(customer1); customer1.getLinkMans().add(linkMan1);
// Session保存: session.save(customer1);
transaction.commit();
} |
(2)保存联系人级联保存客户
@Test /* * 保存联系人级联客户 */ public void demo4() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 创建一个客户 Customer customer = new Customer(); customer.setCust_name("张三"); // 创建一个联系人 LinkMan linkMan1 = new LinkMan(); linkMan1.setLkm_name("李四");
// 建立联系 linkMan1.setCustomer(customer); customer.getLinkMans().add(linkMan1);
session.save(linkMan1); transaction.commit(); } |
(3)测试对象的导航的问题
对象导航就是维护双方的关系。
customer.getLinkMans().add(linkMan1);
linkMan1.setCustomer(customer)
前题:在客户和联系人的映射文件都配置:cascade=”save-update”
@Test /* * 测试对象导航和级联操作 */ public void demo5() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 创建一个客户 Customer customer = new Customer(); customer.setCust_name("李总");
// 创建三个联系对象 LinkMan linkMan1 = new LinkMan(); linkMan1.setLkm_name("小王"); LinkMan linkMan2 = new LinkMan(); linkMan1.setLkm_name("小刘"); LinkMan linkMan3 = new LinkMan(); linkMan1.setLkm_name("小张");
// 建立联系 linkMan1.setCustomer(customer); customer.getLinkMans().add(linkMan2); customer.getLinkMans().add(linkMan3);
// session.save(linkMan1); // 会发送几条insert语句 4 条 session.save(customer);// 会发送3条insert语句 //session.save(linkMan2);// 会发送2条insert语句 transaction.commit(); } |
(4)删除客户级联删除联系人
@Test /* * 删除客户级联删除联系人 */ public void demo6() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 注:级联删除必须是先查询再删除 Customer customer = session.get(Customer.class, 1l); session.delete(customer); transaction.commit(); } |
(5)双向关联产生多余的sql语句
产生的问题:双向维护了关系,而且持久态对象可以自动更新数据库,更新客户的时候会修改一次外键,更新联系人的时候同样也会修改一次外键。
解决:将一方放弃外键维护权。
注:多的一方才是维护关系最好的地方。
@Test /* * 双向维护关系 * 将2号联系人关联的客户改为2号客户 */ public void demo7() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 2l); LinkMan linkMan1 = session.get(LinkMan.class, 2l);
// 建立双向关系 linkMan1.setCustomer(customer); customer.getLinkMans().add(linkMan1); transaction.commit(); }
|
解决方式:
在一的映射文件中:
(6)区分cascade和inverse
cascade强调的是操作一个对象的时候,是否操作其关联对象。
inverse强调的是外键的维护权
在Customer.hbm.xml中set上配置
@Test /* * 区分cascade和inverse */ public void demo8() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 创建customer Customer customer = new Customer(); customer.setCust_name("王总"); LinkMan linkMan = new LinkMan(); linkMan.setLkm_name("李秘书");
customer.getLinkMans().add(linkMan);
session.save(customer);
transaction.commit(); } |
说明:执行保存客户的操作,会发现客户和联系人都插入到数据库中了,但是没有外键,这是因为客户放弃了外键维护权,但是cascade会将数据插入到数据库中。