Hibernate 框架总结

Hibernate框架的总结

hibernate 简介:

hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们java程序员可以使用面向对象的思想来操纵数据库。

hibernate核心接口

session:负责被持久化对象CRUD操作

sessionFactory:负责初始化hibernate,创建session对象

configuration:负责配置并启动hibernate,创建SessionFactory

Transaction:负责事物相关的操作

Query和Criteria接口:负责执行各种数据库查询

Hibernate 核心接口

Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和Configuration。这5个核心接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制。

·Session接口:Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句。)。但需要注意的是Session对象是非线程安全的。

·SessionFactory接口:SessionFactroy接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。

·Configuration接口:Configuration接口负责配置并启动Hibernate,创建SessionFactory对象。在Hibernate的启动的过程中,Configuration类的实例首先定位映射文档位置、读取配置,然后创建SessionFactory对象。

·Transaction接口:Transaction接口负责事务相关的操作。它是可选的,可发人员也可以设计编写自己的底层事务处理代码。

·Query和Criteria接口:Query和Criteria接口负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式。

hibernate工作原理:

    1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件

    2.由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>读取并解析映射信息

    3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory

    4.Session session = sf.openSession();//打开Sesssion

    5.Transaction tx = session.beginTransaction();//创建并启动事务Transation

    6.persistent operate操作数据,持久化操作

    7.tx.commit();//提交事务

    8.关闭Session

    9.关闭SesstionFactory

为什么要用hibernate:

    1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。

    2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作

    3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。

    4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。

Hibernate是如何延迟加载?get与load的区别

    1. 对于Hibernate get方法,Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据 库中没有就返回null。

    2. Hibernate load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论:

        (1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。

        (2)若为false,就跟Hibernateget方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。

get和load有两个重要区别:

    如果未能发现符合条件的记录,Hibernate get方法返回null,而load方法会抛出一个ObjectNotFoundException。

    load方法可返回没有加载实体数据的代 理类实例,而get方法永远返回有实体数据的对象。

    总之对于get和load的根本区别,一句话,hibernate对于 load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方 法,hibernate一定要获取到真实的数据,否则返回null。

Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)

    类与类之间的关系主要体现在表与表之间的关系进行操作,它们都是对对象进行操作,我们程序中把所有的表与类都映射在一起,它们通过配置文件中的many-to-one、one-to-many、many-to-many、

数组映射:<array />    有序,通过下标访问

            <key />    映射集合属性数据表的外键列

            <list-index />    用于映射数组的下标列,用于保存数组的下标值

            <element />    映射保存集合元素

List 集合映射:<list />    有序,通过下标访问

            <key />    映射集合属性数据表的外键列

            <list-index />    映射集合属性数据表的集合索引列

            <element />    映射保存集合元素的数据列,需要指定 type

Set 集合映射:<set /> 无序,唯一,不可重复

            <key />    映射集合属性数据表的外键列

            <element />    映射保存集合元素的数据列,需要指定 type

Map 集合映射: <map /> key 是无序的,唯一的,value 是无序的,不唯一的

            <key />    映射集合属性数据表的外键列

            <map-key />    映射 Map 集合的 key 值,需要指定 type

            <element />    映射保存集合元素的数据列,需要指定 type

Hibernate 中的关系映射

    主键双向一对一关联: 两个表中的主键共享一个值,从表中的主键是从主表中获取得到

        在主表映射文件中配置:

            设置主键生成策略:在<id>中配置

                <generator    class="foreign">

                        <param    name="property>引用的主表中的从表自定义属性名</param>

                </generator>

            

            <one-to-one    name="主表中的从表自定义属性名"    constrained="true"    />

        在从表映射文件中配置:

            <one-to-one    name="从表中的主表自定义属性名">

    

    外键双向一对一关联: 通过外键方式引用主表中的主键,并且设置外键属性为唯一属性

        在主表映射文件中配置:

            <one-to-one    name="主表中的从表自定义属性名"    property-ref="从表中的主表自定义属性名"    cascade="all" />

        

        在从表映射文件中配置:

            <many-to-one    name="从表中主表自定义属性名"    column="外键列名"    unique="true" />

    双向一对多关联:(以 set 为例,其余集合同配置)

        在主表映射文件中配置:

            <set    name="主表中从表自定义属性名"    inverse="true">

                <key    column="外键列名" />

                <one-to-many    class="从表属性类路径">

            </set>

        在从表映射文件中配置:

            <many-to-one    name="从表中主表自定义属性名"    column="外键列名"    class="主表属性类路径"    cascade="all" />

    双向多对多关联:(以 set 为例)

        在主表映射文件中配置:

            <set    name="主表中从表自定义属性名"    table="中间表名"    cascade="all">

                <key    column="主表在中间表的外键名">

                <many-to-many    class="从表属性类路径"    column="从表在中间表的外键名" />

            </set>

        在从表映射文件中配置:

            <set    name="从表中主表自定义属性名"    table="中间表名"    inverse="true">

                <key    column="从表在中间表的外键名">

                <many-to-many    class="主表属性类路径"    column="主表在中间表的外键名" />

            </set>

Hibernate的查询方式Sql、Criteria,object comptosition

Hql:

1、 属性查询

2、 参数查询、命名参数查询

3、 关联查询

4、 分页查询

5、 统计函数

