当前位置: 首页 > 编程日记 > 正文

初学者易上手的SSH-hibernate04 一对一 一对多 多对多

这章我们就来学习下hibernate的关系关联,即一对一(one-to-one),一对多(one-to-many),多对多(many-to-many)。这章也将是hibernate的最后一章了,用于初学者可以了。

首先讲述一对一:就以一个人对应一张身份证为列子。

第一步:新建表 persion(人)与card(身份证) 表结构如下  两个pid都给的varchar是为了在主键生成策略中使用uuid

第二步:项目/com.entity下新建两个实体类,与数据库对应,然后封装构造,有参构造中去掉pid。建好后再新建这两个类的hbm.xml文件,在persion.hbm.xml中将<id/>节点中的主键生成策略改成uuid

    <id name="pid" type="java.lang.String"><column name="PID" />
//改uuid<generator class="uuid" /></id>

将card.hbm.xml中的<id/>节点中的主键生成策略改成foreign,等于外键的意思

<id name="pid" type="java.lang.String"><column name="PID" /><!-- 主键生成策略 改成外键 --><generator class="foreign">            </generator></id>

第三步:就要开始建立一对一关系了:先在persion实体类中定义一个card的对象,记住不要实例化(new),然后封装。

private Card card;
public Card getCard() {return card;}public void setCard(Card card) {this.card = card;}

接着在card实体类中定义一个persion的对象,也不要实例化(new),然后封装。

    private Person person;public Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}

第四步:就要开始建立一对关系的配置了。在persion.hbm.xml<class/>节点中添加<one-to-one/>节点;其中name属性值为persion实体类中定义的card对象的变量名。            

    <one-to-one name="card" class="com.entity.Card" cascade="all"></one-to-one>

在card.hbm.xml<class/>节点中添加<one-to-one/>节点;其中name属性值为card实体类中定义的persion对象的变量名。    

<one-to-one name="person" class="com.entity.Person"></one-to-one>

还要在card.hbm.xml主键生成策略中添加一个参数<param/>,其中name属性值为固定写法,persion为card实体类中定义的persion对象的变量名。  

<id name="pid" type="java.lang.String"><column name="PID" /><!-- 主键生成策略 改成外键 --><generator class="foreign"><param name="property">person</param></generator></id>

配置到这里就完了。那么有人肯定会有疑问?

persion.hbm.xml 中的<one-to-one/>中cascade="all"是什么意思?

cascade这个属性就相当与两张表的关联属性,有以下属性值

none:所有情况下均不进行关联操作。这是默认值。 

all:所有情况下均进行关联操作

save-update:在执行save/update/saveOrUpdate时进行关联操作。

delete:在执行delete时进行关联操作。

all-delete-orphan:当对象图中产生孤儿节点时,在数据库中删除该节点

就拿delete来说吧,就是删除persion的对象数据时,对应的card对象数据也将被删除。

第五步:hibernate.cfg.xml配置文件中加上实体类.hbm.xml的映射关系<mapping/>

<mapping resource="com/entity/Card.hbm.xml" /><mapping resource="com/entity/Person.hbm.xml" />

第六步:就要开始测试了:建立一个测试类,其中写个junit的@Test测试方法。

既然用了@Tset,那么就在再用下@Before(方法执行之前触发)与@Aafter(方法执行之后触发),这样我们就可以将重复的代码写在这两个方法里面,减轻代码量

private Configuration configuration;

private SessionFactory factory;

private Session session;


  private Transaction transaction;



@Before
public void Before() {configuration = new Configuration().configure();factory = configuration.buildSessionFactory();session = factory.openSession();transaction = session.beginTransaction();}

@Afterpublic void after() {// 关闭seeion
        session.close();// 关闭SessionFactory
        factory.close();}

增加:注意要互相添加值(互设)

@Test
    public void add() {

  // 增加Person p = new Person("哈哈");Card c = new Card("431088192215523305");互设p.setCard(c);c.setPerson(p);
//这里因为建立cascade关联关系,所以只要添加设立了关系那端即可session.save(p);transaction.commit();
}

查询:

    // 查询Person p = session.get(Person.class,"4028abee5f2a0142015f2a0144280000");System.out.println(p+"--"+p.getCard());

