《Hibernate学习笔记十一》:树状结构设计

《Hibernate学习笔记十一》:树状结构设计

这是马士兵老师讲解Hibernate的一个作业题,树状结构设计,这是一个比较典型的例子,因此有必要写篇博文记录下。

树状结构的设计,它是在同一个类中使用了多对一(ManyToOne)和一对多(OneToMany).

在完成这个题目我们应该按照如下的步骤进行:

1、先思考数据库的模型应该是什么样的??

数据库中的模型应该如下:即存在id p_id

2、思考面向对象的模型,及如何来进行映射???

根据数据库中表的特点,对象应该有id name;由于此类的对象与对象之间是多对一(即多个孩子对应一个父节点)和一对多(即一个父节点可以有多个孩子)的关系,因此就存在一个自己的引用(parent)以及孩子的Set集合(children);

3、思考如何进行增删改查???

实体类

注意里面的@OneToMany和@ManyToOne

@Entity
public class Org {
    private int id;
    private String name;
    private Set<Org> children=new HashSet<Org>();//孩子集,即站在父节点的角度,这是一个一对多的关联关系
    private Org parent;//站在孩子的角度,这是一个多对一的关系
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER)  //一对多的关联关系
    public Set<Org> getChildren() {
        return children;
    }
    public void setChildren(Set<Org> children) {
        this.children = children;
    }
    @ManyToOne
    @JoinColumn(name="parent_id")  //即在数据库的表Org的外键名为parent_id
    public Org getParent() {
        return parent;
    }
    public void setParent(Org parent) {
        this.parent = parent;
    }

}

这样就完成了数状结构的设计,这个实体类中用到了OneToMany和ManyToOne.

考虑数据库的增删改查(CURD)操作

先看Save

@Test
    public void testSave(){
        Org o=new Org();
        o.setName("总公司");

        Org o1=new Org();
        o1.setName("分公司1");

        Org o2=new Org();
        o2.setName("分公司2");

        Org o11=new Org();
        o11.setName("公司1下面的部门1");

        Org o12=new Org();
        o12.setName("公司1下面的部门2");

        Org o21=new Org();
        o21.setName("公司2下面的部门1");
        Org o22=new Org();
        o22.setName("公司2下面的部门2");
        //建立双向关系
        o.getChildren().add(o1);
        o.getChildren().add(o2);

        o1.getChildren().add(o11);
        o1.getChildren().add(o12);
        o2.getChildren().add(o22);
        o2.getChildren().add(o21);

        o1.setParent(o);
        o2.setParent(o);
        o11.setParent(o1);
        o12.setParent(o1);
        o21.setParent(o2);
        o22.setParent(o2);
        Session s=sessionFactory.getCurrentSession();
        s.beginTransaction();
        s.save(o);
        s.getTransaction().commit();

    }

测试结果如下:

再看Load,并打印输出这棵树

@Test
    public void testLoad(){
        testSave();
        Session s=sessionFactory.getCurrentSession();
        s.beginTransaction();
        Org org=(Org)s.get(Org.class, 1);//由于我们在@OneToMany(fetch=FetchType.EAGER),因此,就可以一下子将孩子节点全部取出来
        print(org,0);//输出
        s.getTransaction().commit();
    }
    private void print(Org org,int level) {
        String str="";
        for(int i=0;i<level;i++){
            str+="----";
        }
        System.out.println(str+org.getName());
        for(Org o:org.getChildren()){
            print(o,level+1);
        }
    }

打印输出的结果如下:

在load的过程中,我们在实体类中设置了@OneToMany(fetch=FetchType.EAGER),因此,就可以一下子将孩子节点全部取出来,如果不设置为EAGER,而是LAZY,则就是用到才会去取出来。

以上可以说是对OneToMany和ManyToOne的一个应用啦。

参考资料

1、马士兵《Hibernate学习视频》

时间: 2024-08-01 03:33:39

《Hibernate学习笔记十一》:树状结构设计的相关文章

初探swift语言的学习笔记十一(performSelector)

作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/35842441 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号fengsh998来支持我,谢谢! 在OC中使用好好的performSelector,但不知为什么在swift有意的被拿掉了.更有甚者连IMP, objc_msgSend也不能用了.虽然想不通为什么,但应该有他的道理.就不纠结了. 大家可能在OC中使用得更多的就是延时处理,及后台处

