hibernate 一对多操作:
(1).一对多映射配置
(以客户和联系人为例,客户是一,联系人是多)
第一步:导入jar包
第二步:创建实体类(两个,一个客户的,一个联系人)
第三步:让这两个实体类之间相互表示.
(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).把映射最基本的配置完成
(3).在映射文件中,配置一对多的关系在客户的映射文件中,表示所有的联系人
在联系人中,表示所属的客户.
<!-- 在客户的映射文件中,表示所有的联系人 使用set标签表示所有的联系人 set标签里面有name属性, 属性值写在客户实体类里面表示联系人的set集合名称 --> <set name="setLinkMan"> <!-- 一对多建表,有外键. hibernate机制, 双向维护外键, 在一和多那一方都配置外键. column属性值就是外键的名称 --> <key column="clid"></key> <!-- 客户所有的联系人,class里面写联系人实体类的全路径 --> <one-to-many class="com.yao.entity.LinkMan"/> </set>
第五步:创建核心配置文件, 把映射文件映入到核心配置文件中
<!-- 表示联系人所属的客户 name属性: 因为在联系人实体类使用customer对象表示,写customer名称 class属性: customer全路径 column属性: 外键的名称clid --> <many-to-one name="customer" class="com.yao.entity.Customer" column="clid"></many-to-one>
第六步: 测试, 执行工具类
级联操作:
(2).一对多级联保存
1.级联保存
(1).添加了客户,为这个客户添加了多个联系人
(添加客户,为这个客户添加一个联系人)
//添加一个客户,为这个客户添加一个联系人. //1.创建客户跟联系人的对象 Customer customer = new Customer(); customer.setCustName("同福客栈"); customer.setCustLevel("vip"); customer.setCustSource("网络"); customer.setCustPhone("110"); customer.setCustMobilb("666"); 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);
简化写法:(根据客户添加联系人)
第一步:在客户映射文件中进行配置; 在客户映射配置文件中set标签内进行配置属性==> cascade="save-update"
<set name="setLinkMan" cascade="save-update">
第二步:创建客户和联系人对象,只要把联系人放到客户里面就可以了,最终只需要保存客户就可以了.
//1.创建客户跟联系人的对象 Customer customer = new Customer(); customer.setCustName("龙门客栈"); customer.setCustLevel("普通客户"); customer.setCustSource("网络"); customer.setCustPhone("949"); customer.setCustMobilb("2233"); LinkMan linkMan = new LinkMan(); linkMan.setLkm_name("小花"); linkMan.setLkm_gender("女"); linkMan.setLkm_phone("666"); //2.把联系人放到客户里面 customer.getSetLinkMan().add(linkMan); //3.保存客户 session.save(customer); session.save(linkMan);
(3).一对多级联删除
(1).删除某一个客户,这个客户里面的所有联系人也删除(删除某个客户,把客户里面所有的联系人删除)
第一步:在客户映射文件set标签`,进行配置==> cascade="save-delete" (注意, 多个属性用逗号隔开)
(1).使用属性cascade="save-update,delete"
第二步:在代码中直接删除客户.
(1).先根据id查询对象,在调用session里面的delete方法删除
//1.根据id查询出客户对象 Customer customer = session.get(Customer.class, 2); //2调用方法删除 session.delete(customer);
执行过程:
(1).根据id查询客户
(2).根据外键查询联系人
(3).把联系人的外键设置为null;
(4).删除联系人和客户
(4).一对多修改操作
1.让lucy联系人所属客户不是同福, 而是龙门
//1.根据id查询lucy联系人, 根据id查询百度的客户 Customer Tongfu = session.get(Customer.class, 3); LinkMan lucy = session.get(LinkMan.class, 1); //2.设置持久态对象值 //把联系人客户里面 Tongfu.getSetLinkMan().add(lucy); //把客户放到联系人里面 lucy.setCustomer(Tongfu);
(5).inverse属性
1.因为hibernate双向维护外键,在客户和联系人里面都需要维护外键, 修改客户的时候修改一次外键, 修改联系人的时候也修改一次外键, 造成效率问题.
2.解决方式:让其中一的一方不维护外键一对多里面,让其中一方放弃对外键的维护. 一个国家有总统,国家有很多人,总统不能这个国家所有的人,国家所有的人认识总统.
3.具体实现: 在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性
<!-- inverse属性默认是false不放弃关系维护 true 放弃关系维护 --> <set name="setLinkMan" cascade="save-update,delete" inverse="true">
hibernate 多对多操作:
(1).多对多映射配置
以用户和角色为例演示
第一步: 创建实体类: 用户和角色
第二步: 两个实体类之间相互表示
(1).用户里面表示所有角色,使用set集合
(2).一个角色多个用户,使用set集合
第三步: 配置映射关系
(1). 基本配置
(2).配置多对多关系在用户里面表示所有的角色, set标签
<!-- 在用户里面表示所有角色, 使用set标签 name属性, 角色set集合名称 table属性, 第三张表的名称 --> <set name="setRole" table="user_role"> <!-- key标签里面要配置当前的映射文件在第三张表中外键名称 --> <key column="userid"></key> <!-- class: 角色实体类全路径 column: 角色在第三张表外键名称 --> <many-to-many class="com.yao.entity.Role" column="roleid"></many-to-many> </set>
在角色里面表示所有的用户, set标签
<!-- 在角色里面表示所有的用户, set标签 --> <set name="setUser" table="user_role"> <!-- 角色在第三张表的外键 --> <key column="roleid"></key> <many-to-many class="com.yao.entity.User" column="userid"></many-to-many> </set>
第四步: 在核心配置文件中映入配置文件
<mapping resource="com/yao/entity/User.hbm.xml"/> <mapping resource="com/yao/entity/Role.hbm.xml"/>
第五步:测试运行utils类,查看数据库是否创建三张表.
(2).多对多级联保存(重点)
根据用户保存用户第一步:在用户映射配置文件中set标签进行配置, cascade值save-update
<set name="setRole" table="user_role" cascade="save-update">
第二步:写代码实现(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 role1 = new Role(); role1.setRole_name("总经理"); role1.setRole_memo("总经理"); Role role2 = new Role(); role2.setRole_name("秘书"); role2.setRole_memo("秘书"); Role role3 = new Role(); role3.setRole_name("保安"); role3.setRole_memo("保安"); //2.建立关系,把角色放到用户里面 //user1 ==> r1/r2 user1.getSetRole().add(role1); user1.getSetRole().add(role2); //user2 ==> r2/r3 user2.getSetRole().add(role2); user2.getSetRole().add(role3); //3.保存用户 session.save(user1); session.save(user2);
(3).多对多级联删除
第一步: 在set标签里面进行配置,cascade 里面save-update,delete
<set name="setRole" table="user_role" cascade="save-update,delete">
第二步:(注意: 一般不用, 删除会将相关联的表的全部数据删除)
//级联删除 User user = session.get(User.class, 1); session.delete(user);
(4).维护第三张表
1.用户和叫是多对多关系, 维护关系是通过第三张表维护
2.让某个用户有某个角色
第一步: 先根据id查询用户和角色
第二步: 把角色对象放到用户里面
(1).把角色对象放到用户set集合
//让lucy有经纪人的角色 //1.查询lucy和经纪人 User lucy = session.get(User.class, 1); Role role = session.get(Role.class, 4); //2.把角色放到用户的set集合里面 lucy.getSetRole().add(role);
3.让某个用户没有某个角色.
第一步: 先根据id查询用户和角色
第二步: 从用户里面把角色去掉
(1).从set集合里面把角色移除
//让lucy有经纪人的角色 //1.查询lucy和经纪人 User lucy = session.get(User.class, 2); Role role = session.get(Role.class, 3); //从用户里面把角色去掉 lucy.getSetRole().remove(role);
叨叨几句... NOTHING