其余我就不再测试了。

接下来讲述一对多:以一个省份对应多个城市为例子。

第一步:一样要新建两张表,province(省份)与城市(city),表结构如下:

第二步:项目/com.entity下新建两个实体类,与数据库对应,然后封装构造,有参构造中去掉表主键。建好后再新建这两个类的hbm.xml文件,在province.hbm.xml与city.hbm.xml中将<id/>节点中的主键生成策略改成uuid。

第三步:在province(一端)实体类中定义并实例化city(多端)的集合,(set与list)以set为例。然后封装即可。

    private Set<City> cities = new HashSet<>();public Set<City> getCities() {return cities;}public void setCities(Set<City> cities) {this.cities = cities;}

第四步:在city(多端)实体类中定义province(一端)对象,封装。注意:这个时候要将pid(多端表中一端表外键)这个属性在city的实体类中去掉(数据库表中依然存在),因为已经定义的province的对象,同时请将city.hbm.xml中所对应生成pid的<property/>节点也去掉!

     private Province province;public Province getProvince() {return province;}public void setProvince(Province province) {this.province = province;}

第五步:在一端的hbm.xml中<class/>节点中添加如下代码:

<!--name 一端类中定义多端的集合名 table 表名 -->
<set name="cities" table="city" inverse="true" cascade="save-update"><key><!-- 一端(province)主键名 --><column name="pid" /></key><!-- 多端类(city)全限定名 --><one-to-many class="com.entity.City" /></set>

 在多端的hbm.xml中<class/>节点中添加如下代码:

<!--name="多端类中定义一端的集合名" class="一端类全限定名" --><many-to-one name="province" class="com.entity.Province"><!-- 多端表中外键名(一端主键名) --><column name="pid" /></many-to-one>

第六步:hibernate.cfg.xml配置文件中加上实体类.hbm.xml的映射关系<mapping/>

<mapping resource="com/entity/Province.hbm.xml" /><mapping resource="com/entity/City.hbm.xml" />

这样配置就可以了,那么疑问又来了?在一端的hbm.xml<set/>中inverse又是什么?

Inverse:负责控制关系,默认为false,也就是关系的两端都能控制,但这样会造成一些问题,更新的时候会因为两端都控制关系,于是重复更新。一般来说有一端要设为true。那么SQL语句的维护关系就在多端进行操作。

第七步:测试:@Test就与一对一的测试方法一样即可

增加:

         Province p = new Province("湖南");City c = new City("长沙");City c1 = new City("株洲");City c2 = new City("湘潭");
//互设
         p.getCities().add(c);p.getCities().add(c1);p.getCities().add(c2);c.setProvince(p);c1.setProvince(p);c2.setProvince(p);session.save(p);transaction.commit();

查询:

    City c = (City) session.createQuery("from City where cname=?").setParameter(0, "长沙").uniqueResult();System.out.println(c.getProvince().getPid());

其余的方法就不测试了。

最后讲述多对多:就以多个角色对应多个权限,多个权限对应多个角色为例子:

第一步:还是老样子建表:角色表(users),权限表(role),还要一张中间表(users_role),表结构如下:

第二步:项目/com.entity下新建两个实体类,中间表不用,与数据库对应,然后封装构造,有参构造中去掉表主键。建好后再新建这两个类的hbm.xml文件,在hbm.xml中将<id/>节点中的主键生成策略改成uuid。

第三步:在这两个实体类中定义并实例化对方的集合,(set与list)以set为例。然后封装即可。

第四步:在users.hbm.xml中添加如下代码:

//name=集合对象名  table=中间表名 
<set name="roles" table="users_role" inverse="true" cascade="save-update">
//该类主键名<key column="uid"></key>
//calss set集合中对象的全路径名 column外键名(set集合中对象的主键名)<many-to-many class="com.entity.Role" column="rid" /></set>

在role.hbm.xml中添加如下代码:

//name=集合对象名  table=中间表名 
<set name="users" table="users_role" inverse="true" cascade="save-update">
//该类主键名<key column="rid"></key>
//calss set集合中对象的全路径名 column外键名(set集合中对象的主键名)<many-to-many class="com.entity.Users" column="uid" /></set>

