本文可作为,北京尚学堂马士兵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关联对象的增删改查------增的更多相关文章

  1. 【基础篇】js对本地文件增删改查--增

    前置条件: 1. 本地有安装node,点击传送门 项目目录: 1. msg.json内容 { "data": [ { "id": 1, "name&q ...

  2. Sqlserver 增删改查----增

    注意我说的常见查询,可不是简单到一个表得增删改查,做过实际开发得人都知道,在实际开发中,真正牵扯到一个表得增删改查只能说占很小得一部分,大多都是好几个表的关联操作的. 下面我就说一下我在实际开发中经常 ...

  3. Ajax增删改查-----------增

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. php 数据库内容增删改查----增

    首先,建立一个主页面(crud.php) <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  5. django基础之day04,必知必会13条,双下划线查询,字段增删改查,对象的跨表查询,双下划线的跨表查询

    from django.test import TestCase # Create your tests here. import os import sys if __name__ == " ...

  6. MongoDB的ObjectId和基本操作增删改查(3)

    ObjectId 基本操作增删改查 增: insert 介绍: mongodb存储的是文档,. 文档是json格式的对象. 语法: db.collectionName.insert(document) ...

  7. oracle初试、函数、增删改查、多表查询

      安装oracle后的测试以及解锁账户                  安装后打开命令行,输入 sqlplus 回车后会提示输入用户名,输入 sys或者system 回车后输入密码,密码为安装or ...

  8. SQL学习之简单增删改查

    SQL最常用的语句,就是增删改查: 增删改查的对象,分别是库(文件夹),表(文件),表的内容(表的记录): 一.创建一个基本的表 #create table Student_Info (Name VA ...

  9. Django——6 模型基础ORM 数据库连接配置 模型的创建与映射 数据的增删改查

    Django Django的ORM简介 数据库连接配置 模型的创建与映射 数据库的增删改查 增数据 查数据及补充 改数据 删数据   Django的ORM系统分析 ORM概念:对象关系映射(Objec ...

随机推荐

  1. 剑指Offer——知识点储备-故障检测、性能调优与Java类加载机制

    剑指Offer--知识点储备-故障检测.性能调优与Java类加载机制 故障检测.性能调优 用什么工具可以查出内存泄露 (1)MerroyAnalyzer:一个功能丰富的java堆转储文件分析工具,可以 ...

  2. springMVC源码分析--HttpRequestHandlerAdapter(四)

    上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...

  3. Leetcode解题-链表(2.2.6)RotateList

    1 题目:Rotate List Given a list, rotate the list to the right by k places, where k is non-negative. Fo ...

  4. UISearchController替换UISearchDisplayController

    随着iOS 的升级,iOS 7的占有率更低了.Xcode 升级到Xcode 8之后,对iOS 应用支持的最低版本,iOS 7也被抛弃了.我在新项目中也是最低支持到iOS 8,因此工程里也是各种警告.首 ...

  5. EBS业务学习之采购管理

    一.基础数据 w供应商档案 w采购员设置 w审批层次 w单据控制 w危险类代码 w检验代码 w自动来源 w供应商项目w目录册 二.业务流程 w请购单 w询价单 w报价单 w采购定单 w接收 w检验 w ...

  6. 01_Eclipse的使用方法

     1 选择工作站 Workspace:表示工作站 2 切换工作站 选择工作站的方式:File->SwitchWorkspace 这里选择其他的工作站 清除工作站的方式: 找到MyEclips ...

  7. Android View框架总结(五)View布局流程之Layout

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52216195 View树的Layout流程 View的Layout时序图 View布局 ...

  8. FFmpeg源代码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. Mac下安装Homebrew并升级subversion

    1. 切 Tencent-GuestWiFi2. $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/ins ...

  10. Cocos2D中Action的进阶使用技巧(一)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 大家对Cocos2d中动作的使用大概都很清楚了,其实本身act ...