hibernate框架学习

本文介绍Hibernate框架的基本概念,包括ORM框架的定义及Hibernate的特点,并详细讲解了如何通过编写JavaBean类和映射文件来实现数据库操作。

hibernate入门

1、ORM框架:object relational mapping用于实现面向对象编程语言里不同数据类型系统的数据之间的转换。
Hibernate是一个数据持久化层的ORM框架.它是轻量级的JavaEE应用的持久层解决方案,是一个关系数据库ORM框架
这里写图片描述

ORM 就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作
Hibernate提供了对关系型数据库增删改成操作

hibernate的优点:

  • Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
  • Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作 session.save(User);
  • Hibernate使用java的反射机制
  • Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系

入门案例:

1、编写流程

  • 导入jar包
  • 创建数据库和表
  • 编写核心配置文件(hibernate.cfg.xml)–> 配置获得链接等参数
  • 编写映射文件 hibernate mapping(*.hbm.xml)
  • 使用api测试

一、创建表

create database h_db;
use h_db;
create table t_user(
  id int auto_increment primary key,
  username varchar(50),
  password varchar(30)
);

二、导入jar包:

  • hibernate3.jar
  • \lib\required
  • jap规范:lib\jpa
  • mysql驱动包

包的含义:
这里写图片描述

三、编写JavaBean + 映射文件

package com.zeroyoung.domain;

public class User {
    /*
     * create table t_user(
          id int auto_increment primary key,
          username varchar(50),
          password varchar(30)
        );
     */
    private Integer uid;
    private String username;
    private String password;
    public Integer getUid() {
        return uid;
    }
    public void setUid(Integer uid) {
        this.uid = uid;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User [uid=" + uid + ", username=" + username + ", password="
                + password + "]";
    }
}

在javabean的同一目录下创建一个User.hbm.xml的文件
这个xml的文件的约束在hibernate3.jar/org.hibernate/hibrenate-mapping-30.dtd

<?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">

<!-- ORM元数据,表对象关系映射文件
    package:配置改配置文件中类所在的包 -->
<hibernate-mapping >
    <!-- class: 配置实体与表的关系
        name : 填写实体的完整类名
        table: 与实体对应表的名称
        dynamic-insert:动态插入 默认值是false
                        true=>如果字段值为null,不参与insert语句
         dynamic-update:动态更新  默认值"false"
                        true=> 没改动过的属性,将不会生成到update语句中
     -->
    <class name="com.zeroyoung.domain.User" table="t_user">
        <!-- 主键的声明 -->
        <!-- id: 配置实体与表中 id对应
            name: user对象中标识主键的属性名称
            column: 主键在表中的列名
            length: 列的数据长度
            unsaved-value(不常用): 指定主键为什么值时,当做null来处理.
            access(强烈推荐不要用):field 那么在操作属性时,会直接操作对应的字段而不是get/set方法
         -->
        <id name="uid" column="id" length="255">
            <!-- 主键生成策略,由数据库控制 -->
            <!-- generator:主键生成策略
                    1.increment  数据库自己生成主键. 先从数据库中查询最大的ID值,将ID值加1作为新的主键
                    2.identity  依赖于数据的主键自增功能
                    3.sequence  序列,依赖于数据中的序列功能(Oracle).
                    4.hilo(纯了解,永远用不到) : Hibernate自己实现序列的算法,自己生成主键. (hilo算法 )
                    5.native 自动根据数据库判断,三选一. identity|sequence|hilo
                    6.uuid  生成32位的不重复随机字符串当做主键
                    7.assigned 自己指定主键值. 表的主键是自然主键时使用.

             -->
            <generator class="native"></generator>
        </id>
        <!-- property : 实体中属性与表中列的对应
             name : 实体中属性名称
             column : 表中列的名称
             length : 数据长度
             precision: 小数点后的精度
             scale: 有效位数
             insert(一般不用): 该属性是否加入insert语句.
             update(一般不用): 该属性是否加入update语句.
             not-null : 指定属性的约束是否使用 非空
             unique : 指定属性的约束是否使用 唯一
         -->
        <property name="username" column="username"/>
        <property name="password" column="password"/>
    </class>
</hibernate-mapping>   

四、编写核心配置文件
在src目录下面编写配置文件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:元素用于配置hibrenate中的属性,方式为键值对 -->

        <!-- hibernate.connection.driver_class:数据库连接驱动 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

        <!--hibernate.connection.username: 数据库连接用户名 -->
        <property name="hibernate.connection.username">root</property>

        <!-- 数据库连接密码 -->
        <property name="hibernate.connection.password">root</property>