第六步:hibernate.cfg.xml配置文件中加上实体类.hbm.xml的映射关系<mapping/>

    <mapping resource="com/entity/Users.hbm.xml" /><mapping resource="com/entity/role.hbm.xml" />

最后测试:

增加:

         Users u = new Users("哈哈");Role r = new Role("草鸡管理员");Role r1 = new Role("普通管理员");Role r2 = new Role("垃圾管理员");u.getRoles().add(r);u.getRoles().add(r1);u.getRoles().add(r2);r.getUsers().add(u);r1.getUsers().add(u);r2.getUsers().add(u);

transaction.commit();

查询:

Users s = session.get(Users.class, "4028abee5f664493015f6644959b0001");
     for (Role r : s.getRoles()) {
       System.out.println(r);
         }

//List<Users> ls = session.createQuery("from Users u left outer join fetch u.roles r where r.rid='4028abee5f664493015f6644958a0000'").list();//    for (Users users : ls) {//       System.out.println(users.getRoles());//    }

到此,hibernate结束!

转载于:https://www.cnblogs.com/lzx2509254166/p/7766930.html

相关文章:

Python爬虫入门教程 54-100 博客园等博客网站自动评论器

爬虫背景 爬虫最核心的问题就是解决重复操作&#xff0c;当一件事情可以重复的进行的时候&#xff0c;就可以用爬虫来解决这个问题&#xff0c;今天要实现的一个基本需求是完成“博客园“ 博客的自动评论&#xff0c;其实原理是非常简单的&#xff0c;提炼一下需求 基本需求 登…

T-SQL Convert转换时间类型

关键字: sql 时间 转化 SQL中CONVERT转化函数的用法 格式: CONVERT(data_type,expression[,style]) 说明: 此样式一般在时间类型(datetime,smalldatetime)与字符串类型(nchar,nvarchar,char,varchar) 相互转换的时候才用到. 例子: SELECT CONVERT(varchar(30),getdate(),101) n…

解决Lodop 8443端口找不到CLodopfuncs.js文件问题

问题描述&#xff1a; GET https://localhost:8443/CLodopfuncs.js?nameCLODOP net::ERR_CERT_COMMON_NAME_INVALID 可能原因&#xff1a; https证书问题&#xff0c;通用名称不合法&#xff0c;地址栏访问https://localhost:8443&#xff0c;如下图所示 解决方法&#…

CString工作原理和常见问题分析

关于Cstring 类 版权所有©Stevencaobenq.com2003-11-6转自&#xff1a;http://blog.csdn.net/laiyiling/archive/2004/10/05/125216.aspx 看了很多人写的程序,包括我自己写的一些代码&#xff0c;发现很大的一部分bug是关于MFC类中的CString的错误用法的.出现这种错误的原…

javascript 学习三 语句

1、if 语句 if (condition){ do something else } condition 是条件语句&#xff0c;在这里&#xff0c;condition 可以是任意表达式&#xff0c;但结果不一定就是布尔值&#xff0c;但javascript 会调用 boolean&#xff08;&#xff09; 来把结果转换成布尔值。 2、do-while …

新建本地仓库,同步远程仓场景,出现git branch --set-upstream-to=origin/master master 解决方法...

1.本地创建一个本地仓库 2.关联远程端:git remote add origin gitgithub.com:用户名/远程库名.git3.同步远程仓库到本地git pull这个时候会报错If you wish to set tracking information for this branch you can do so with:git branch --set-upstream-toorigin/<branch>…

Git npm相关命令

Git 相关命令查看用户名和密码配置用户名和密码查看git项目远程地址添加git远程仓库查看提交记录查看已有tag打标签在某次提交记录上打标签推送标签到远程推送单个指定tag到远程推送多个tag到远程2. npm相关命令2.1 设置npm源2.2 查看npm源2.3 npm清缓存查看用户名和密码 $ gi…

2009年上半年网络工程师考试下午试卷参考答案(一)

试题一&#xff08;15分&#xff09;  阅读以下说明&#xff0c;回答问题1至问题4&#xff0c;将解答填入答题纸对应的解答栏内。【说明】某公司有1个总部和2个分部&#xff0c;各个部门都有自己的局域网。该公司申请了4个C类IP地址块202.114.10.0/24~202.114.13.0/24。公司各…

