一对多|多对一

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

  创建分类表 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. 表单enctype属性传值问题

    form表单的enctype设置为multipart/form-data后,表单中除了文件后台能拿到,其他值后台都拿不到. 知识点: 一.application/x-www-form-urlencod ...

  2. Labview学习笔记(三)

    一.数据 1.数值控件 (1)数值控件 根据不同的模拟状态,放置不同控件 (2)显示格式 为了程序显示,需要设置数值型控件的表示法.数值范围.显示格式等属性. 一般来说,长度越长,则可以表示的数值范围 ...

  3. PAT 1109 Group Photo

    Formation is very important when taking a group photo. Given the rules of forming K rows with N peop ...

  4. 【郑轻邀请赛 G】密室逃脱

    [题目链接]:https://acm.zzuli.edu.cn/zzuliacm/problem.php?id=2133 [题意] [题解] 考虑每一个二进制数的最高位->第i位; 肯定是1(这 ...

  5. RestEasy 用户指南---第11章 @FormParam

    转载说明出处:http://blog.csdn.net/nndtdx/article/details/6870391 原文地址 http://docs.jboss.org/resteasy/docs/ ...

  6. N天学习一个linux命令之xargs

    用途 标准输入流读取参数(空格或者换行符分隔),传递给需要执行的命令 用法 xargs [options] [command [initial-arguments]] 常用选项 --arg-file= ...

  7. IDFTP连不上FTP服务器的解决方法

    使用IDFTP连不上FTP服务端. 原来是IDFTP有2种模式:主动模式和被动模式. IDFTP默认是使用主动模式,如果FTP服务端设置使用被动模式,使用IDFTP连不上FTP服务端的. 解决方法: ...

  8. Mac OSX:添加host地址

    Mac OSX的hosts文件位于/private/etc/hosts.记得用sudo权限编辑即可.在文件中添加如下内容: xxx.xxx.xxx.xxx (ip地址)     abc.com(你的h ...

  9. 微信的token验证

    微信的token验证 在微信公众平台的基本配置中,需要输入token,这个token不是那个access_token springmvc验证代码: @RequestMapping(value=&quo ...

  10. clCreateCommandQueue&#39;: was declared deprecated

    今天在配置opencl的开发环境.測试用例时,用的是intel的sdk开发包.遇到了这个问题: clCreateCommandQueue': was declared deprecated 也就是说这 ...