一. 表与表之间的关系
1. 一对多的关系: 一对多建表,通过外键建立关系.
2.多对多的关系: 多对多建表,通过第三张表建立关系.
二.Hibernate的一对多操作
1.一对多映射配置
以客户和联系人为例: 客户为一,联系人是多;
第一步: 创建两个实体类: Customer类即客户类 和 LinkMan类即联系人类,其中Customer类表示一 ,LinkMan类表示多;
第二步: 让两个实体类之间相互表示;
(1)在客户实体类里面表示多个联系人
//在客户实体类里面表示多个联系人,一个客户有多个联系人
//hibernate要求使用集合表示多的数据,使用set集合
private Set<LinkMan> setLinkMan = new HashSet<LinkMan>();
public Set<LinkMan> getSetLinkMan() {
return setLinkMan;
}
public void setSetLinkMan(Set<LinkMan> setLinkMan) {
this.setLinkMan = setLinkMan;
}
(2)在联系人类里面表示所属客户
// 在联系人实体类里面表示所属客户,一个联系人只能属于一个客户
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
第三步: 配置映射关系
(1) 一般一个实体类对应一个映射文件
(2) 在映射文件中,配置一对多关系
Customer类的配置文件的内容
<hibernate-mapping>
<!-- 配置类和表对应
class标签
name属性: 实体类的全路径
table属性: 数据表的名称 -->
<class name="com.company.Customer" table="customer">
<id name="cid" column="cid">
<!--设置数据表id增长策略-->
<generator class="native"></generator>
</id>
<property name="custName" column="custName"></property>
<property name="custLevel" column="custLevel"></property>
<property name="custSource" column="custSource"></property>
<property name="custPhone" column="custPhone"></property>
<property name="custMobile" column="custMobile"></property>
<!-- 在客户映射文件中,表示所有联系人
使用set标签表示所有联系人
set标签里面有name属性:Set集合的对象
inverse 属性: 取消一对外键的操作 -->
<set name="setLinkMan" cascade="save-update,delete" inverse="true">
<!-- 一对多建表,有外键
hibernate机制: 双向维护外键,在一和多那一方都配置外键
column属性值: 外键名称 -->
<key column="cid"></key>
<!--客户所有人的联系人,class里面写联系人实体类全路径-->
<one-to-many class="com.company.LinkMan"></one-to-many>
</set>
</class>
</hibernate-mapping>
2.一对多级联保存
public void TestGave1() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//得到SessionFactory对象
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//添加一个客户,为这个客户添加一个联系人
//1.创建客户和联系人对象
Customer customer = new Customer();
customer.setCustName("百度");
customer.setCustLevel("普通客户");
customer.setCustSource("网络");
customer.setCustPhone("110");
customer.setCustMobile("999");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("小宏");
linkMan.setLkm_gender("男");
linkMan.setLkm_phone("911");
//2.把联系人放到客户里面
<!-- 简便方法:
1. 在Customer配置文件中的set标签中添加cascade属性,值为: save-update
这样配置之后,就可以省略linkMan 的 setCustomer方法 和 session.save(linkMan) 方法
-->
customer.getSetLinkMan().add(linkMan);
// linkMan.setCustomer(customer);
//3.保存客户
session.save(customer);
//session.save(linkMan);
//提交事务
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
3.一对多的级联删除
public void TestDelete() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//得到SessionFactory对象
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//添加一个客户,为这个客户添加一个联系人
//1.根据id查询到客户对象
Customer customer = session.get(Customer.class, 3);
//2.调用方法删除
session.delete(customer);
//提交事务
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
4.一对多级联修改
public void TestUpdate() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//得到SessionFactory对象
sessionFactory = HibernateUtils.getSessionFactory();
//得到session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//1. 根据id查询百度的客户
Customer baidu = session.get(Customer.class,1);
//2.根据id查询联系人
LinkMan linkMan = session.get(LinkMan.class,2);
//设置持久态的值
baidu.getSetLinkMan().add(linkMan);
//把客户放到联系人里面
linkMan.setCustomer(baidu);
//提交事务
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
注: inverse属性
1.因为hibernate是双向维护,在客户和联系人里面都需要维护外键,修改客户的时候修改一次外键,造成效率问题
2.解决方案: 在Customer配置文件中的set标签中添加inverse属性,属性值: true