创建Silverlight自定义启动画面

每一款商业的Silverlight项目&#xff0c;为了体现项目个性化&#xff0c;都会有不同的界面设计&#xff0c;项目UI设计的第一步就是创建个性的自定义启动画面&#xff0c;本文将介绍如何创建Silverlight自定义启动画面&#xff0c;也就是经常说的Splash Screen. Silverlight初…

params.success params.success(res.data)

params.success && params.success(res.data)只有success 为真&#xff0c;才执行后边的代码转载于:https://www.cnblogs.com/qq254980080/p/10619413.html

有关 drop delete truncate 问题

drop 可以删除数据库 数据表 数据表中字段 delete 删除数据表中的行 而不删除数据表 可以删除一行&#xff1a; Delete from 表 where 列名称值 或是多行&#xff1a; Delete from 表 truncate 删除数据表中数据 而不删除数据表&#xff1a; truncate table 表 三者的删除速度 …

IDEAWebstorm使用

IDEA&Webstorm使用小记录 插件 1. CodeGlance 在编辑器窗格中嵌入一个类似于Sublime中的代码小地图。使用自定义的颜色进行语法高亮&#xff0c;可以同时处理浅色和深色主题。 2. Free Mybatis plugin 3. MyBatis Log Plugin

如何用JNI技术提高Java的性能详解

阻碍Java获得广泛应用的一个主要因素是Java程序的运行效率。Java是介于解释型和编译型之间的一种语言&#xff0c;同样的程序&#xff0c;如果用编译型语言C来实现&#xff0c;其运行速度一般要比Java快一倍以上。Java具有平台无关性&#xff0c;这使人们在开发企业级应用的时候…

Jquery实战_读书笔记1—选择jQuery

近期公司积极组织我们这些开发人员学习进步&#xff0c;督促我们学习更多的技术来提高自己。为此我选择了jQuery作为我学习的方向&#xff0c;同时我也是想将我的学习心得分享给大家&#xff0c;以后我会不断的更新一系列jQuery方面的学习纪要&#xff0c;帮助大家学习。 对比了…

Python入门(一)数据类型、循环语句

脚本语言类型&#xff1a; 1.编译型语言&#xff1a;写完代码不能执行&#xff0c;需要先编译 eg&#xff1a;c、c、c# 2.解释性语言&#xff1a;不需要编译 直接执行 eg&#xff1a;python、java、php、js、go、ruby 编程工具 pycharm 1.破解方法&a…

ionic项目创建打包签名

1. 环境搭建 1.1 安装Node.js 使用node -v查看Node.js版本 1.2 安装npm 使用npm -v查看npm版本 1.3 安装ionic 使用npm install -g ionic命令&#xff0c;全局安装最新版本的ionic 使用ionic -v查看当前安装的ionic版本 1.4 安装cordova 使用npm install -g cordova命令…

Java 常用对象-Date类和Calender类

2017-11-02 22:29:34 Date类&#xff1a;类 Date 表示特定的瞬间&#xff0c;精确到毫秒。 在 JDK 1.1 之前&#xff0c;类 Date 有两个其他的函数。它允许把日期解释为年、月、日、小时、分钟和秒值。它也允许格式化和解析日期字符串。不过&#xff0c;这些函数的 API 不易于实…

为你的水晶报表装载本地图片

本文为解答该贴所做&#xff1a;http://topic.csdn.net/u/20090524/15/911fd15a-32c6-4be9-9aa1-3ee95365e7e3.html 并没有什么新内容&#xff0c;主要是如何读取本地图片显示在报表中。 如果是CR XI及以上版本&#xff0c;可以用更简便的方法&#xff0c;参考&#xff1a;水晶…

asp.net断点续传技术

断点续传的原理 在了解HTTP断点续传的原理之前&#xff0c;先来说说HTTP协议&#xff0c;HTTP协议是一种基于tcp的简单协议&#xff0c;分为请求和回复两种。请求协议是由客户机(浏览器)向服务器(WEB SERVER)提交请求时发送报文的协议。回复协议是由服务器(web server)&#xf…

