分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

Hibernate多表映射(三)

发布时间:2023-09-06 01:55责任编辑:熊小新关键词: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多表映射(三)

原文地址:https://www.cnblogs.com/baidawei/p/9063478.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved