《Java从入门到放弃》框架入门篇:hibernate中的多表对应关系(二)

前一篇讲完了一对多的关系,通过与JDBC对比应该能发现,是不是比JDBC简单了很多?

我们只需要把对象只间的包含或对应关系理清楚,完全不用我们自己来写SQL语句。所以使用hibernate框架后,我们的关注重点是业务逻辑,所有的SQL语句都不用再操心了。

上次忘记说明,如果使用增、删、改的操作,我们还需要再引入一个Transaction对象。代码如下所示:

    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        Transaction tx = session.beginTransaction();
        try {
            Author author = new Author("刘皇叔", "sb250");
            session.save(author);
            tx.commit();    //提交
            System.out.println("保存成功");
        } catch (Exception e) {
            tx.rollback();  //回滚
        }
        HibernateSessionFactory.closeSession();
    }

知道数据库中事务的客官应该对这个对象不陌生吧。所以执行了session对象的增、删、改后,一定要记得使用transaction对象进行提交。如果某个业务有多次数据的操作,那么一定记得使用事务。

接下来,我们继续上次未完成的任务。

二、多一对映射关系

上次我们已经生成了作者和博客表的关系,从作者的角度来看,作者对应博客是一对多,而从博客的角度来看,博客对应作者是多对一。所以博客实体类中的代码如下:

public class Blog  implements java.io.Serializable {

     private Integer id;
     private Author author;    //相当于数据库中的外键引用
     private String title;
     private String content;
     private Date createTime;
     private String type;
     //封装的get和set方法略
}

blog的映射文件中代码如下:

    <class name="com.pxy.entity.Blog" table="blog" catalog="blogdb">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="native" />
        </id>
        <many-to-one name="author" class="com.pxy.entity.Author" fetch="select">
            <column name="author_id" />
        </many-to-one>
        <property name="title" type="java.lang.String">
            <column name="title" length="30" not-null="true" />
        </property>
        <property name="content" type="java.lang.String">
            <column name="content" length="500" />
        </property>
        <property name="createTime" type="java.util.Date">
            <column name="create_time" length="10" />
        </property>
        <property name="type" type="java.lang.String">
            <column name="type" length="20" />
        </property>
    </class>

里面的many-to-one就是多对一的关系。我们同样先不做任何修改,来查询一篇博客看看效果。

    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        Blog blog = (Blog)session.get(Blog.class, 6);
        System.out.println("标题:"+blog.getTitle());
        System.out.println("内容:"+blog.getContent());
        System.out.println("作者:"+blog.getAuthor().getUsername());

        HibernateSessionFactory.closeSession();
    }

结果如下:

接下来,我们来聊五毛钱的与映射关系有关的几个属性:not-null、fetch、lazy、cascade、inverse。

1)not-null

    从名字就能看出来,这个表示非空,不用多说吧。

2)fetch

    表示获取数据的方式,对应的值有两个:select和join。默认是select。它们的差别我们可以通过生成的SQL语句来看看。

select的结果如上图,默认只查询blog的内容,需要使用映射的author时,再次到数据库中查询。

    我们将Blog的映射文件中many-to-one中的fetch的值设置为join,结果如下图:

区别是不是很明显!!!

使用join后,默认就使用多表联合的方式查询了所有的数据。

3)lazy

    接下来,我们先把fetch的值还原为select。然后再把lazy的分别设置为proxy和false看效果对比。

左图为设置lazy的值为false(实时加载,实体类中包含的所有对象都一次性查询出来),

右图为设置lazy的值为proxy(延时加载,默认只查询blog的数据,当需要使用其中包含的对象时再去数据库查询)。

4)cascade

    表示执行增、删、改时的级联操作。其值有:none、save-update、delete、delete-orphan、all、all-delete-orphan。

cascade属性

描  述

none

当Session操纵当前对象时,忽略其关联对象。它是cascade属性的默认值

save-update

当通过Session的save()、update()及saveOrUpdate()方法来保存或更新当前对象时,级联保存关联的临时对象,并且级联更新所有关联的游离对象

delete

当通过Session的delete()方法删除当前对象时,会级联删除关联的对象

all

包含save-update、delete的行为

delete-orphan

删除和当前对象解除关联关系的所有对象。  即当一个节点在对象图中成为孤儿节点时,删除该节点

