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。

时间: 2024-12-19 14:54:55

hibernate关联对象的增删改查------增的相关文章

Sqlserver 实际开发中常见的数据库操作增删改查----增

注意我说的常见查询,可不是简单到一个表得增删改查,做过实际开发得人都知道,在实际开发中,真正牵扯到一个表得增删改查只能说占很小得一部分,大多都是好几个表的关联操作的. 下面我就说一下我在实际开发中经常用到得一些增删改查方式.(首先我还要说一下,就是我虽然能写,但是我不知道这种查询方式叫什么类型查询,毕竟数据库这块以前都没干过,做.net开发也就一年左右,大家看我写的博客也会知道,以前搞前端U3D游戏开发的,不接触数据库,取数据调后台接口就行了,其他不用管.所以没做.net前,我也就是会大学时候学

增删改查——————增

<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width

php 增删改查---增

<meta charset="utf-8"><?php //连接数据库$db = new MySQLi('localhost','root','','php');!mysqli_connect_error() or die('连接失败');$db->query('set names utf8'); //判断 if(!empty($_GET['id'])){ $sql="delete from student where sno=".$_GET

yii中数据的"增删改查"相关工作!(此文比较乱,需细看)

使用findByPk()根据数据表主键查询的是对象,不需要使用foreach()循环出来 但是使用findall()和find()查询的是对象类型的数组需要使用foreach()循环出来 ======================================= public function getMinLimit () { $sql = "..."; $result = yii::app()->db->createCommand($sql); $query = $r

Django ORM 数据库增删改查

Django ORM 数据库增删改查 增 # 创建.增加数据(推荐) models.UserInfo.objects.create(username='root',password='123') # 创建.增加数据 dic = {'username':'eric','password':'666'} models.UserInfo.objects.create(**dic) # 创建.增加数据 obj = models.UserInfo(username='xsk',password='123'

django,form表单,数据库增删改查

Django 02 复习:  Django下载:   在命令行输入:    pip3 install django==1.11.11    在这里不要用最新的3.7,推荐使用3.6/3.5/3.4    判断下载成功:     django-admin    创建django项目:     django-admin startproject 项目名     会创建跟项目同名的文件夹     settings.py 暴露给用户可配置的配置文件     urls.py     路由与视图函数对应文件

Django静态文件配置、request方法、ORM简介、字段的增删改查

app的创建注意事项: 在Django新创建的app要在seetings.py中添加注册,才会生效 创建app:django-adminapp an startapp app名称 或者 python3 mansge.py startpp名称 手动创建的app不会自带存放html的templates文件夹,需要手动创建 Django静态文件配置 对于前端已经写好了的文件,我们只是拿过来使用,那么这些文件都可以称之为"静态文件"; 静态文件可以是:boostrap一类的前端框架,已经写好了

mysql数据库增删改查

mysql数据库增删改查增:create database DBname charset gbk; 删:drop database DBname; 改:alter database DBname charset gbk; 改名:如下查:show databases;(show databases like '%name';)查:查看数据库定义:show create database 库名; (改名)百度了下大概就这三种方法: 1. RENAME DATABASE db_name TO new_

EF总结--模型创建和数据的增删改查

EF的创建方式有三种: DataBaseFirst 新建项-ADO.NET实体数据模型-从数据库生成 ModelFirst 新建项-ADO.NET实体数据模型-空模型,在设计器中设计实体和它们之间的关系,之后右击选择从模型生成数据库. CodeFirst 通过写代码的方式,创建实体,上下文,数据库也是通过写代码生成. LinQ To EF进行增删改查 增: //实例化上下文 departmentEntities dbcontext = new departmentEntities(); //添加