Hibernate(开放源代码的对象关系映射框架)详解

目录

  • Hibernate简介
  • Hibernate优缺点
  • Hibernate编程开发
  • Hibernate语言特点
  • Hibernate核心API
  • Hibernate缓存管理
  • Hibernate延迟加载
  • Hibernate性能优化

Hibernate简介

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的JaveEE架构中取代CMP,完成数据持久化的重任。

Hibernate优缺点

优点:
1,完全的面向对象编程   
2,hibernate的缓存很牛的,一级缓存,二级缓存,查询缓存 重点   
3,编程的时候就比较简单了
4,跨平台性很强   
5使用场合就是企业内部的系统

缺点
1、效率比较低
2、表中的数据如果在千万级别,则hibernate不适合
3、如果表与表之间的关系特别复杂,则hibernate也不适合

Hibernate编程开发

编程环境

Hibernate是一个以LGPL(Lesser GNU Public License)许可证形式发布的开源项目。在Hibernate官网上有下载Hibernate包的说明。Hibernate包以源代码或者二进制的形式提供。

编程工具

IntelliJ IDEA:在代码自动提示、代码分析等方面的具有很好的功能

Hibernate使用流程

步骤1.启动IDEA创建一个工程
ps:这步就不上图了;
步骤2.pim.xml里导入jar包,Hibernate和oracle(我使用的数据库是oracle)如图;
在这里插入图片描述

<dependencies>
        <!-- Hibernate的jar包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.1.Final</version>
        </dependency>

        <!-- oracle jar包 -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.1.0</version>
        </dependency>
    </dependencies>

步骤3.连接Oracle数据库,如图:
ps:不连接也可以自己创建个实体类就行了,我只是顺便把链接数据库也讲了
在这里插入图片描述
在这里插入图片描述
PS:注意端口号别填错了,填写完后点击:**【Test Connection】*测试是否成功
.
步骤4.配置hibernate.cfg.xml文件
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
        <!--连接数据库URL-->
        <property name="connection.url">jdbc:oracle:thin:@localhost:1522:orcl</property>
        <!--连接数据库驱动-->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <!--连接数据库用户名-->
        <property name="connection.username">scott</property>
        <!--连接数据库用户密码-->
        <property name="connection.password">orcl</property>
        <!--是否把Hibernate运行时的SQL语句输出到控制台,编码阶段便于测试-->
        <property name="show_sql">true</property>
        <property name="current_session_context_class">thread</property>
    </session-factory>
</hibernate-configuration>

步骤5.创建实体类,我用的是数据库自带的Emp表
在这里插入图片描述

package com.accp.entity;

import java.util.Date;
/**
 * 实体类Emp表,
 */
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private Date hiredate;
private java.lang.Float sal;
private  java.lang.Float comm;
private  Integer deptno;

    public Integer getEmpno() {
        return empno;
    }
    public void setEmpno(Integer empno) {
        this.empno = empno;
    }
    public String getEname() {
        return ename;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }
  public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public Integer getMgr() {
        return mgr;
    }
    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }
    public Date getHiredate() {
        return hiredate;
    }
    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }
    public Float getSal() {
        return sal;
    }
    public void setSal(Float sal) {
        this.sal = sal;
    }
    public Float getComm() {
        return comm;
    }
    public void setComm(Float comm) {
        this.comm = comm;
    }
    public Integer getDeptno() {
        return deptno;
    }
    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }
    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", mgr=" + mgr +
                ", hiredate=" + hiredate +
                ", sal=" + sal +
                ", comm=" + comm +
                ", deptno=" + deptno +
                '}';
    }
}

步骤6.配置实体类Emp表的映射文件xml
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class table="emp" name="com.accp.entity.Emp">
       <id name="empno" column="empno">
           <generator class="sequence">
               <param name="sequence">seq_emp_id</param>
           </generator>
       </id>
        <!--如实体类的字段和数据库相同可以不用写column-->
        <property name="ename" column="ename"/>
        <property name="job"/>
        <property name="mgr"/>
        <property name="hiredate"/>
        <property name="sal"/>
        <property name="comm"/>
        <property name="deptno"/>
    </class>
</hibernate-mapping>

class:定义一个持久化类的映射信息。常用属性如下
——name:表示持久化类的全限定名
—— table:表示持久化类对应的数据库表名
id:表示持久化类的OID和表的主键的映射,常用的属性如下
——name表示持久化类属性的名称,和属性的访问器相匹配。
——type表示持久化类属性的类型
——column表示持久化类属性对应的数据库表字段的名称,也可在子元素column中指定
property:定义持久化类中的属性和数据库表中的字段对应关系,常用属性如下
——name:表示持久化类属性的名称,和属性的访问器相匹配
——type:表示持久化类属性的类型(可以不写)
——column:表示持久化类属性对应的数据库表字段的名称,也可在子元素column中指定。

步骤7.在文件夹hibernate.cfg.xml加载映射文件Emp.hbn.xml
在这里插入图片描述

<!--加载映射文件-->
        <mapping resource="xml/Emp.hbn.xml"/>

步骤8.通过Session接口提供的各种方法操作数据库
1.save保存
2.delete删除
3.get获取
4.load也是获取
5.Merge有主键则修改无主键则添加
6.saveOrUpdate有主键就执行更新,如果没有主键就执行插入
7.update修改

get和load的区别:
两个方法都是从数据库获取数据
get():若数据库无此数据,则返回null;
load():懒加载模式,若数据库无此数据,则会报错ObjectNotfountException异常,所以,load加载数据一定要保证其数据存在。

