一对多|多对一

  一个分类对应多个商品,一个商品只属于一个分类

  创建分类表 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多表映射(三)的更多相关文章

  1. Hibernate单表映射学习笔记之一——hibernalnate开发环境配置

    1.什么是ORM? Object/Relationship Mapping:对象/关系映射 2.写SQL语句不好之处: (1)不同数据库使用的SQL语法不同(PL/SQL.T/SQL) (2)同样的功 ...

  2. Hibernate 表映射 主键生成策略与复合主键

    主要分析三点: 一.数据表和Java类的映射 : 二.单一主键映射和主键的生成策略 : 三.复合主键的表映射 : 一.数据表和Java类的映射  Hibernate封装了数据库DDL语句,只需要将数据 ...

  3. 同一个数据库实例,不同用户下多表创建视图,Hibernate完毕ORM映射,Spring整合,后台实现

    1.同一个数据库实例.同用户,多表创建视图 2.同一个数据库实例,不同用户下.多表创建视图 3.同一个数据库,不同数据库实例,多表创建视图 4.不同类型数据库,多表创建视图 1.同一个数据库实例.同用 ...

  4. hibernate之单表映射

    目录 第一章 Hibernate初识 1-1 课程介绍 1-2 什么是ORM 1-3 Hibnerate简介 1-4 开发前的准备 1-5 编写第一个Hibernate例子 1-6 创建hiberna ...

  5. 怎么让Intellj Idea 把数据库的表映射成hibernate的domain对象

    步骤如下: 第一步:连接数据源: 点击:idea右边的database.如下图所示: 或者你依次点击:view-->Tool windows--->database 然后你将看在如下点击下 ...

  6. Hibernate初探之单表映射——Hibernate概念及插件的安装

    什么是ORM ORM(Object/Relationship Mapping):对象/关系映射 为什么要有ORM? 利用面向对象思想编写的数据库应用程序最终都是把对象信息保存在关系型数据库中,于是要编 ...

  7. hibernate(3) —— 关系映射

    hibernate中关系映射指的是实体类与实体类间的关系.和数据库中表与表之间的关系类似,有一对一,多对一,一对多,多对多四种映射关系. 一:一对一映射 两个对象之间是一对一的关系,如人和身份证之间是 ...

  8. Hibernate的关联映射

    单向N-1关联 <many-to-one> 单向N-1关系,比如多个人对应同一个住址,只需要从人实体端找到对应的住址实体,无须关系某个地址的全部住户.程序在N的一端增加一个属性,该属性引用 ...

  9. Hibernate配置文件和映射元素解释

    象关系的映射是用一个XML文档来说明的.映射文档可以使用工具来生成,如XDoclet,Middlegen和AndroMDA等.下面从一个映射的例子开始讲解映射元素. AD:干货来了,不要等!WOT20 ...

随机推荐

  1. mybatis批量操作(foreach)

    foreach可以在SQL语句中通过拼接的方式进行集合迭代.foreach元素的属性主要有collection,item,index,separator,open,close. item属性:表示循环 ...

  2. Python----DFS---骑士周游问题

    这篇文章将会将一个数据结构与算法中一个很经典很重要的概念——深度优先搜索(Depth-First-Search:DFS).........(你他喵不是在标题里说了吗?) 好吧,DFS的精髓我其实也还没 ...

  3. 一个带关闭按钮的Div窗口,很漂亮

    <html><head><title>JS+CSS实现带关闭按钮的DIV弹出窗口</title><script> function lock ...

  4. 基于vue的nuxt框架cnode社区服务端渲染

    nuxt-cnode 基于vue的nuxt框架仿的cnode社区服务端渲染,主要是为了seo优化以及首屏加载速度 线上地址 http://nuxt-cnode.foreversnsd.cngithub ...

  5. hdu2010 水仙花数【C++】

    水仙花数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  6. Ch’s gift

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Proble ...

  7. [luoguP2870] [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold(后缀数组)

    传送门 数据小的话贪心就行. 可以把这个串翻转再接到后面,再求后缀数组,求出 rank 数组就很简单了. ——代码 #include <cstdio> #include <iostr ...

  8. 06springMVC数据验证

    u  声明式数据验证 u  内置的验证约束和注解 u  错误消息 u  功能处理方法上多个验证参数的处理 u  异常处理的支持 1      声明式数据验证 Spring3开始支持JSR-303验证框 ...

  9. Spring MVC-集成(Integration)-生成PDF示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_pdf.htm 说明:示例基于Spring MVC 4.1.6. 以下示例显示如何 ...

  10. 权限问题导致无法删除ftp文件

    首先吐槽一下,使用新版编辑器,发了两遍愣是time out,果断放弃 这个文章也是一件小事,大致说一下: 有一个java操作ftp文件的程序,运行删除时,总是返回false,也没有报错.開始考虑是没有 ...