Linux安装Nodejs

Linux安装Nodejs 阿里云镜像&#xff1a; https://npm.taobao.org/mirrors/node/ 选择所需版本&#xff0c;进行下载。 我这边下载的是&#xff1a;https://npm.taobao.org/mirrors/node/v8.2.1/node-v8.2.1-linux-x64.tar.gz 环境&#xff1a; linux 7.x 目录结构&#xff08…

jQuery-1.样式篇---选择器

jQuery选择器之id选择器 页面的任何操作都需要节点的支撑&#xff0c;开发者如何快速高效的找到指定的节点也是前端开发中的一个重点。jQuery提供了一系列的选择器帮助开发者达到这一目的&#xff0c;让开发者可以更少的处理复杂选择过程与性能优化&#xff0c;更多专注业务逻辑…

CentOS 7 相关命令

Centos 7 相关命令 查看Linux内核/操作系统/CPU # uname -a查看系统位数是64位还是32位 # getconf LONG_BIT检验java是否安装成功 # java -version查询java的执行路径 # which java打开java环境变量的配置文件 # vi /etc/profile配置java环境变量后重新加载配置文件 …

51cto的初体验

注册该网站也有一段时间了&#xff0c;第一次来到这个网站是在一次无意间搜索某个问题的时候进来的&#xff0c;我有一个习惯&#xff0c;就是每次一遇到不懂的问题就会上网搜&#xff0c;看看大家都是怎么解决的&#xff0c;至少到现在用这种方法&#xff0c;我已经解决了不少…

Codeforces Round #550 (Div. 3)E. Median String

把字符串看作是26进制的数&#xff0c;从后往前翻译&#xff0c;那么就可以把两个串变成对应的26进制的数字&#xff0c;那么只要把两个数加起来除以二就得到中间的串对应的数了&#xff0c;同理再转化回来就行了。但是这样会有一个问题就是串的长度有2e5&#xff0c;26的2e5次…

window.print()前端实现打印功能

方法介绍 window.print()方法用于打印当前窗口的内容。 默认打印页面中body里的所有内容。 调用 print() 方法会产生一个打印预览弹框&#xff0c;让用户可以设置打印配置。 1. 打印方法 1.1 打印当前窗口内容 示例demo如下&#xff1a; <!DOCTYPE html> <html la…

.NET 4.0 Interop新特性ICustomQueryInterface (转载)

.NET 4.0 Interop新特性ICustomQueryInterface 在.NET Framework v4.0发布的新功能中&#xff0c;在名字空间System.Runtime.InteropServices新增加了一个叫做ICustomQueryInterface的Interface, 顾名思义&#xff0c;这个Interface的功能就是使得用户可以自己控制QueryInterf…

HTML5 3D旋转图片相册

H5旋转3D相册&#xff0c;鼠标放置暂停&#xff0c;图片灰度级为0&#xff0c;有放大效果。 该实例运用H5和CSS3动画效果&#xff0c;未用javascript。提高了本人对CSS3 新属性的了解及掌握。 完整代码如下&#xff1a; <!DOCTYPE html> <html lang"en">…

DHTML中style的display和visibility属性

DHTML中style的display和visibility属性 display是隐藏该对象&#xff0c;使该对象不占用页面排版空间。document.all("tr1").style.display"block"document.all("tr1").style.display"none" visibility只是在页面上看不见&#xff0c…

多线程共享全局变量以及锁机制

多线程都是在同一个进程中运行的。因此在进程中的全局变量所有线程都是共享的&#xff0c;这就造成一个问题&#xff0c;因为线程执行的顺序是无序的&#xff0c;有可能会造成数据错误&#xff0c;为了解决这个问题&#xff0c; threading提供了一个lock类&#xff0c;这个类可…

HTML DOM Console对象

在开发过程中对程序进行测试&#xff0c;经常使用浏览器控制台输出相关信息&#xff0c;下面详细介绍console对象的相关方法。 Console 对象 提供了访问浏览器调试模式的信息到控制台 1. console.assert()方法 用法&#xff1a;该方法在第一个参数为 false 的情况下会在控制台…