hibernate知识回顾

嗯,又要开始......了

一、前言

1.1 EE 的三层架构
1.2 什么是ORM

ORM:Object Relational Mapping(对象关系映射)。指的是将一个Java中的对象与关系型数据库中的表建立一种映射关系,从而操作对象就可以操作数据库中的表。



二、入门

2.1 版本及目录

Hibernate3.X很多企业使用
Hibernate4.X不需要掌握,过渡版本(结构改变很多)
Hibernate5.X最新版本,配置同3


documentation       :Hibernate开发的文档
lib                 :Hibernate开发包
  >required         :Hibernate开发的必须的依赖包
  >optional         :Hibernate开发的可选的jar包
project             :Hibernate提供的项目
2.2 基本配置
  • 映射需要通过XML的配置文件来完成,这个配置文件可以任意命名。尽量统一命名规范(类名.hbm.xml)


  • Hibernate的核心配置文件的名称:hibernate.cfg.xml


2.3 映射配置
【class标签的配置】
标签用来建立类与表的映射关系
属性:
name        :类的全路径
table       :表名(类名与表名一致,table可以省略)
catalog     :数据库名
【id标签的配置】
标签用来建立类中的属性与表中的主键的对应关系
属性:
name        :类中的属性名
column      :表中的字段名(类中的属性名和表中的字段名如果一致,column可以省略)
length      :长度
type            :类型
【property标签的配置】
标签用来建立类中的普通属性与表的字段的对应关系
属性:
name        :类中的属性名
column      :表中的字段名
length      :长度
type            :类型
not-null        :设置非空
unique      :设置唯一

2.4 核心配置
  • 配置方式

    • hibernate.properties
    • hibernate.cfg.xml
  • 配置

必须的配置
  连接数据库的基本的参数
    驱动类
    url路径
    用户名
    密码
    方言
可选的配置
  显示SQL     :hibernate.show_sql
  格式化SQL    :hibernate.format_sql
  自动建表  :hibernate.hbm2ddl.auto
    none        :不使用hibernate的自动建表
    create      :如果数据库中已经有表,删除原有表,重新创建,如果没有表,新建表。(测试)
    create-drop :如果数据库中已经有表,删除原有表,执行操作,删除这个表。如果没有表,新建一个,使用完了删除该表。(测试)
    update      :如果数据库中有表,使用原有表,如果没有表,创建新表(更新表结构)
    validate        :如果没有表,不会创建表。只会使用数据库中原有的表。(校验映射和表结构)。
映射文件的引入
<mapping resource="com/tcy/java/Customer.hbm.xml"/>
2.5 Hibernate的配置对象

SessionFactory线程安全

Session非线程安全、不能定义为全局,只可局部

  • Session API

Session代表的是Hibernate与数据库的链接对象。不是线程安全的。与数据库交互桥梁。
1. 保存方法:
Serializable save(Object obj);
2. 查询方法:
T get(Class c,Serializable id);
T load(Class c,Serializable id);

get方法和load方法的区别?
  1. 修改方法:
    void update(Object obj);
  2. 删除方法:
    void delete(Object obj);
  3. 保存或更新:
    void saveOrUpdate(Object obj)
  4. 查询方法:
2.6 事物对象

Hibernate中管理事务的对象。
commit();
rollback();


三、主键缓存及事物

3.1 Hibernate的持久化类的编写规则
  • 无参数构造
  • 属性私有
  • 属性尽量使用包装类
  • 提供一个唯一OID与主键对应
  • 不要使用final修饰(会导致load失效)
3.2 Hibernate的主键生成策略

(1)主键分类

  • 自然主键
    指业务相关,由用户指定,且能唯一标识数据库中的任意一条记录

  • 代理主键
    指与业务无关且能唯一标识数据库中记录,一般是数据库自动生成的,比如mysql可以使用auto_increment,Sql2000可以使用identity生成方式,oracle可以使用sequence生成方式
    (2)主键生成策略

    1、increment:hibernate中提供的自动增长机制,适用于short、int、long类型的主键。在单线程程序中使用。
                  首先先发送一条语句:select max(id) from 表,然后id+1作为下一条记录的主键
    2、identity:适用于short、int、long类型的主键,使用的是数据库底层的自动增长机制,适用于有自动增长的数据库(MySQL、MSSQL)但是Oracle无
    3、sequence:适用于short、int、long类型的主键,采用的是序列的方式(Oracle支持),MySQL不支持
    4、uuid:适用于字符串类型主键。使用hibernate中的随机方式生成字符串主键。
    5、native:本地策略,可以在identity和sequence之间进行自动切换。
    6、assigned:hibernate放弃外键的管理,需要通过手动编写程序或者用户自己设置
    7、foreign:外部的。一对一的一种关联映射的情况下使用。(了解)
    
3.3 持久化类的三种状态
  • 瞬时态:没有唯一标识OID,没有被session管理
  • 持久态:有唯一标识OID,已经被session管理
  • 脱管态:有唯一标识OID,没有被session管理
  • 状态转换:(了解)
