首页 > 学院 > 开发设计 > 正文

Hibernate的级联操作

2019-11-08 02:37:09
字体:
来源:转载
供稿:网友

表与表间的联系

一对多

CRM系统 - 客户与联系人的关系

客户 —— 公司联系人—— 公司的员工

多对多

多对多的关系通过联系表两个实体联系起来

CRM系统 - 用户和角色

用户可以拥有多种角色一个角色可以有多个用户

一对一

hibernate中的一对多

一对多的映射配置

Step1:创建实体

Customer 客户LinkMan 联系人

Step2: 两个实体类之间互相表示

在客户实体类里面表示多个联系人

//在客户实体类里面表示多个联系人//hibernate要求使用集合set表示多的数据PRivate Set<LinkMan> linkMen = new HashSet<LinkMan>();

在联系人实体类里面表示所属客户

//在联系人实体类里面表示所属客户private Customer customer;

Step3:配置映射文件

一般一个实体类对应一个配置文件把映射最基本的配置完成

配置一对多关系

1.在客户的映射文件中,表示所有的联系人

<!-- 表示多方的配置 --> <set name="linkMen" > <!-- 一对多建表,有外键 hibernate机制:双向维护外键,在一方和多方都配置外键,名字需相同 column: 外键的名称 --> <key column="cust_id"></key> <!-- 客户所有的联系人 class:联系人实体类全路径 --> <one-to-many class="com.jeff.entity.LinkMan"/> </set>

2.在联系人的映射文件中,表示所属的客户

<!-- 一方配置多方的信息 column:外键--><many-to-one name="customer" column="cust_id" class="com.jeff.entity.Customer"></many-to-one>

Step4:核心配置文件引入映射配置文件

<mapping resource="com/jeff/entity/LinkMan.hbm.xml"/><mapping resource="com/jeff/entity/Customer.hbm.xml"/>

Step5:运行结果