update和saveORUpdate的区别
update()如果是对一个已经存在的托管对象进行更新那么肯定是要update()方法了,数据中有这个对象。
saveOrUpdate()这个方法是更新或者插入,有主键就执行更新,如果没有主键就执行插入。
在这里插入图片描述

public class TestAdd {
    /**
     * 增加
     * @param args
     */
    public static void main(String[] args) {
        /*构建Configuration实例*/
        Configuration configure = new Configuration().configure("hibernate.cfg.xml");
        /*获取会话工厂*/
        SessionFactory sessionFactory = configure.buildSessionFactory();
        //获取会话
        /*Session session1 = sessionFactory.openSession();不会自动关闭会话*/
        Session session = sessionFactory.getCurrentSession();//会自动关闭会话
        /*由Session实例创建Transaction的一个实例,开启事务*/
        Transaction transaction = session.beginTransaction();
        //保存员工 延迟加载
        Emp emp = new Emp();
        emp.setComm(100f);
        emp.setDeptno(10);
        emp.setEname("aaa");
        emp.setHiredate(new Date());
        emp.setJob("aa");
        emp.setMgr(7369);
        emp.setSal(11f);
        Serializable save = session.save(emp);
        System.out.println(save);
        /*提交事务*/
        transaction.commit();
        /*或回滚事务*/
        //tanTransaction.rollback();
        /*关闭session*/
       // session.close();
    }
}

openSession与getCurrentSession的区别:
getCurrentSession在事务提交或回滚之后会自动关闭,而openSession需要手动关闭。如果使用openSession没有手动关闭,多次使用之后可能会导致连接池溢出。
openSession每次创建新的Session对象,getCurrentSession使用现有的Session对象。

结束;

这里我就不一 一加载代码了可以去这里拿取其他代码:
Hibernate的demo代码

核心API

Hibernate的API一共有6个,分别为:
1,Configuration:负责配置并启动hibernate,创建SessionFactory  
2,SessionFactory:负责初始化hibernate,创建session对象
3,Session:负责被持久化对象CRUD操作
4,Transaction:负责事物相关的操作
4,Query:负责执行各种数据库查询
5,Criteria:条件查询接口

Configuration

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

Configuration configure = new Configuration().configure(“hibernate.cfg.xml”);

Configuration实例构建一个SessionFactory实例

SessionFactory sessionFactory = configure.buildSessionFactory();

SessionFactory实例创建Session实例

1 Session session1 = sessionFactory.openSession(); //不会自动关session
2 Session session = sessionFactory.getCurrentSession(); //会自动关闭session

由Session实例创建Transaction的一个实例,开启事务

Transaction transaction = session.beginTransaction();

Query查询语句
Hibernate核心API之Query查询(hql)

Hibernate缓存管理

Hibernate 中提供了两级Cache(高速缓冲存储器),第一级别的缓存是Session级别的缓存,它是属于事务范围的缓存。这一级别的缓存由hibernate管理的,一般情况下无需进行干预;第二级别的缓存是SessionFactory级别的缓存,它是属于进程范围或集群范围的缓存。这一级别的缓存可以进行配置和更改,并且可以动态加载和卸载。 Hibernate还为查询结果提供了一个查询缓存,它依赖于第二级缓存。

一级缓存

当应用程序调用Session的save()、update()、saveOrUpdate()、get()或load(),以及调用查询接口的 list()、iterate()或filter()方法时,如果在Session缓存中还不存在相应的对象,Hibernate就会把该对象加入到第一级缓存中。当清理缓存时,Hibernate会根据缓存中对象的状态变化来同步更新数据库。 Session为应用程序提供了两个管理缓存的方法: evict(Object obj):从缓存中清除参数指定的持久化对象。 clear():清空缓存中所有持久化对象。

二级缓存

Hibernate的二级缓存策略的一般过程如下:

  1. 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象
  2. 把获得的所有数据对象根据ID放入到第二级缓存中。
  3. 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。
  4. 删除、更新、增加数据的时候,同时更新缓存。 Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query Cache。

Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的Query Cache。

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

1) 很少被修改的数据
2 )不是很重要的数据,允许出现偶尔并发的数据
3) 不会被并发访问的数据
4) 参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。

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

1 经常被修改的数据
2 财务数据,绝对不允许出现并发
3 与其他应用共享的数据。

延迟加载

Hibernate对象关系映射提供延迟的与非延迟的对象初始化。非延迟加载在读取一个对象的时候会将与这个对象所有相关的其他对象一起读取出来。这有时会导致成百的(如果不是成千的话)select语句在读取对象的时候执行。这个问题有时出现在使用双向关系的时候,经常会导致整个数据库都在初始化的阶段被读出来了。当然,你可以不厌其烦地检查每一个对象与其他对象的关系,并把那些最昂贵的删除,但是到最后,我们可能会因此失去了本想在ORM工具中获得的便利。

延迟加载

<class table="emp" name="com.ssh.entity.Emp" lazy="true">

在这里插入图片描述
立即加载

改为false就行了

<class table="emp" name="com.ssh.entity.Emp" lazy="false">

性能优化

数据库设计

  1. 降低关联的复杂性
  2. 尽量不使用联合主键
  3. ID的生成机制,不同的数据库所提供的机制并不完全一样
  4. 适当的冗余数据,不过分追求高范式

HQL优化

HQL如果抛开它同HIBERNATE本身一些缓存机制的关联,HQL的优化技巧同普通的SQL优化技巧一样,可以很容易在网上找到一些经验之谈。

优化Hibernate

1、使用一对多的双向关联,尽量从多的一端维护。
2、不要使用一对一,尽量使用多对一。
3、配置对象缓存,不要使用集合缓存。
4、表字段要少,表关联不要怕多,有二级缓存撑腰。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