过滤器与拦截器

    使用过滤器的步骤:

        ① 定义过滤器,使用 <filter-def />定义过滤器(mapping的子元素)

        ② 使用过滤器,使用 <filter /> 应用过滤器(class的子元素)

        ③ 代码中通过 session 启用过滤器

            session.enableFilter("过滤器名").setParameter("过滤器属性名","值");

    过滤器类似于集合上的 where 属性条件

    当某个查询条件使用的非常频繁的时候,那么就可以将条件设置为过滤器。

    拦截器:① 实现 Interceptor 接口,重写所有方法

                 ② 继承 EmptyInterceptor 类(推荐使用)

    常用方法:

        onLoad: 加载持久化实体时调用

        onSave: 保存数据的时候调用,数据还没有保存到数据库

        onFlushDirty: 更新数据时调用,但数据还没有更新到数据库

        onDelete: 当删除实体时调用

        preFlush:持久化所做修改之前调用

        postFlush: 持久化所做修改之后调用

    拦截器的配置:

        ① 全局拦截器配置

                Configuration cfg = new Configuration().configure();

                cfg.setInterceptor(配置的拦截器类);

        ② 局部拦截器配置

                session = factory.withOptions().interceptor(配置的拦截器类).openSession();

如何优化Hibernate?

    1.使用双向一对多关联,不使用单向一对多

    2.灵活使用单向一对多关联

    3.不用一对一,用多对一取代

    4.配置对象缓存,不使用集合缓存

    5.一对多集合使用Bag,多对多集合使用Set

    6. 继承类使用显式多态

    7. 表字段要少,表关联不要怕多,有二级缓存撑腰

hibernate的开发步骤:开发步骤

    1)搭建好环境

        引入hibernate最小的jar包

        准备Hibernate.cfg.xml启动配置文件

    2)写实体类(pojo)

    3)为实体类写映射文件"User.hbm.xml"

        在hibernate.cfg.xml添加映射的实体

    4)创建库表

    5)写测试类

        获得Configuration

        创建SessionFactory

        打开Session

        开启事务

        使用session操作数据

        提交事务

        关闭资源

Hibernate 注解

    注:GeneratedValue指定了标识符的生成策略。jpa提供了4种标准用法。

    01.AUTO:根据不同的数据库选择不同的策略

    02.TABLE:使用表保存id值

    03.INDENITY:使用数据库自动生成主键

    04.SEQUENCE:使用序列创建主键(如Oracle)

双向外键一对一:@OneToOne

    在主表类中 从表属性上配置:

        @OneToOne(cascade=CascadeType.ALL)

        @JoinColumn(name="添加的外键名",unique=true)

    在从表类中 主表属性上配置:

        @OneToOne(mappedBy="主表中从表的自定义属性名")

    注:双向关联,必须设置 mappedBy 属性 ,因为双向关联只能交给一方去维护,不能在两边都设置外键关联,否则双方都无法保存。

双向主键一对一

    在主表类中 

        主表主键上配置:

            @Id

            @GeneratedValue(generator="策略名")

            @GenericGenerator(name="策略名",strategy="assigned")    //设置为手动输入 方便测试

        在主表中从表自定义属性上配置:

            @OneToOne(cascade=CascadeType.ALL)

            @PrimaryKeyJoinColumn

    

    在从表类中 

        从表主键上配置:

            @Id

            @GeneratedValue(generator="策略名")

            @GenericGenerator(name="策略名",strategy="foreign",parameters={@Parameter(name="property",value="从表中主表自定义属性名")})

        在从表中主表自定义属性上配置:

            @OneToOne(mappedBy="主表中从表自定义属性名")

双向一对多

    在主表中从表自定义属性上配置:

            @ManyToOne

            @JoinColumn(name="外键名",referencedColumnName="从表中关联的id")

    

    在从表中主表自定义属性上配置:

            @OneToMany(mappedBy="主表中从表自定义属性名",cascade=CascadeType.ALL)

双向多对多

    在主表中从表自定义属性上配置:

            @ManyToMany(cascade=CascadeType.ALL)

            @JoinTable (

                    name="中间表名",

                    joinColumns={@JoinColumn(name="主表在中间表的id")},

                    inverseJoinColumns={@JoinColumn(name="从表在中间表的id")}

             )

    在从表中主表自定义属性上配置:

            @ManyToMany(mappedBy="主表中从表自定义属性名")

注意:在判断到底是谁维护关联关系时,可以通过查看外键,哪个实体类定义了外键,哪个类就负责维护关联关系。

Hibernate缓存的作用:

    Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据

Hibernate缓存分类:

    Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存

       Hibernate一级缓存又称为“Session的缓存”,它是内置的,意思就是说,只要你使用hibernate就必须使用session缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每个实例都具有唯一的OID。

       Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。

什么样的数据适合存放到第二级缓存中?   

    1 很少被修改的数据   

    2 不是很重要的数据,允许出现偶尔并发的数据   

    3 不会被并发访问的数据   

    4 常量数据  

 

不适合存放到第二级缓存的数据?   

    1经常被修改的数据   

    2 .绝对不允许出现并发访问的数据,如财务数据,绝对不允许出现并发   

    3 与其他应用共享的数据。

Hibernate查找对象如何应用缓存?

    当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;如果都查不到,再查询数据库,把结果按照ID放入到缓存

    删除、更新、增加数据的时候,同时更新缓存

Hibernate管理缓存实例无论何时,我们在管理Hibernate缓存(Managing the caches)时,当你给save()、update()或saveOrUpdate()方法传递一个对象时,或使用load()、 get()、list()、iterate() 或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。

当随后flush()方法被调用时,对象的状态会和数据库取得同步。 如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。

猜你喜欢

转载自blog.csdn.net/Darryl_Tang/article/details/82633642