提纲:
1.表与表之间的关系
2.hibernate一对多操作
(1)一对多映射配置
(2)一对多级联保存
(3)一对多级联删除
(4)inverse属性
3.hibernate多对多操作
(1)多对多映射配置
(2)多对多级联保存
(3)多对多级联删除
(4)维护第三张表
###1.表与表之间的关系
####一对多(客户和联系人)
(1)分类和商品关系,一个分类里面有多个商品,一个商品只能属于一个分类
(2)客户与联系人是一对多关系
客户:与公司有业务往来,百度,新浪,360
联系人:公司里面的员工,百度里面有很多员工,练习员工相当于练习客户
公司和公司员工的关系,客户是一,联系人是多:
一个客户里面有多个联系人,一个联系人只能属于一个客户
(3)一对多建表,通过外键建立关系
在多的那一方创建字段作为外键,指向少的那一方的主键
####多对多(用户和角色)
(1)订单和商品的关系,一个订单里面有多个商品,一个商品属于多个订单
(2)用户和角色关系
用户:小王,小马,小宋
角色:总经理,秘书,司机,保安
一个用户可以多个角色,一个角色可以多个用户
一对一
(1)一个男人对应一个老婆,一个女人对应一个老人
###Hibernate的一对多操作(重点)
####一对多的映射关系
以客户和联系人为例,客户是一,联系人是多
第一步 创建实体类(这里我创建的是Customer和LinkMan两个实体类)
第二步 让两个实体类之间互相进行表示
(1)在客户实体类里面表示多个联系人
一个客户里面有多个联系人
//hibernate要求使用集合表示多的数据,使用set集合
private Set<LinkMan> setLinMan=new HashSet<LinkMan>();
public Set<LinkMan> getSetLinMan() {
return setLinMan;
}
public void setSetLinMan(Set<LinkMan> setLinMan) {
this.setLinMan = setLinMan;
}
(2)在联系人实体类中里表示所属客户
一个联系人只能属于一个客户
private Customer customer;
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
第三步 配置映射文件
(1)一般一个实体类对应一个映射文件
(2)把映射最基本的配置完成
(3)在映射文件文件中,配置一对多关系
在客户映射文件中,表示所有联系人
<!-- 在客户映射文件中,表示所有联系人
使用set标签表示所有联系人
set标签name属性,属性值写在客户实体类里面表示联系人的set集合名称
-->
<set name="setLinkMan">
<!-- 一对多键表,有外键
hibernate机制,双向维护外键,在一和多的那一方配置外键
column属性值,外键名称
-->
<key column="clid">
</key>
<!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
<one-to-many class="cn.lawfree.entity.LinkMan"/>
</set>
在联系人映射文件中表示所有的客户
<!-- 表示联系人所属客户
name属性.因为联系人实体类使用customer对象表示,写customer名称
clas属性,customer全路径
colmn属性,外键名称
-->
<many-to-one name="customer" class="cn.lawfree.entity.Customer" column="clid">
</many-to-one>
第四步 创建核心配置文件,把映射文件放到核心配置文件中
<mapping resource="cn/lawfree/entity/Customer.hbm.xml"/>
<mapping resource="cn/lawfree/entity/LinkMan.hbm.xml"/>
####一对多级联操作
#####1.级联保存
(1)添加一个客户,为这个客户添加多个联系人
// 一对多级联保存 (复杂写法)
@Test
public void testAddDemo1() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
// 得到sessionFaction
sessionFactory = HibernateUtils.getSessionFactory();
// 得到session
session = sessionFactory.openSession();
// 开启事务
tx = session.beginTransaction();
// 添加一个客户,为这个添加联系人
// 1.创建客户和联系人对象
Customer customer = new Customer();
customer.setCustName("传智播客");
customer.setCustLevel("vip");
customer.setCustSource("网络");
customer.setCustPhone("110");
customer.setCustPhone("999");
LinkMan linkman = new LinkMan();
linkman.setLkm_name("lucy");
linkman.setLkm_gender("男");
linkman.setLkm_phone("911");
// 2.在客户表示所有联系人,再联系人表示客户
// 建立客户对象和联系人对象关系
// 2.1把联系人放到客户对象的set集合里面
customer.getSetLinkMan().add(linkman);
// 2.2把客户对象放到联系人里面
linkman.setCustomer(customer);
// 3.保存到数据库
session.save(customer);
session.save(linkman);
// 提交事务
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
一对多级联保存 (简化写法)
第一步 在客户映射文件中进行配置
在客户映射文件里面set标签中配置
<set name="setLinkMan" cascade="save-update">
第二步 创建客户和联系人对象,只需要把联系人放到客户里面就可以了,最终只需要保存客户就可以了.
// 2.在客户表示所有联系人,再联系人表示客户
customer.getSetLinkMan().add(linkman);
// 3.保存到数据库
session.save(customer);
#####2.级联删除
(1)删除某一个客户,这个客户里面所有联系人都会被删除
(2)具体实现
第一步 在客户映射文件set标签,进行配置属性为cascade,值为delete
<set name="setLinkMan" cascade="save-update,delete">
第二步 在代码中直接删除客户
根据id查询对象,调用session中的delete方法删除
// 1.根据id查询客户对象
Customer customer = session.get(Customer.class, 2);
// 2.调用方法删除
session.delete(customer);
(3)执行过程
根据id先查询客户
根据外键查联系人
把联系人的外键设置为null
删除联系人与客户
#####3.级联修改
(1)让lucy所属的客户不是网易而是百度
// 1.根据id查询lucy联系人,根据id查询百度的客户
Customer baidu = session.get(Customer.class, 2);
LinkMan lucy = session.get(LinkMan.class, 1);
// 2.设置持久态对象值
// 把联系人放到客户里面
baidu.getSetLinkMan().add(lucy);
// 把客户放到联系人里面
lucy.setCustomer(baidu);
(2)因为hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改客户时候改了一次外键,修改联系人时又改了一次外键,造成性能下降
解决方式:让其中的一方放弃外键维护
**一对多里面,让其中一方放弃外键维护(让一的那方放弃关系维护)
具体实现:在放弃维护映射文件中进行配置,在set标签上使用
###Hibernate的多对多操作
####多对多映射配置
以用户和角色为例演示
第一步 创建实体类,用户和角色
第二步 让两个实体类之间相互表示
(1) 一个用户里面表示所有的角色,使用set集合
//一个用户可以有多个角色
private Set<Role> setRole=new HashSet<Role>();
public Set<Role> getSetRole() {
return setRole;
}
public void setSetRole(Set<Role> setRole) {
this.setRole = setRole;
}
(2) 一个角色有多个用户,使用set集合
// 一个角色有多个用户
private Set<User> setUser = new HashSet<User>();
public Set<User> getSetUser() {
return setUser;
}
public void setSetUser(Set<User> setUser) {
this.setUser = setUser;
}
第三步 配置映射关系
(1)基本配置
(2)配置多对多关系
在用户里面表示所有的角色,使用set标签
<!-- 在用户里面表示所有角色,使用set标签
name属性,角色set集合名称
table属性,第三张表名称
-->
<set name="setRole" table="user_role">
<!-- key标签里面配置
配置当前映射文件在第三张表的外键名称
-->
<key column="userid"></key>
<!-- class 角色实体类全路径
column 角色在第三张表的外键名称
-->
<many-to-many class="cn.lawfree.manytomany.Role" column="roleid"></many-to-many>
</set>
在角色里面表示所有的用户,使用set标签
<!-- 在角色里面表示所有用户,使用set标签 -->
<set name="setUser" table="user_role">
<!--key标签里面配置
角色在第三张表中的配置
-->
<key column="roleid"></key>
<!-- class 角色实体类的全路径
column 角色在第三张表的外键名称
-->
<many-to-many class="cn.lawfree.manytomany.User" column="userid"></many-to-many>
</set>
第四步 在核心配置中引入配置文件
<mapping resource="cn/lawfree/manytomany/Role.hbm.xml"/>
<mapping resource="cn/lawfree/manytomany/User.hbm.xml"/>
####多对多级联保存
根据用户保存角色
第一步 在用户配置文件set标签中进行配置,cascade值 save-update
<set name="setRole" table="user_role" cascade="save-update">
第二步 写代码实现
(1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了
(2)
@Test
public void testSave() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
// 得到sessionFaction
sessionFactory = HibernateUtils.getSessionFactory();
// 得到session
session = sessionFactory.openSession();
// 开启事务
tx = session.beginTransaction();
// 添加两个用户,为每个用户添加两个角色
// 1.创建对象
User user1 = new User();
user1.setUser_name("lucy");
user1.setUser_password("123");
User user2 = new User();
user2.setUser_name("mary");
user2.setUser_password("456");
Role r1 = new Role();
r1.setRole_name("总经理");
r1.setRole_memo("总经理");
Role r2 = new Role();
r2.setRole_name("秘书");
r2.setRole_memo("总秘书");
Role r3 = new Role();
r3.setRole_name("保安");
r3.setRole_memo("保安");
// 2.建立关系,把角色放到用户里
// user1--r1/r2
user1.getSetRole().add(r1);
user1.getSetRole().add(r2);
// user2--r2/r3
user2.getSetRole().add(r2);
user2.getSetRole().add(r3);
// 保存用户
session.save(user1);
session.save(user2);
// 提交事务
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
####多对多级联删除(了解)
第一步 在set标签进行配置,cascade值delete
第二步 删除用户
User lucy=session .get(User.class, 1);
session.delete(lucy);
####维护第三张表关系
用户和角色是多对多的关系,维护关系通过第三张表维护
让某个用户有某个角色
第一步 根据id查询用户和角色
第二步 把角色对象放到用户set集合
// 让某个用户有某个角色
// 1.查询lucy总经理
User lucy = session.get(User.class, 1);
Role role = session.get(Role.class, 3);
// 2.把角色放到用户的set集合里面
lucy.getSetRole().add(role);
让某个用户没有某个角色
第一步 根据id查询用户和角色
第二步 从用户里面把角色去掉
// 让某个用户没有有某个角色
// 1.查询lucy总经理
User lucy = session.get(User.class, 1);
Role role = session.get(Role.class, 3);
// 2.把角色从用户的set集合里面删掉
lucy.getSetRole().remove(role);