第十七篇:实例分析(4)--初探WDDM驱动学习笔记(十一)

感觉有必要把 KMDDOD_INITIALIZATION_DATA 中的这些函数指针的意思解释一下, 以便进一步的深入代码. DxgkDdiAddDevice 前面已经说过, 这个函数的主要内容是,将BASIC_DISPLAY_DRIVER实例指针存在context中, 以便后期使用, 支持多实例. DxgkDdiStartDevice 取得设备信息, 往注册表中加入内容, 从POST设备中获取FRAME BUFFER以及相关信息(DxgkCbAcquirePostDisplayOwnershi

Linux System Programming 学习笔记(十一) 时间

1. 内核提供三种不同的方式来记录时间: Wall time (or real time):actual time and date in the real world Process time:the time that a process spends executing on a processor 包括用户时间user time 和 系统时间system time Monotonic time:use the system's uptime (time since boot) for t

《Hibernate学习笔记八》:组件映射

<Hibernate学习笔记八>:组件映射 前面介绍了一对一的单向.双向外键关联,例如,学生证和学生是一个一对一的关系.这篇博文主要是介绍下组件映射,即一个是另一个的一部分,例如,学生证的信息也可以作为学生信息的一部分,即在数据库中只存在学生一个表,而不是有学生和学生证两个表,并且这两个表中有一个一对一的关联关系. 如下: 有人或许会说,那我们就将学生和学生证的信息写在一个类中,则就不需要组件映射了,确实可以这样,但是,根据类的设计原则,我们一般都会将其设计为两个类,然后将学生证的信息作为一个

Hibernate学习笔记:第一个程序的搭建

Hibernate学习笔记:第一个程序的搭建 前一段时间对Struts2这个框架有了一点点地了解,很高兴,自己开始学习Hibernate这个框架了.本篇博文将记录下第一个Hibernate程序的搭建过程.其实有时候个人觉得无论我们学习什么语言也好,还是学习什么框架也好,第一个HelloWorld程序真的相当重要,假如 我们在学习第一个HelloWorld程序都跑不出来,这完全影响着我们对新接触的东西的兴趣和动力,但是,往往第一个程序都会涉及到很多的配置,因此使得对于初学者要摸索一定的时间,对于我

hibernate学习笔记之三(一级缓存的使用和管理)

(hibernate学习笔记系列来自于 "疯狂Java" Hibernate视频学习) 一级缓存 一级缓存生命周期很短,与session生命周期一致,所以一级缓存也叫session级缓存或事务级缓存.位于缓存中的对象处于持久化状态,它与表中的相关记录对应,session能够在某些时间点,按照缓存中持久化对象的属性来同步数据库中表的记录,这一过程称为清理缓存. 一级缓存实现原理. session缓存是由它的实现类sessionImpl中定义的一些集合属性构成的,原理是保证有一个引用在关联

hibernate学习笔记之四(Hibernate中的类型)

(hibernate学习笔记系列来自于 "疯狂Java" Hibernate视频学习) Hibernate中的类型 在*.hbm.xml文件中,<property name="password" column="t_pass">,hibernate根据type转换将java转换成hibernate类型,然后再转换成SQL类型,<property name="password" type="...&q

Hibernate学习笔记(3)

两年前曾经学习过Hibernate,也通过博客将Hibernate的学习过程记录下来了,地址如下: Hibernate学习笔记(1) Hibernate学习笔记(2) 最近在复习Hibernate,在重新学习的过程中,有了一些新的体会和收获,现在将其总结成博客,供以后作为参考资料使用. 一.导入相应的jar包 目前Hibernate更新到了4.x版本,在官网下载后,找到lib文件加中的required文件夹,此外还需要额外导入log4j和数据库驱动包. 二.创建Hibernate配置文件 在sr

Hibernate学习笔记(1)Hibernate配置

一 准备工作 首先我们将创建一个简单的基于控制台的(console-based)Hibernate应用程序. 我们所做的第一件事就是创建我们的开发目录,并且把所有需要用到的Java库文件放进去.解压缩从Hibernate网站下载的Hibernate发布包,并把所有需要的库文件拷到我们项目中去. 学习建User-library-hibernate,并加入相应的jar包 (a)项目右键-buildpath-configure build path-add library (b)选择User-libr