all-delete-orphan

包含all和delete-orphan的行为

接下来,我们演示一下默认值和save-update,其它的值,各位客官可以自行试验哈。

4.1)不设置cascade属性

    编码如下代码:

    public static void main(String[] args) {
        Session session = HibernateSessionFactory.getSession();
        Transaction tx = session.beginTransaction();
        //创建作者和博客对象
        Author author = new Author("刘皇叔", "sb250");
        Blog blog = new Blog("论持久战");
        //相互关联
        author.getBlogs().add(blog);
        blog.setAuthor(author);
        //保存作者或者保存博客
        session.save(author);
        //session.save(blog);
        //提交数据
        tx.commit();
        HibernateSessionFactory.closeSession();

    }

运行后查看结果,可以发现,只添加了作者或者博客(注意看代码,只添加作者或者只添加博客)。

4.2)把blog的映射文件和author的映射文件中的cascade属性设置为save-update

Test中的代码不做任何修改,再次运行看效果。

现在的添加操作就进行了级联,虽然我们只保存作者,或者只保存博客,但Session发现它内部还包含新的对象时就会级联更新。

5)inverse

    表示是否由关联对象来主控级联关系。一般设置在一对多中的”一方“。看4.2图中的set标签中包含有inverse属性。

    接下来,我们把inverse设置为false。

是不是发现多了一个update?

其实很好理解,因为把inverse设置为false后,表示没有主控方了,A执行了控制B的代码后,B也会再次执行控制A的代码,所以blog对象会发现:“哟,我还关联有author对象,那我必须要更新一下它的ID”。

今天的内容虽然简单,但大伙一定要把每个属性及每个属性的值都多练习几遍,不然很容易弄混效果。

想当初第一次讲这个的时候,自己都是晕晕的,快被学生问疯了···

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xcywt

《Linux命令行与shell脚本编程大全》第十一章 构建基本脚本

11.1使用多个命令 $date;who   //  命令列表,加入分号就可以,这样会依次执行。参见5.2.1节 注意区分$(date;who),这个是进程列表...

1817
来自专栏猛牛哥的博客

快手(AAU)更新记录v2.9.1.23

1687
来自专栏C/C++基础

Linux命令(31)——find命令

find命令用于在指定目录查找文件,可以指定一些匹配条件,如按文件名、文件类型、用户甚至是时间戳来查找文件。

814
来自专栏吴柯的运维笔记

Linux下常用的shell脚本整理

<转>分享下看到比较好的关于常用的shell脚本,供大家学习: 1、脚本之间互相调用与传递参数   "1.sh"的脚本,接受参数。如下,如果有一个...

3674
来自专栏个人随笔

MySQL 关于索引那点事

索引 其实数据库中的数据是按页存放的 其实索引也是按页存放的 所以本质上索引也占硬盘空间(以最小的消耗,换取最大的利益) 索引是一种有效组合数据的方式!为快速...

2609
来自专栏后端技术探索

vim神奇高效功能--批量生成Sql实例

可以通过写代码,读取文件进行入库,无论用什么语言,这代码逻辑都很容易实现。唯一的问题是代码需要上线后执行,每次上线可是一个大工程,恐怕会被pm同学嘲笑说:“你这...

873
来自专栏xcywt

《Linux命令行与shell脚本编程大全》第十四章 处理用户输入

有时还会需要脚本能够与使用者交互。bash shell提供了一些不同的方法来从用户处获得数据, 包括命令行参数,命令行选项,以及直接从键盘读取输入的能力。 14...

1965
来自专栏Java技术

为什么你创建的数据库索引没有生效?

几乎所有的小伙伴都可以随口说几句关于创建索引的优缺点,也知道什么时候创建索引能够提高我们的查询性能,什么时候索引会更新,但是你有没有注意到,即使你设置了索引,有...

421
来自专栏雪胖纸的玩蛇日常

python3+django2 开发易语言网络验证(中)

1937
来自专栏Golang语言社区

Linux内核通知链机制的原理及实现

一、概念: 大多数内核子系统都是相互独立的,因此某个子系统可能对其它子系统产生的事件感兴趣。为了满足这个需求,也即是让某个子系统在发生某个事件时通知其它...

3448

扫码关注云+社区