3.4 一级缓存
  • Hibernate优化手段,称为是session级别缓存。
  • 快照区





3.5 事务管理

事务:事务指的是逻辑上的一组操作,组成这组操作的各个逻辑单元要么全都成功,要么全都失败

  1. 事务的特性
  • 原子性:代表事务不可分隔
  • 一致性:代表事务执行的前后,数据的完整性保持一致
  • 隔离性:代表一个事务执行的过程中,不应该受到其它事务的干扰
  • 持久性:代表事务执行完成后,数据就持久化到数据库
  1. 如果不考虑隔离性,引发安全性问题
  • 读问题
    • 脏读:一个事务读到另一个事务未提交的数据。
    • 不可重复读:一个事务读到另一个事务已经提交的update数据,导致在前一个事务多次查询结果不一致
    • 虚读:一个事务读到另一个事务已经提交的insert数据,导致在前一个事务多次查询结果不一致
  • 写问题(了解)
    • 引发两类丢失更新
  1. 读问题的解决
  • 设置事务的隔离级别
    • Read uncommitted:以上读问题都会发生1
    • Read committed:解决脏读,但是不可重复读和虚读有可能发生(Oracle使用)2
    • Repeatable read:解决脏读和不可重复度,但是虚读有可能发送(MySQL使用)4
    • Serializable:解决所有读问题8
  1. hibernate中设置事务的隔离级别


  2. Service层事务
  • Hibernate解决Service的事务管理
* 必须保证链接对象是同一个
  1. 向下传递 DBUtils
  2. 使用ThreadLocal对象
      将这个连接绑定到当前线程中
      在DAO的方法中,通过当前的线程获得到连接对象
* Hibernate框架内部已经绑定好了ThreadLocal
  1. 早SessionFactory中提供了一个方法getCurrentSession();
  2. 通过一个配置完成。
  3. <property name="hibernate.current_session_context_class">thread</property>
      thread:Session 对象的生命周期与本地线程绑定
      jta:Session 对象的生命周期与JTA事务绑定(跨数据库)
      managed:Hibernate 委托程序来管理 Session 对象的生命周期
  4. 无需session.close(); 线程结束会自动关闭session

3.6 Hibernate的其他的API
  1. Query
  • Query 接口用于接收HQL,查询多个对象
    • HQL:hibernate查询语言,这种语言与SQL的语法及其类似,面向对象的查询语言。


  1. Criteria
  • Criteria:QBC(Query By Criteria)
    • 更加面向对象的一种查询方式


  1. SQLQuery
  • SQLQuery用于接收SQL。特别复杂情况下使用SQL

四、关系映射

1 一对多关系(双向数据绑定)
  • 多的一方映射
<!-- 配置多对一的关系:放置的是一的一方的对象 -->
        <!-- 
            many-to-one标签
                * name      :一的一方的对象的属性名称。
                * class     :一的一方的类的全路径。
                * column    :在多的一方的表的外键的名称。
         -->
        <many-to-one name="customer" cascade="save-update,delete" 
                     class="com.itheima.hibernate.domain.Customer" column="lkm_cust_id" />
  • 一的一方映射
<!-- 配置一对多的映射:放置的多的一方的集合 -->
        <!-- 
            set标签 :
                * name  :多的一方的对象集合的属性名称。
                * cascade:级联
                * inverse:放弃外键维护权。
        -->
        <set name="linkMans" cascade="save-update,delete" inverse="true">
            <!--
                 key标签
                    * column:多的一方的外键的名称。
             -->
            <key column="lkm_cust_id" />
            <!-- 
                one-to-many标签
                    * class :多的一方的类的全路径
             -->
            <one-to-many class="com.itheima.hibernate.domain.LinkMan" />
        </set>
  • 一对多的级联操作
    操作一个对象的时候,是否会同时操作其关联的对象
    添加,删除 cascade="save-update,delete"
  • 一对多设置了双向关联产生多余的SQL语句
    单向维护
    使一方放弃外键维护权
    一的一方放弃。在set上配置inverse=”true”
2 多对多关系
  • 映射配置
<!-- 
            set标签
                * name      :对方的集合的属性名称。
                * table     :多对多的关系需要使用中间表,放的是中间表的名称。
         -->
        <set name="roles" table="sys_user_role" cascade="save-update,delete">
            <!-- 
                key标签:
                    * column    :当前的对象对应中间表的外键的名称。
             -->
            <key column="user_id"/>
            <!-- 
                many-to-many标签:
                    * class     :对方的类的全路径
                    * column    :对方的对象在中间表中的外键的名称。
             -->
            <many-to-many class="com.itheima.hibernate.domain.Role" column="role_id"/>
        </set>
<!-- 
            set标签
                * name      :对方的集合的属性名称。
                * table     :多对多的关系需要使用中间表,放的是中间表的名称。
         -->
        <set name="users" table="sys_user_role" inverse="true" cascade="save-update,delete">
            <!-- 
                key标签:
                    * column    :当前的对象对应中间表的外键的名称。
             -->
            <key column="role_id"/>
            <!-- 
                many-to-many标签:
                    * class     :对方的类的全路径
                    * column    :对方的对象在中间表中的外键的名称。
             -->
            <many-to-many class="com.itheima.hibernate.domain.User" column="user_id"/>
        </set>