        <!-- 数据库连接的地址,路径 -->
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/h_day01_db</property>

        <!-- 操作数据库时,会向控制台打印sql语句 -->
        <property name="show_sql">true</property>

        <!-- 格式化sql语句 -->
        <property name="format_sql">true</property>

        <!-- hbm2ddl.auto: 生成表结构的策略配置
            update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构. 
                    如果存在表结构,并且表结构与实体一致,那么不做修改
                    如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
             create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
             create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
             validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
         -->
        <property name="hbm2ddl.auto">update</property>

        <!-- 数据库方言配置 
         org.hibernate.dialect.MySQLDialect (选择最短的)
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- hibernate.connection.autocommit: 事务自动提交  -->
        <property name="hibernate.connection.autocommit">true</property>

        <!-- 将Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession -->
        <property name="hibernate.current_session_context_class">thread</property>

        <!-- 引入ORM 映射文件 
            填写src之后的路径
         -->
        <mapping resource="com/zeroyoung/domain/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

五、测试:

    @Test
    public void tet() {
        // 1.加载配置文件获取核心配置核心对象
        // 1.1 调用configure() 方法=> 加载src下名为hibernate.cfg.xml
        // 1.2 如果配置文件不符合默认加载规则.我们可以调用
        // new Configuration().configure(file); 通过file加载
        // new Configuration().configure(path); 通过路径加载
        // 1.3 可以通过Configuration对象加载 映射文件(不推荐)
        // 推荐hibernate.cfg.xml 使用 mapping 属性引入配置文件
        // 规范: 1>orm映射文件名称与实体的简单类名一致
        // 2>orm映射文件 需要与实体的类在同一包下
        Configuration config = new Configuration().configure();

        // 2.获取sessionFactory,相当于连接池
        // 根据Configuration 配置信息创建 SessionFactory

        SessionFactory factory = config.buildSessionFactory();
        // 3.获取会话session,相当于serlvet重点connection
        // 3.1 openSession => 获得一个全新的Session对象
        // 3.2 getCurrentSession => 获得与当前线程绑定的session对象
        // 调用getCurrentSession 需要加上一个配置: <property
        // name="hibernate.current_session_context_class">thread</property>
        Session session = factory.openSession();

        User u = new User();
        u.setPassword("1233");
        u.setUsername("zhon");
        // 4.操作数据库
        session.save(u);

        // 5.关闭资源
        session.close();
        factory.close();
    }

api详解

  • Configuration配置对象
    我们编写的hibernate.cfg.xml配置文件需要使用 Configuration来加载,加载的方式有几种。常见的使用方式如下:
Configuration config = new Configuration().configure();

这里configure()方法就是加载src下名为hibernate.cfg.xml
同时,它也提供了有参数的构造方法来使用,当我们的配置文件的不符合默认加载规则,我们可以调用如下的方法

  • new Configuration().configure(file); 通过file加载
  • new Configuration().configure(path); 通过路径加载

####SessionFactory工厂
SessionFactory 相当于java web连接池,用于管理所有session
获得方式:SessionFactory factory = config.buildSessionFactory();
sessionFactory hibernate缓存配置信息 (数据库配置信息、映射文件,预定义HQL语句 等)
SessionFactory线程安全,可以是成员变量,多个线程同时访问时,不会出现线程并发访问问题。
提供api:
打开一个新的会话:

Session session = factory.openSession();

这里得到的session是重新创建的session会话

得到当前线程绑定的session

Session session = getCurrentSession()

这里是使用当前线程绑定的session会话,如果当前线程没绑定session则先创建一个session对象,然后绑定之后返回。
要想使用当前线程绑定session就需要在配置文件中加上这句话:

<property name="hibernate.current_session_context_class">thread</property>

这个方法主要是跟事务的提交有关系,事务关闭时,会自动把与当前线程关联的session关闭,并删除


Session 会话

Session 相当于 JDBC的 Connection – 会话,我们是通过session来操作po(persistent object ,用于与数据库交互数据。–dao层 (JavaBean + hbm ))对象的
session是单线程的,线程不安全,不能编写成员变量
session中的几个api方法:

  • save 保存
  • update 更新
  • delete 删除
  • get 通过id查询,如果没有 null
  • load 通过id查询,如果没有抛异常
  • createQuery(“hql”) 获得Query对象
  • createCriteria(Class) 获得Criteria对象

保存对象上面的例子已近说明,更新对象那个的方法如下

        User user = (User) session.get(User.class, 1);
        user.setUsername("汤姆");
        session.update(user);

删除:

        // 先查询出你要修改的对象
        User user = (User) session.get(User.class, 1);
        // 删除
        session.delete(user);

get查询:
第一个参数时候javabean,第二个是id的值

        // 先查询出你要修改的对象
        User user = (User) session.get(User.class, 2);

load查询:

// 先查询出你要修改的对象
User user = (User) session.load(User.class, 2);

load与get的区别:
get方法被调用时立刻 发送sql语句查询、load调用时并没有查询数据库,当我们需要使用该对象的时候,才查询数据

createQuery编写查询语句
查询所有的用户

        // HQL语言 => Hibernate Query Language
        // createQuery 传入hql语句查询,完整类名字
        // 相当于select * from t_user;
        Query query = session.createQuery("from com.zeroyoung.domain.User");
        List<User> list = query.list();
        System.out.println(list);

Criteria查询所有(一般很少使用)

// Criteria 查询 => Hibernate独创的面向对象的查询=> 无语句
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();

支持原生的sql语句查询:

        // 原生的Sql查询
        SQLQuery query = session.createSQLQuery("select * from t_user");
        // addEntity 将查询结果封装到指定对象中
        query.addEntity(User.class);
        List<User> list = query.list();
事务Transaction

开启事务 beginTransaction()
获得事务 getTransaction()
提交事务:commit()
回滚事务:rollback()

try{
   //开启
   //session操作
   //提交
} catch(e){
   //回滚
}

query对象

通过createQuery()方法,我们会得到一个query对象,它能帮助我们完成一些列的事情。
api:

  • list() 查询所有
  • uniqueResult()获取一个结果,如果没有查到返回null,如果查询到多条抛出异常
  • setFirstResult(int)分页,开始索引的数startIndex
  • setMaxResults(int) 分页,每页显示个数 pageSize
        Query query = session.createQuery("from com.zeroyoung.domain.User");

        // 分页 limit index,count;
        // 指定结果从第几个开始拿
        query.setFirstResult(0);
        // 指定拿几个
        query.setMaxResults(2);

        // query.list() 将hql语句执行,并返回结果(多行)
        List<User> list = query.list();
        System.out.println(list);

        //uniqueResult 将hql语句执行,并返回结果(一行),用于在createquery中添加条件
        //User u = (User) query.uniqueResult();
        //System.out.println(u);
Criteria对象

QBC(query by criteria),hibernate提供纯面向对象查询语言,提供直接使用PO对象进行操作。
获得方式:Criteria criteria = session.createCriteria(User.class);

        criteria.add(Restrictions.eq("username", "tom"));
//      Restrictions.gt(propertyName, value)        大于
//      Restrictions.ge(propertyName, value)    大于等于
//      Restrictions.lt(propertyName, value)    小于
//      Restrictions.le(propertyName, value)    小于等于
//  Restrictions.like(propertyName, value)  模糊查询,注意:模糊查询值需要使用 % _

创建一个工具类

public class H3Utils {

    // 会话工厂,整个程序只有一份。
    private static SessionFactory factory;

    static{
        //1 加载配置
        Configuration config = new Configuration().configure();

        //2 获得工厂
        factory = config.buildSessionFactory();
//3 关闭虚拟机时,释放SessionFactory
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {

            @Override
            public void run() {
                System.out.println("虚拟机关闭!释放资源");
                sf.close();
            }
        }));
    }


    /**
     * 获得一个新的session
     * @return
     */
    public static Session openSession(){
        return factory.openSession();
    }

    /**
     * 获得当前线程中绑定session
     * * 注意:必须配置
     * @return
     */
    public static Session getCurrentSession(){
        return factory.getCurrentSession();
    }
}

配置文件详解

<?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 元素用于配置Hibernate中的属性
            键:值 
          -->
          <!-- hibernate.connection.driver_class : 连接数据库的驱动  -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
          <!-- hibernate.connection.username : 连接数据库的用户名 -->
        <property name="hibernate.connection.username">root</property>
          <!-- hibernate.connection.password : 连接数据库的密码 -->
        <property name="hibernate.connection.password">1234</property>
          <!-- hibernate.connection.url : 连接数据库的地址,路径 -->
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/EE19Day01</property>

        <!-- show_sql: 操作数据库时,会 向控制台打印sql语句 -->
        <property name="show_sql">true</property>
        <!-- format_sql: 打印sql语句前,会将sql语句先格式化  -->
        <property name="format_sql">true</property>
        <!-- hbm2ddl.auto: 生成表结构的策略配置
             update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构. 
                    如果存在表结构,并且表结构与实体一致,那么不做修改
                    如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
             create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
             create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
             validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
          -->
        <property name="hbm2ddl.auto">update</property>

        <!-- 数据库方言配置 
             方言:为不同的数据库,不同的版本,生成sql语句(DQL查询语句)提供依据 
             mysql 字符串 varchar
             orcale 字符串 varchar2
        -->

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>



        <!-- hibernate.connection.autocommit: 事务自动提交  -->
        <property name="hibernate.connection.autocommit">true</property>
        <!-- 将Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession -->
        <property name="hibernate.current_session_context_class">thread</property>
        <!-- 引入ORM 映射文件 
            填写src之后的路径
         -->
        <mapping resource="com/itheima/a_hello/User.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

