hibernate关联对象的增删改查------增
本文可作为,北京尚学堂马士兵hibernate课程的学习笔记。
这一节,我们看看hibernate关联关系的增删改查
就关联关系而已,咱们在上一节已经提了很多了,一对多,多对一,单向,双向...
其实咱们可以简单的说就是A与B,有关系。
至于他们到底是一对多,多对一,暂且不论。
咱们要讨论的是,如果我存储A,那么数据库里是否会有B;如果我删除A,那么与之相关的B是否也会删除;如果我更新了A,那么B是否会被更新;如果我查询出A,那么B是否也会被查询出来。
首先,咱们看一对多,多对一双向的例子。
还是我们上一节的例子,dream与person。
一个person有多个dream,而每一个dream只能属于一个person。
我们在配置xml时,让hibernate自动生成建表语句,并且每次都新生数据库。
<property name="hbm2ddl.auto">create</property>
实体类情况
@Entity
public class Person {
private int id;
private String name;
private Set<Dream> dreams=new HashSet<>();
@Id
@GeneratedValue
public int getId() {
return id;
}
@Column(name ="myname")
public String getName() {
return name;
}
@OneToMany(mappedBy="person")
public Set<Dream> getDreams() {
return dreams;
}//省略部分代码
}
@Entity
public class Dream {
private int id;
private String description;
private Person person;
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToOne
@JoinColumn(name="personId")
public Person getPerson() {
return person;
} //省略部分代码
}
OK,两个类的关系已经很清楚了,双向多对一/一对多。
如果我们的测试代码如下:
//代码片1
public static void main(String[] args) {
Person p=new Person();
p.setName("dlf");
Dream d=new Dream();
d.setDescription("marry glt");
d.setPerson(p);
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
session.save(p);
session.save(d);
session.getTransaction().commit();
}
上面的代码是没有问题的,而且即使先save dream也OK。
那么现在问题来了
d.setPerson(p);
这句代码,已经说明了dream里有一个引用指向了person。
那么我可以在代码层次不save person么?
即只有一个
session.save(d);
答案是否定的,报下面的错误。
object references an unsaved transient instance - save the transient instance before flushing: com.bjsxt.hibernate.Person
因为在数据库保存dream的时候,person还没有保存,所以出错了。
上面的例子告诉我们,默认情况下:hibernate不会替我们存储"一"的那一方。
当我写到这块的时候,我忽然脑子一抽,又写下了下面的测试代码:
//代码片2
public static void main(String[] args) {
Dream d=new Dream();
d.setDescription("marry glt");
Person p=new Person();
p.setName("dlf");
p.getDreams().add(d);
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
session.save(p);
session.getTransaction().commit();
}
如果,我以"一"的那一方为主,上面的代码会是个什么情况?
答案是,不报错,代码能正常执行,但是数据库里只有p的信息而没有d的信息。
上面的代码确实有点奇葩了,在上一节的时候,我们就已经达成了共识,在处理关联关系时,数据库层面总是在多的那一方维护关系。
所以上面的代码,并不能保存dream。
上面也说了,是在默认情况下,那特殊情况呢?
我们看api文档
上面是manytoone这个元标签可以带的属性,cascade翻译成中文就是级联。他是caschdetype型的
而Caschdetype是enum型的。可以取六个值
我们最经常用的就是,all,persist与remove。
all的意思是,对这个对象的增删改四中操作都会影响到与之关联的那个对象。(关于查询的级联,由另一个属性管理)
persist的意思是,对这个对象的增加(save操作)会连带把与之关联的那个对象也sava了。
remove的意思就是,如果删除这个对象也会删除与之关联的那个对象。
OK看下面的改动
@ManyToOne(cascade={CascadeType.ALL})
@JoinColumn(name="personId")
public Person getPerson() {
return person;
}
此时,我们下面的代码,就能正常运行了,而且数据库里,两个对象都存储了,且外键关联也是OK的。
//代码片3
Person p=new Person();
p.setName("dlf");
Dream d=new Dream();
d.setDescription("marry glt");
d.setPerson(p);
session.save(d);
写到这,我的脑子又抽了,如果我给onetomany的那一方加上cascade会如何?
@OneToMany(mappedBy="person",cascade={CascadeType.ALL})
public Set<Dream> getDreams() {
return dreams;
}
测试代码:
Dream d=new Dream();
d.setDescription("marry glt");
Person p=new Person();
p.setName("dlf");
p.getDreams().add(d);
session.save(p);
cascade确实有用,此时数据库里已经有了dream,但是dream的外键是null。
为什么?因为dream里并没有关联person。
其实,cascade这个东西也不是绝对的,如果关联关系比较麻烦,我们发现数据库里总是少存了一个对象,那就按照代码1的办法,直接存两次对象不就OK了。
谈点规律:
1 我们发现如果存储对象的时候,我们从多的一方操作是比较简单的。所以以后,尽量在多的一方操作。
2 为了符合逻辑,同时也不出错,一点两个对象之间的关系是双向的,那么在代码层次,就把两个的引用都设好,这样就不会出问题了。
3 之前说的,如果是双向的,设定mappedby。
hibernate关联对象的增删改查------增的更多相关文章
- 【基础篇】js对本地文件增删改查--增
前置条件: 1. 本地有安装node,点击传送门 项目目录: 1. msg.json内容 { "data": [ { "id": 1, "name&q ...
- Sqlserver 增删改查----增
注意我说的常见查询,可不是简单到一个表得增删改查,做过实际开发得人都知道,在实际开发中,真正牵扯到一个表得增删改查只能说占很小得一部分,大多都是好几个表的关联操作的. 下面我就说一下我在实际开发中经常 ...
- Ajax增删改查-----------增
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- php 数据库内容增删改查----增
首先,建立一个主页面(crud.php) <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- django基础之day04,必知必会13条,双下划线查询,字段增删改查,对象的跨表查询,双下划线的跨表查询
from django.test import TestCase # Create your tests here. import os import sys if __name__ == " ...
- MongoDB的ObjectId和基本操作增删改查(3)
ObjectId 基本操作增删改查 增: insert 介绍: mongodb存储的是文档,. 文档是json格式的对象. 语法: db.collectionName.insert(document) ...
- oracle初试、函数、增删改查、多表查询
安装oracle后的测试以及解锁账户 安装后打开命令行,输入 sqlplus 回车后会提示输入用户名,输入 sys或者system 回车后输入密码,密码为安装or ...
- SQL学习之简单增删改查
SQL最常用的语句,就是增删改查: 增删改查的对象,分别是库(文件夹),表(文件),表的内容(表的记录): 一.创建一个基本的表 #create table Student_Info (Name VA ...
- Django——6 模型基础ORM 数据库连接配置 模型的创建与映射 数据的增删改查
Django Django的ORM简介 数据库连接配置 模型的创建与映射 数据库的增删改查 增数据 查数据及补充 改数据 删数据 Django的ORM系统分析 ORM概念:对象关系映射(Objec ...
随机推荐
- Java程序员的Golang入门指南(下)
Java程序员的Golang入门指南(下) 4.高级特性 上面介绍的只是Golang的基本语法和特性,尽管像控制语句的条件不用圆括号.函数多返回值.switch-case默认break.函数闭包.集合 ...
- springMVC源码分析--动态样式ThemeResolver(一)
Spring MVC中通过ThemeSource接口来提供对动态更换样式的支持,并提供了ResourceBundleThemeSource这个具体实现类来提供通过properties配置文件对them ...
- SSH架构实现在线支付功能
在线支付是指卖方与卖方通过因特网上的电子商务网站进行交易时,银行为其提供网上资金结算服务的一种业务,她为企业和个人提供了一个安全.快捷.方便的电子商务应用环境和网上资金结算工具,在线支付不仅帮助企业实 ...
- 转义字符\(在hive+shell以及java中注意事项):正则表达式的转义字符为双斜线,split函数解析也是正则
转义字符 将后边字符转义,使特殊功能字符作为普通字符处理,或者普通字符转化为特殊功能字符. 各个语言中都用应用,如java.python.sql.hive.shell等等. 如sql中 "\ ...
- 一个ExtJS实例
聊聊ExtJS 这几天接触了一个项目 前台用的是extjs 发现这个东西还是有点意思的 就把前台的部分 剥离了下来 有兴趣的朋友可以当做模板学习 不多说先上效果图 这篇文章 可以看作是ext知识的一 ...
- Blue Path(基于cocos2dx 3.0)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=498 iTunes下载:http ...
- MySQl数据库必会sql语句加强版
这篇承接上一篇<mysql必会sql语句>:http://blog.csdn.net/qq_32059827/article/details/51763950 这一篇属于加强版,问题和sq ...
- 软考下午题详解---uml图
在上篇博客中,小编主要简单的对软考下午题当中的数据流图设计进行了一系列总结,今天我们继续来看软考下午题当中大题部分,uml图的相关知识,在我们学习的过程中,我们也已经接触过,西安交大刘惠老师讲解过um ...
- Android面试题总结
1.Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念 DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟 ...
- JSP标签JSTL(5)--常用的标签函数
在使用JSTL的标签函数的时候请务必加上如下代码 <!-- 添加jsp标签的核心库 --> <%@ taglib uri="http://java.sun.com/jsp/ ...