-- customer表的信息CREATE TABLE `customer` ( `cust_id` int(11) NOT NULL AUTO_INCREMENT, `cust_name` varchar(255) DEFAULT NULL, `cust_level` varchar(255) DEFAULT NULL, `cust_source` varchar(255) DEFAULT NULL, `cust_mobile` varchar(255) DEFAULT NULL, `cust_address` varchar(255) DEFAULT NULL,PRIMARY KEY (`cust_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8-- link_man 表的信息CREATE TABLE `link_man` ( `lkm_id` int(11) NOT NULL AUTO_INCREMENT, `lkm_name` varchar(255) DEFAULT NULL, `lkm_gender` varchar(255) DEFAULT NULL, `lkm_mobile` varchar(255) DEFAULT NULL, `cust_id` int(11) DEFAULT NULL,PRIMARY KEY (`lkm_id`),KEY `FKd378jah5xd7bsqjolfsop35i` (`cust_id`),CONSTRAINT `FKd378jah5xd7bsqjolfsop35i` FOREIGN KEY (`cust_id`) REFERENCES `customer` (`cust_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8

一对多的级联操作

级联保存

简单的保存操作步骤

<!--1. 在一方(客户)的映射配置文件set标签中添加cascade属性--><set name="linkMen" cascade="save-update"><!--*********--></set>//2. 只需一方进行保存就行//客户Customer customer = new Customer();customer.setCustName("水里鸟国际有限公司");customer.setCustLevel("Vip");customer.setCustSource("www.exelinux.com");customer.setCustMobile("1668888");customer.setCustAddress("广州天河");//联系人LinkMan lm = new LinkMan();lm.setLkmName("陈丁烷");lm.setLkmGender("男");lm.setLkmMobile("13972517234");customer.getLinkMen().add(lm);session.save(customer);-- 3. 底层sql语言Hibernate: insert into customer (cust_name, cust_level, cust_source, cust_mobile, cust_address) values (?, ?, ?, ?, ?)Hibernate: insert into link_man (lkm_name, lkm_gender, lkm_mobile, cust_id) values (?, ?, ?, ?)Hibernate: update link_man set cust_id=? where lkm_id=?级联删除

删除一方时,多方都会删除

步骤

<!--1. 配置级联删除 set标签的cascade属性添加delete值--><set name="linkMen" cascade="save-update,delete">//2. 删除某个客户以及客户的所有联系人

注意

/* 若客户的映射配置文件中的set标签的cascade属性没有添加delete值 删除客户时,会抛出错误;但客户的信息会被删除,而关联联系人的 信息没有删除,仅是外键被设置为null*/Customer customer = session.get(Customer.class, 1);session.delete(customer);/* -- 运行结果 Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_name as cust_nam2_0_0_, customer0_.cust_level as cust_lev3_0_0_, customer0_.cust_source as cust_sou4_0_0_, customer0_.cust_mobile as cust_mob5_0_0_, customer0_.cust_address as cust_add6_0_0_ from customer customer0_ where customer0_.cust_id=? Hibernate: update link_man set cust_id=null where cust_id=? Hibernate: delete from customer where cust_id=?org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.cache.spi.RegionFactory]at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:184)at org.hibernate.cfg.Settings.getRegionFactory(Settings.java:300)....*/一对多修改操作//将联系人的客户修改//1. 查询客户(联系人最终修改的客户)Customer customer = session.get(Customer.class, 4);//2. 查询需要修改的联系人LinkMan lm = session.get(LinkMan.class, 3);//3. 修改客户的信息customer.getLinkMen().add(lm);//4. 修改联系人的信息lm.setCustomer(customer);//实体类的持久态会自动保存,不需调用save()方法由于hibernate的默认机制:双向维护,所以在修改客户信息会修改外键,修改联系人的信息时也会修改一次外键,这就造成外键的重复修改,从而降低效率和性能-- 运行结果,其中外键被修改了2次Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_name as cust_nam2_0_0_, customer0_.cust_level as cust_lev3_0_0_, customer0_.cust_source as cust_sou4_0_0_, customer0_.cust_mobile as cust_mob5_0_0_, customer0_.cust_address as cust_add6_0_0_ from customer customer0_ where customer0_.cust_id=?Hibernate: select linkman0_.lkm_id as lkm_id1_1_0_, linkman0_.lkm_name as lkm_name2_1_0_, linkman0_.lkm_gender as lkm_gend3_1_0_, linkman0_.lkm_mobile as lkm_mobi4_1_0_, linkman0_.cust_id as cust_id5_1_0_ from link_man linkman0_ where linkman0_.lkm_id=?Hibernate: select linkmen0_.cust_id as cust_id5_1_0_, linkmen0_.lkm_id as lkm_id1_1_0_, linkmen0_.lkm_id as lkm_id1_1_1_, linkmen0_.lkm_name as lkm_name2_1_1_, linkmen0_.lkm_gender as lkm_gend3_1_1_, linkmen0_.lkm_mobile as lkm_mobi4_1_1_, linkmen0_.cust_id as cust_id5_1_1_ from link_man linkmen0_ where linkmen0_.cust_id=?Hibernate: -- 多方的维护修改update link_man set lkm_name=?, lkm_gender=?, lkm_mobile=?, cust_id=? where lkm_id=?-- 一方的维护修改 Hibernate: update link_man set cust_id=? where lkm_id=?

解决方法

一方放弃外键的维护,仅有多方进行外键维护配置set标签的inverse属性值<!-- inverse 设置外键的维护机制 false 默认值,不放弃双向维护 true 放弃外键维护 --><set name="linkMen" cascade="save-update,delete" inverse="true">-- 运行结果Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_name as cust_nam2_0_0_, customer0_.cust_level as cust_lev3_0_0_, customer0_.cust_source as cust_sou4_0_0_, customer0_.cust_mobile as cust_mob5_0_0_, customer0_.cust_address as cust_add6_0_0_ from customer customer0_ where customer0_.cust_id=?Hibernate: select linkman0_.lkm_id as lkm_id1_1_0_, linkman0_.lkm_name as lkm_name2_1_0_, linkman0_.lkm_gender as lkm_gend3_1_0_, linkman0_.lkm_mobile as lkm_mobi4_1_0_, linkman0_.cust_id as cust_id5_1_0_ from link_man linkman0_ where linkman0_.lkm_id=?Hibernate: select linkmen0_.cust_id as cust_id5_1_0_, linkmen0_.lkm_id as lkm_id1_1_0_, linkmen0_.lkm_id as lkm_id1_1_1_, linkmen0_.lkm_name as lkm_name2_1_1_, linkmen0_.lkm_gender as lkm_gend3_1_1_, linkmen0_.lkm_mobile as lkm_mobi4_1_1_, linkmen0_.cust_id as cust_id5_1_1_ from link_man linkmen0_ where linkmen0_.cust_id=?Hibernate: update link_man set lkm_name=?, lkm_gender=?, lkm_mobile=?, cust_id=? where lkm_id=?

hibernate的多对多的操作

用户与角色的示例

Step1: 创建用户与角色的实体

User 用户Role 角色

Step2: 在实体类里表示多对多的关系

一个用户可以拥有多个角色

//用户用户多个角色的表示private Set<Role> roles = new HashSet<Role>();一个角色可以有多个用户 java //角色有多个用户的表示 private Set<User> users = new HashSet<User>();

Step3: 配置相应的映射

用户映射配置

<!-- 配置多对多的关系 table:自动生成关联表的名称--><set name="roles" table="user_role"> <!-- column:user自身在关联表中的外键名称 --> <key column="uid"></key> <!-- column: 另一个多方(角色)在关联表中的外键名称 --> <many-to-many class="com.jeff.entity.Role" column="role_id"></many-to-many></set>

角色映射配置

<!-- 配置多对多的关系table:自动生成关联表的名称--><set name="users" table="user_role"><!-- column:role自身在关联表中的外键名称 --><key column="role_id"></key><!-- column: 另一个多方(角色)在关联表中的外键名称 --><many-to-many class="com.jeff.entity.User" column="uid"></many-to-many></set>

注意

两者的关联表的名称必须相同key的外键配置是自身在关联表中的外键名称,但必须与对方在many-to-many标签中的column属性的值相同

Step4: 核心配置中引入映射配置

Step5: 运行

-- 关联表中的信息 CREATE TABLE `user_role` ( `uid` int(11) NOT NULL, `role_id` int(11) NOT NULL, PRIMARY KEY (`role_id`,`uid`), KEY `FKsx7vp1qbr8ktssdi3etxwtci6` (`uid`), CONSTRAINT `FKj88osoj2hsbpvwgraxlnh2442` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`role_id`), CONSTRAINT `FKsx7vp1qbr8ktssdi3etxwtci6` FOREIGN KEY (`uid`) REFERENCES `t_user` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8

多对多的级联保存

与一对多级联操作相同

多对多的级联删除(一般不用)

维护关联表

修改用户的角色

//1. 查询用户和角色的信息User user = session.get(User.class, 3);Role role = session.get(Role.class, 6);//2. 修改用户中的角色user.getRoles().add(role);

删除用户拥有的角色

//1. 查询用户和角色的信息User user = session.get(User.class, 3);Role role = session.get(Role.class, 5);//2. 移除用户角色user.getRoles().remove(role);
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表