Hibernate中持久化类–javabean

1、javabean的编写规范

  • 提供一个无参数 public访问控制符的构造器
  • 提供一个标识属性,映射数据表主键字段
  • 所有属性提供public访问控制符的 set get 方法(javaBean)
  • 标识属性应尽量使用基本数据类型的包装类型
  • 不要用final修饰实体 (将无法生成代理对象进行优化)

2、持久化对象的唯一标识OID

  • java按地区区分同一个类的不同对象
  • 关系数据库用主键区分同一条记录
  • Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系
    结论:对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID付值
区分自然主键和代理主键

一、主键需要具备:

  • 不为空
  • 不能重复
  • 不能改变

    自然主键:在业务中,某个属性符合主键的三个要求.那么该属性可以作为主键列.
    代理主键:在业务中,不存符合以上3个条件的属性,那么就增加一个没有意义的列.作为主键.

基本数据与包装类型
  • 基本数据类型和包装类型对应hibernate的映射类型相同
  • 基本类型无法表达null、数字类型的默认值为0。
  • 包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类。

数据类型的对应图标表
这里写图片描述


普通属性
<hibernate-mapping> 
            package 用于配置PO类所在包
                例如: package="com.itheima.d_hbm"
        <class> 配置 PO类 和 表 之间对应关系
            name:PO类全限定类名
                例如:name="com.itheima.d_hbm.Person"
                如果配置 package,name的取值可以是简单类名 name="Person"
            table : 数据库对应的表名
            dynamic-insert="false" 是否支持动态生成insert语句
            dynamic-update="false" 是否支持动态生成update语句
                如果设置true,hibernate底层将判断提供数据是否为null,如果为null,insert或update语句将没有此项。
        普通字段
            <property>
                name : PO类的属性
                column : 表中的列名,默认name的值相同
                type:表中列的类型。默认hibernate自己通过getter获得类型,一般情况不用设置
                    取值1: hibernate类型
                        string 字符串
                        integer 整形
                    取值2: java类型 (全限定类名)
                        java.lang.String 字符串
                    取值3:数据库类型
                        varchar(长度) 字符串
                        int 整形
                        <property name="birthday">
                            <column name="birthday" sql-type="datetime"></column>
                        </property>
                        javabean 一般使用类型 java.util.Date
                        jdbc规范提供3中
                            java类型              mysql类型
                            java.sql.Date       date
                            java.sql.time       time
                            java.sql.timestamp  timestamp
                            null                datetime

                            以上三个类型都是java.util.Date子类

                length : 列的长度。默认值:255
                not-null : 是否为null
                unique : 是否唯一
                access:设置映射使用PO类属性或字段
                    property : 使用PO类属性,必须提供setter、getter方法
                    field : 使用PO类字段,一般很少使用。
                insert 生成insert语句时,是否使用当前字段。
                update 生成update语句时,是否使用当前字段。
                    默认情况:hibernate生成insert或update语句,使用配置文件所有项
        注意:配置文件如果使用关键字,列名必须使用重音符    
主键
<id>配置主键
                name:属性名称
                access="" 设置使用属性还是字段
                column=""  表的列名
                length=""  长度
                type="" 类型
            <generator> class属性用于设置主键生成策略
                1.increment 由hibernate自己维护自动增长
                    底层通过先查询max值,再+1策略
                    不建议使用,存在线程并发问题
                2.identity hibernate底层采用数据库本身自动增长列
                    例如:mysql auto_increment
                3.sequence hibernate底层采用数据库序列
                    例如:oracle 提供序列
                4.hilo 

                    </generator>
                5.native 根据底层数据库的能力选择 identity、sequence 或者 hilo 中的一个。【】
                ##以上策略使用整形,long, short 或者 int 类型
                6.uuid 采用字符串唯一值【】
                ##以上策略 代理主键,有hibernate维护。
                7.assigned 自然主键,由程序自己维护。【】
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值