Hibernate多表映射(三)
一对多|多对一
一个分类对应多个商品,一个商品只属于一个分类
创建分类表 products用set装,set特点值不能够重复
- package com.hibernate.domain;
- import java.util.HashSet;
- import java.util.Set;
- public class Category {
- private Integer cid;
- private String cname;
- private Set<Product> products = new HashSet<Product>();
- public Integer getCid() {
- return cid;
- }
- public void setCid(Integer cid) {
- this.cid = cid;
- }
- public String getCname() {
- return cname;
- }
- public void setCname(String cname) {
- this.cname = cname;
- }
- public Set<Product> getProducts() {
- return products;
- }
- public void setProducts(Set<Product> products) {
- this.products = products;
- }
- }
创建商品表 category表示所属分类
- package com.hibernate.domain;
- public class Product {
- private Integer pid;
- private String pname;
- private Category category;
- public Integer getPid() {
- return pid;
- }
- public void setPid(Integer pid) {
- this.pid = pid;
- }
- public String getPname() {
- return pname;
- }
- public void setPname(String pname) {
- this.pname = pname;
- }
- public Category getCategory() {
- return category;
- }
- public void setCategory(Category category) {
- this.category = category;
- }
- }
配置映射关系
Category.hbm.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
- <hibernate-mapping package="com.hibernate.domain">
- <class name="Category" table="Category">
- <id name="cid" column="cid">
- <generator class="native"/>
- </id>
- <property name="cname"/>
- <!--配置一对多关系
- set表示所有products
- name 实体类中 商品集合属性
- -->
- <set name="products">
- <!--column 外键名 -->
- <key column="cpid"></key>
- <one-to-many class="Product"></one-to-many>
- </set>
- </class>
- </hibernate-mapping>
Product.hbm.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
- <hibernate-mapping package="com.hibernate.domain">
- <class name="Product" table="Product">
- <id name="pid">
- <generator class="native"/>
- </id>
- <property name="pname"/>
- <!--配置多对一 所属分类
- name 分类属性
- class 分类全路径
- column 外键名称 要与 一对多设置的外键一样
- -->
- <many-to-one name="category" class="Category" column="cpid"></many-to-one>
- </class>
- </hibernate-mapping>
配置全局映射hibernate.cfg.xml
- <mapping resource="com/hibernate/domain/Category.hbm.xml"></mapping>
- <mapping resource="com/hibernate/domain/Product.hbm.xml"></mapping>
插入
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- Category category = new Category();
- category.setCname("产品分类");
- Product p1 = new Product();
- p1.setPname("产品1");
- p1.setCategory(category);
- Product p2 = new Product();
- p2.setPname("产品2");
- p2.setCategory(category);
- category.getProducts().add(p1);
- category.getProducts().add(p2);
- session.save(category);
- session.save(p1);
- session.save(p2);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
为已有分类追加商品
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- //获得已有分类对象
- Category category = session.get(Category.class,1);
- Product p = new Product();
- p.setCategory(category);
- p.setPname("小米电脑");
- category.getProducts().add(p);
- session.save(p);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
移除分类下的商品 (将商品的外键设置为null 并没有删除)
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- //获得已有分类对象
- Category category = session.get(Category.class,1);
- Product p = session.get(Product.class,2);
- category.getProducts().remove(p);
- p.setCategory(null);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
cascade级联操作
级联保存更新 只保存分类 自动把产品也保存
首先配置category.hbm.xml
- <hibernate-mapping package="com.hibernate.domain">
- <class name="Category" table="Category">
- ...
- <!--级联操作:cascade
- save-update:级联保存更新
- delete:级联删除
- all:save-update+delete -->
- <set name="products" cascade="save-update">
- <key column="cpid"></key>
- <one-to-many class="Product"></one-to-many>
- </set>
- </class>
- </hibernate-mapping>
编辑代码 只需要save 分类即可
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- Category category = new Category();
- category.setCname("产品分类1");
- Product p1 = new Product();
- p1.setPname("产品11");
- p1.setCategory(category);
- Product p2 = new Product();
- p2.setPname("产品22");
- p2.setCategory(category);
- category.getProducts().add(p1);
- category.getProducts().add(p2);
- session.save(category);
- //session.save(p1);
- //session.save(p2);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
级联删除 配置hbm.xml 为delete
- <hibernate-mapping package="com.hibernate.domain">
- <class name="Category" table="Category">
- 。。。
- <!--级联操作:cascade
- save-update:级联保存更新
- delete:级联删除
- all:save-update+delete-->
- <set name="products" cascade="delete">
- <key column="cpid"></key>
- <one-to-many class="Product"></one-to-many>
- </set>
- </class>
- </hibernate-mapping>
编写删除代码 该分类下的产品都将被删除
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- Category category = session.get(Category.class,4);
- session.delete(category);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
cascade="all" 就是 添加 修改 删除时 不用save 商品 直接操作分类即可
在产品的配置文件中 也可以设置 many-to-one cascade="save-update" 操作时 就是不用操作分类表了
作用:简化操作,如果一定要用就用save-update,不要用delete。
inverse属性
关系维护,在保存时,两方都会维护外键关系,存在多余的维护关系语句。
上面保存分类和商品时 生成的sql语句如下:
- Hibernate: insert into Category (cname) values (?)
- Hibernate: insert into Product (pname, cpid) values (?, ?)
- Hibernate: insert into Product (pname, cpid) values (?, ?)
- Hibernate: update Product set cpid=? where pid=?
- Hibernate: update Product set cpid=? where pid=?
配置Category.hbm.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
- <hibernate-mapping package="com.hibernate.domain">
- <class name="Category" table="Category">
- 。。。
- <!-- inverse:配置关系是否维护
- true:不维护
- false:维护(默认值)-->
- <set name="products" inverse="true">
- <key column="cpid"></key>
- <one-to-many class="Product"></one-to-many>
- </set>
- </class>
- </hibernate-mapping>
修改配置文件后 重新运行程序 sql语句如下:
- Hibernate: insert into Category (cname) values (?)
- Hibernate: insert into Product (pname, cpid) values (?, ?)
- Hibernate: insert into Product (pname, cpid) values (?, ?)
inverse的作用就是 优化性能,此配置只能设置一的一方放弃维护关系,多的一方不可以放弃维护关系。
多对多
一个用户可以有很多角色,一个角色可以有很多用户。
使用中间表,至少两列,都是外键,分别引用其他两张表的主键
创建user表 set装role集合
- package com.hibernate.domain;
- import java.util.HashSet;
- import java.util.Set;
- public class User {
- private Integer uid;
- private String uname;
- private Set<Role> roles = new HashSet<Role>();
- public Integer getUid() {
- return uid;
- }
- public void setUid(Integer uid) {
- this.uid = uid;
- }
- public String getUname() {
- return uname;
- }
- public void setUname(String uname) {
- this.uname = uname;
- }
- public Set<Role> getRoles() {
- return roles;
- }
- public void setRoles(Set<Role> roles) {
- this.roles = roles;
- }
- }
创建role表 set装user
- package com.hibernate.domain;
- import java.util.HashSet;
- import java.util.Set;
- public class Role {
- private Integer rid;
- private String rname;
- private Set<User> users = new HashSet<User>();
- public Integer getRid() {
- return rid;
- }
- public void setRid(Integer rid) {
- this.rid = rid;
- }
- public String getRname() {
- return rname;
- }
- public void setRname(String rname) {
- this.rname = rname;
- }
- public Set<User> getUsers() {
- return users;
- }
- public void setUsers(Set<User> users) {
- this.users = users;
- }
- }
编写 User.hbm.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
- <hibernate-mapping package="com.hibernate.domain">
- <class name="User" table="User">
- <id name="uid">
- <generator class="native"/>
- </id>
- <property name="uname"/>
- <!--多对多关系
- table:中间表名
- -->
- <set name="roles" table="User_Role">
- <!--column 别人引入我的外键 uid -->
- <key column="uid"></key>
- <!--column 另外一方的外键 rid -->
- <many-to-many class="Role" column="rid"></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
编写role.hbm.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
- <hibernate-mapping package="com.hibernate.domain">
- <class name="Role" table="Role">
- <id name="rid">
- <generator class="native"/>
- </id>
- <property name="rname"/>
- <set name="users" table="User_Role">
- <key column="rid"></key>
- <many-to-many column="uid" class="User"></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
最后写入全局配置中
- <mapping resource="com/hibernate/domain/User.hbm.xml"></mapping>
- <mapping resource="com/hibernate/domain/Role.hbm.xml"></mapping>
添加操作
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- User u1 = new User();
- u1.setUname("武大郎");
- User u2 = new User();
- u2.setUname("武松");
- Role r1 = new Role();
- r1.setRname("卖烧饼");
- Role r2 = new Role();
- r2.setRname("武都头");
- u1.getRoles().add(r1);
- u2.getRoles().add(r2);
- //武松帮大哥卖卖烧饼
- u2.getRoles().add(r2);
- r1.getUsers().add(u1);
- r1.getUsers().add(u2);
- r2.getUsers().add(u2);
- session.save(u1);
- session.save(u2);
- session.save(r1);
- session.save(r2);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
虽然会插入数据成功 但是运行后会报错:could not execute statement(插入主键报错),是因为双方都维护关系导致。
解决办法1: 去掉一方的维护关系
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- User u1 = new User();
- u1.setUname("武大郎");
- User u2 = new User();
- u2.setUname("武松");
- Role r1 = new Role();
- r1.setRname("卖烧饼");
- Role r2 = new Role();
- r2.setRname("武都头");
- u1.getRoles().add(r1);
- u2.getRoles().add(r2);
- //武松帮大哥卖卖烧饼
- u2.getRoles().add(r2);
- // r1.getUsers().add(u1);
- // r1.getUsers().add(u2);
- // r2.getUsers().add(u2);
- session.save(u1);
- session.save(u2);
- session.save(r1);
- session.save(r2);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
解决办法2:
修改配置文件,选择一方不维护关系 加入节点inverse=true
- <hibernate-mapping package="com.hibernate.domain">
- <class name="User" table="User">
- <id name="uid">
- <generator class="native"/>
- </id>
- <property name="uname"/>
- <!--user一方 放弃维护 -->
- <set name="roles" table="User_Role" inverse="true">
- <key column="uid"></key>
- <many-to-many class="Role" column="rid"></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
然后把注释放开 ,运行 也不会报错了。
级联操作cascade
编辑user.hbm.xml配置文件
- <hibernate-mapping package="com.hibernate.domain">
- <class name="User" table="User">
- <id name="uid">
- <generator class="native"/>
- </id>
- <property name="uname"/>
- <!--user一方 放弃维护 -->
- <set name="roles" table="User_Role" inverse="true" cascade="save-update">
- <key column="uid"></key>
- <many-to-many class="Role" column="rid"></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
剩下联行save而已
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- User u1 = new User();
- u1.setUname("武大郎");
- User u2 = new User();
- u2.setUname("武松");
- Role r1 = new Role();
- r1.setRname("卖烧饼");
- Role r2 = new Role();
- r2.setRname("武都头");
- u1.getRoles().add(r1);
- u2.getRoles().add(r2);
- //武松帮大哥卖卖烧饼
- u2.getRoles().add(r2);
- r1.getUsers().add(u1);
- r1.getUsers().add(u2);
- r2.getUsers().add(u2);
- session.save(u1);
- session.save(u2);
- //session.save(r1);
- //session.save(r2);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
只save一方,另一方自动save。
不建议使用 如果非要用就用save-update。
解除权限关系
- public class Main {
- public static void main(String[] args) {
- Session session = HibernateUtils.getCurrentSession();
- Transaction trans = session.beginTransaction();
- try {
- User u = session.get(User.class,2);
- //武松不想卖烧饼了
- Role r = session.get(Role.class,1);
- r.getUsers().remove(u);
- trans.commit();
- } catch (Exception ex){
- System.out.println(ex);
- trans.rollback();
- }
- }
- }
Hibernate多表映射(三)的更多相关文章
- Hibernate单表映射学习笔记之一——hibernalnate开发环境配置
1.什么是ORM? Object/Relationship Mapping:对象/关系映射 2.写SQL语句不好之处: (1)不同数据库使用的SQL语法不同(PL/SQL.T/SQL) (2)同样的功 ...
- Hibernate 表映射 主键生成策略与复合主键
主要分析三点: 一.数据表和Java类的映射 : 二.单一主键映射和主键的生成策略 : 三.复合主键的表映射 : 一.数据表和Java类的映射 Hibernate封装了数据库DDL语句,只需要将数据 ...
- 同一个数据库实例,不同用户下多表创建视图,Hibernate完毕ORM映射,Spring整合,后台实现
1.同一个数据库实例.同用户,多表创建视图 2.同一个数据库实例,不同用户下.多表创建视图 3.同一个数据库,不同数据库实例,多表创建视图 4.不同类型数据库,多表创建视图 1.同一个数据库实例.同用 ...
- hibernate之单表映射
目录 第一章 Hibernate初识 1-1 课程介绍 1-2 什么是ORM 1-3 Hibnerate简介 1-4 开发前的准备 1-5 编写第一个Hibernate例子 1-6 创建hiberna ...
- 怎么让Intellj Idea 把数据库的表映射成hibernate的domain对象
步骤如下: 第一步:连接数据源: 点击:idea右边的database.如下图所示: 或者你依次点击:view-->Tool windows--->database 然后你将看在如下点击下 ...
- Hibernate初探之单表映射——Hibernate概念及插件的安装
什么是ORM ORM(Object/Relationship Mapping):对象/关系映射 为什么要有ORM? 利用面向对象思想编写的数据库应用程序最终都是把对象信息保存在关系型数据库中,于是要编 ...
- hibernate(3) —— 关系映射
hibernate中关系映射指的是实体类与实体类间的关系.和数据库中表与表之间的关系类似,有一对一,多对一,一对多,多对多四种映射关系. 一:一对一映射 两个对象之间是一对一的关系,如人和身份证之间是 ...
- Hibernate的关联映射
单向N-1关联 <many-to-one> 单向N-1关系,比如多个人对应同一个住址,只需要从人实体端找到对应的住址实体,无须关系某个地址的全部住户.程序在N的一端增加一个属性,该属性引用 ...
- Hibernate配置文件和映射元素解释
象关系的映射是用一个XML文档来说明的.映射文档可以使用工具来生成,如XDoclet,Middlegen和AndroMDA等.下面从一个映射的例子开始讲解映射元素. AD:干货来了,不要等!WOT20 ...
随机推荐
- vue-cli3 中的环境变量
官方文档是这样写的: src同名文件夹下的建立 .env.[model] 配置文件 // mode:production development ... 载入的变量会对vue-cli-service ...
- java 导入导出的 命令
$exp lddba/ld_321@192.168.1.3/testora file=E:\db_bak\ld20170219_1testora.dmp log=E:\db_bak\ld2017021 ...
- 利用WMITool解决浏览器快捷方式启动参数被篡改以及浏览器主页被劫持的问题
先说说症状 症状①:通过快捷方式启动浏览器,首页跳转到2345以及hao123网址导航页,切系统内安装的多款浏览器(IE.Chrome.Firefox.Opera.Safari.Maxthon)症状相 ...
- python爬虫17 | 听说你又被封 ip 了,你要学会伪装好自己,这次说说伪装你的头部
这两天 有小伙伴问小帅b 为什么我爬取 xx 网站的时候 不返回给我数据 而且还甩一句话给我 “系统检测到您频繁访问,请稍后再来” 小帅b看了一下他的代码 ): requests.get(url) 瞬 ...
- 3.3.4 lambda 表达式
lambda表达式常用来声明匿名函数,即没有函数名字的临时使用的小函数,例如第2章中列表对象的sort()方法以及内置函数sorted()中key参数.lambda表达式只可以包含一个表达式,不允许包 ...
- Python 6 数字和布尔值及字符串的基本功能
数据类型:查看变量数据类型type(变量) 或者 print(type(变量)) 整数int:就是不带小数的自然数字,也叫整型.在2.X版本中还分为长整型和整形.但是在3.X版本中统一称为整数或整 ...
- centos7安装opennms-17.0.0
https://blog.csdn.net/jiangzhexi/article/details/52036858 http://www.jb51.net/os/RedHat/281470.html
- POJ 3304 segments 线段和直线相交
Segments Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14178 Accepted: 4521 Descrip ...
- Libevent 学习笔记 (1)——Libevent 2.0安装与简单演示样例
今天開始学习Libevent . Libevent 是开源社区的一款高性能I/O框架库. 主要特点有: 1 跨平台. 2 统一事件源 3 线程安全 4 基于Reactor 今天主要进行了Libeven ...
- 翻翻git之---溜的飞起的载入效果AVLoadingIndicatorView
转载请注明出处:王亟亟的大牛之路 由于接近过春节.看各个群体的工作都不太旺盛(不是年会就是各种吹B或是放空). 之前的Material Design的内容差点儿讲的差点儿相同了(至少基本的几个控件都介 ...