Hibeinate

作者: 怎奈我本楚狂人 | 来源:发表于2017-12-23 22:24 被阅读0次

    一、Hibernate 持久化类-映射文件-表

    1.持久化类?我更愿称之容器

    由于约定优于编码的不成文规定,我们通常需要将持久化类的属性名和表中的字段名保持一致,但是这并不是一定的,我们可以在映射文件中配置持久化类的属性名和表中的字段,如果一致,那么即满足了约定优于编码的规定,又让我们能在映射文件中省去column这一属性,就好比持久化类名和表名一致,我们能省去映射文件class标签中的table属性一样。

    那么是否在配置文件中,我们一定要将持久化类的每一个属性都在映射文件中和表中的字段一一对应吗?答案是否定的,看我们的需求,我们可以把持久化类看做一个容器,hibernate底层使用jdbc发送的sql语句,数据库需要给我们一个响应,例如select查询语句,会返回查询到的数据,此时拿到这个响应数据,hibernate会根据响应的数据去参照我们的映射文件找到我们的持久化类,在映射文件中配置了多少个持久化类属性名和表中字段的映射关系,就给持久化类封装多少个属性值。

    既然持久化类是一个接受 数据库对hibernate发送sql的响应 (查询语句返回的结果,放眼CRUD只有查询语句返回的结果需要封装到POJO类中)的一个容器,那么为何不让这个容器记录的信息更广更多呢?要想记100%的数据,那么我们在设计持久化类的时候,就应该让他的属性值和数据库中他对应的表的字段一一对应,并且在映射文件中一一映射出来。如此下来,hibernate就能将响应结果100%地封装到我们的持久化类的对象中--此时的容器记录的信息就最全。

    2.主键生成策略

    映射文件中 class标签必须包含id标签,此标签用于映射表中的主键和持久化类中的唯一标识。

    id标签下有主键生成策略,------------------------建表的时候也有主键生成策略 二者必须一一对应。

    二者有何区别?           

    hibernate中有策略(native)-表中没有策略(报错):若建表的时候没有主键生成策略increase,而hibernate却设置了主键生成策略为native(根据主配置文件中的数据库方言去判断?mysql的话就是identity:Oracle的话就是sequence),此时执行多条插入操作,那么数据库无法获知主键到底该为何值(int类型的 设置increase自增策略-只适用于int,short,long,默认值为1,一次+1),那么肯定会报错的。

    表中有策略(自然主键(生成策略为increase,除了主键约束外还有一个非空约束))-hibernate中没有策略(报错):hibernate的主键生成策略是给hibernate看的,hibernate看到了主键的这个生成策略,就知道如何去操作表中的主键。                          例如:    hibernate的两个主键生成策略identity(线程安全)和increment(线程不安全)         

    identity:由底层数据库生成标识符号。identity是由数据库自己生成的,但这个主键必须设置为自增长,前提条件是低层数据库支持自动增长字段类型。                                  increment:由hibernate管理主键,自动以递增的方式生成标识符,每次增量为1。其在每次插入前取得一个当前最大的id+1作为主键,该主键必须为Integer类型。

    3.表可以没有主键,也可以没有唯一标识(但表一般都会设计出主键,即使不是自然主键,也会有一个代理主键存在)。但是hibernate映射文件中配置的表必须要有主键,且持久化类中必须有唯一标识与主键对应。hibernate映射文件必须配置id标签,也就是进去配置文件中的表必须要有主键才行。


    二、同时保存(save即insert操作)具有主外键关系两张表中的数据

    需要满足以下条件:

    一、映射文件中设置主外键

    主键设置:id标签

    普通字段设置:property

    外键设置(维护):

    分两种:1、one-to-many:靠主键方(一的一端)维护

    2、many-to-one:靠外键所在方(多的一端)维护

    这里的外键维护仅仅是表结构方面的一种维护,但是表数据就另说了,后面会讲到。

    二、持久化类中设置主外键关键关系(两边数据层面了)

    分两种:

    1、主键方对应的持久化类(一的一端):

    private Set<LinkMan>linkmans =new  HashSet<LinkMan> 记得生成get set

    2、外键所在方对应的持久化类(多的一端):

    private Customer customer同样需要get.set

    三、在编写的代码中,让他们发生关联关系(表数据层面)

    分两种:

    1、一的一端:

    Customer c = new Customer()

    LinkMan l1 = new LinkMan()

    LinkMan l2 = new LinkMan()

    LinkMan l3 = new LinkMan()

    c.getLinkMans().add(l1)

    c.getLinkMans().add(l2)

    c.getLinkMans().add(l3)

    发生数据层面的关联关系,若不发生关系,那么在save(c),save(l1),save(l2),save(l3)之后,linkman表中由one-to-many维护的表结构层面的外键的值就为null,因为他们没有发生数据层面的关联。

    2、多的一端也如此(我偷个懒写个关键)

    l1.setCustomer(c)

    l2.setCustomer(c)

    l3.setCustomer(c)

    道理之前的一样。

    四、保险起见-

    二中的操作,一端多端都写上维护外键关系

    三种的操作,一端多端都关键起来

    五、级联保存。级联也同上面一样具有方向性,固为了防止出错,参照四中的策略,在多的一端和一的一端都加上csdsa=save-update

    这样只save(c),l1l2l3自动被save(执行insert语句)。

    但是级联会发送多余的sql(不管是从多的一端维护还是从一的一端维护),就好比从多的一端维护外键只发送insert语句,而从一的一端维护外键不但发送insert语句,还会发送update语句。

    为了避免多余的update语句,我们需要在一的一端设置取消外键维护权,这样维护权只在多的一端手上,就自然不会发送update语句了。

    相关文章

      网友评论

          本文标题:Hibeinate

          本文链接:https://www.haomeiwen.com/subject/tktcgxtx.html