注意:
// 保存操作:多对多建立了双向的关系必须有一方放弃外键维护。
// 一般是被动方放弃外键维护权。


五、查询方式及抓取策略(结)

1 OID查询

OID检索:Hibernate根据对象的OID(主键)进行检索

Customer customer = session.get(Customer.class,1l);
Customer customer = session.load(Customer.class,1l);
2 对象导航检索

对象导航检索:Hibernate根据一个已经查询到的对象,获得其关联的对象的一种查询方式。

LinkMan linkMan = session.get(LinkMan.class,1l);
Customer customer  = linkMan.getCustomer();

Customer customer = session.get(Customer.class,2l);
Set<LinkMan> linkMans = customer.getLinkMans();

3 HQL检索(取对象名与属性,跟表无关)

HQL查询:Hibernate Query Language,Hibernate的查询语言,是一种面向对象的方式的查询语言,语法类似SQL。通过session.createQuery(),用于接收一个HQL进行查询方式。

  • 3.1 HQL的简单查询


  • 3.2 HQL的别名查询


  • 3.3 HQL的排序查询


  • 3.4 HQL的条件查询


  • 3.5 HQL的投影查询(需添加构造方法)


  • 3.6 HQL的分页查询


  • 3.7 HQL的分组统计查询


  • 3.8 HQL的多表查询
    SQL的多表查询

1.连接查询
  交叉连接:笛卡尔积
    select * from A,B;
  内连接   :inner join (inner 可以省略)
    隐式内连接:
      select * from A,B where A.id = B.aid;
    显示内连接:
      select * from A inner join B on A.id = B.aid;
  外连接   :
    左外连接:left outer join(outer 可以省略)
      select * from A left outer join B on A.id= B.aid;
    右外连接:right outer join(outer 可以省略)
      select * from A right outer join B on A.id = B.aid;
2.子查询

HQL的多表查询

连接查询
  交叉连接
  内连接
    显示内连接
    隐式内连接
    迫切内连接
  外连接
    左外连接
    右外连接
    迫切左外连接
4 QBC检索

QBC查询:Query By Criteria,条件查询。是一种更加面向对象化的查询的方式。

  • 4.1 简单查询


  • 4.2 排序查询


  • 4.3 分页查询


  • 4.4 条件查询


  • 4.5 统计查询


  • 4.6 离线条件查询(SSH) -- DetachedCriteria


5 SQL检索

SQL查询:通过使用sql语句进行查询


6 延迟加载

延迟加载:lazy(懒加载)。执行到该行代码的时候,不会发送语句去进行查询,在真正使用这个对象的属性的时候才会发送SQL语句进行查询。

  • 6.1 延迟加载的分类
类级别的延迟加载
  指的是通过load方法查询某个对象的时候,是否采用延迟。session.load(Customer.class,1l);
  类级别延迟加载通过<class>上的lazy进行配置,如果让lazy失效
    将lazy设置为false
    将持久化类使用final修饰
    Hibernate. Initialize()
关联级别的延迟加载
  指的是在查询到某个对象的时候,查询其关联的对象的时候,是否采用延迟加载。
  Customer customer = session.get(Customer.class,1l);
  customer.getLinkMans();----通过客户获得联系人的时候,联系人对象是否采用了延迟加载,称为是关联级别的延迟。
  抓取策略往往会和关联级别的延迟加载一起使用,优化语句。

7 抓取策略

通过一个对象抓取到关联对象需要发送SQL语句,SQL语句如何发送,发送成什么样格式通过策略进行配置。
通过<set>或者<many-to-one>上通过fetch属性进行设置
fetch和这些标签上的lazy如何设置优化发送的SQL语句

  • 7.1 <set>上的fetch和lazy
  fetch:抓取策略,控制SQL语句格式
    select      :默认值,发送普通的select语句,查询关联对象
    join            :发送一条迫切左外连接查询关联对象
    subselect       :发送一条子查询查询其关联对象
  lazy:延迟加载,控制查询关联对象的时候是否采用延迟
    true            :默认值,查询关联对象的时候,采用延迟加载
    false           :查询关联对象的时候,不采用延迟加载
    extra       :及其懒惰。
  在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。

  • 7.2 <many-to-one>上的fetch和lazy
  fetch :抓取策略,控制SQL语句格式。
    select  :默认值,发送普通的select语句,查询关联对象。
    join        :发送一条迫切左外连接。
  lazy  :延迟加载,控制查询关联对象的时候是否采用延迟。
    proxy   :默认值,proxy具体的取值,取决于另一端的<class>上的lazy的值。
    false       :查询关联对象,不采用延迟。
    no-proxy    :(不会使用)
  在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。

8 批量抓取

一批关联对象一起抓取,batch-size


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354