0%

Hibernate

Hibernate

Hibernate概述

  1. Hibernate框架应用在javaEE三层结构中的dao层框架
  2. 在dao层里面做对数据库crud(增上改查)操作,使用Hibernate实现crud操作,Hibernate底层代码就是jdbc,Hibernate对jdbc进行封装,使用Hibernate可以不用写复杂的jdbc代码,不需要写sql语句实现
  3. Hibernate是开源的轻量级的框架

ORM思想

什么是ORM

object relational mapping:对象关系映射

  1. 让实体类和数据库表进行一一对应关系

    让实体类首先和数据库表对应

    让实体类属性和表里面字段对应

  2. 不需要直接操作数据库表,而操作表对应实体类对象

Hibernate入门

  1. 搭建Hibernate环境

    导入jar包(包括本身的lib中的required和jpa以及mysql驱动jar包和log4j日志jar包)

  2. 创建实体类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class User {
    //hibernate要求实体类中有一个属性唯一
    private int uid;
    private String uname;
    private String pwd;

    public int getUid() {
    return uid;
    }

    public void setUid(int uid) {
    this.uid = uid;
    }

    public String getUname() {
    return uname;
    }

    public void setUname(String uname) {
    this.uname = uname;
    }

    public String getPwd() {
    return pwd;
    }

    public void setPwd(String pwd) {
    this.pwd = pwd;
    }
    }
  3. 配置实体类和数据库表一对关系(映射关系)

    1. 创建xml格式的配置文件(位置没有固定文件,但建议在实体类所在包中,名称为实体类名.hbm.xml)

    2. 配置xml格式,在配置文件中首先引入xml约束,hibernate里面引入的是dtd约束

    1
    2
    3
    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    1. 配置映射关系
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <!-- User.hbm.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>
    <!-- 1.配置类和表对应
    class标签
    name属性:实体类全路径
    table属性:数据库表名称
    -->
    <class name="com.zephon.entity.User" table="user">
    <!-- 2.配置实体类id和表id对应
    hibernate要求实体类有一个属性唯一值
    hibernate要求表有字段作为唯一值
    -->
    <!-- id标签
    name属性:实体类里面id属性名称
    column属性:生成的表字段名称
    -->
    <id name="uid" column="uid">
    <!-- 设置数据库中增长策略
    native:生成表id值就是主键自动增长
    -->
    <generator class="native"></generator>
    </id>
    <!-- 配置其它属性和表字段对应
    name属性:实体类属性名称
    column属性:生成表字段名称
    -->
    <property name="uname" column="uname"></property>
    <property name="pwd" column="pwd"></property>
    </class>
    </hibernate-mapping>
    1. 创建hibernate的核心配置文件(必须在src下,名称必须是hibernate.cfg.xml)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <!-- 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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql:///JavaMysql0</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <!-- 配置hibernate信息 可选-->
    <!-- 输出底层sql语句 -->
    <property name="hibernate.show_sql">true</property>
    <!-- 输出底层sql语句格式 -->
    <property name="hibernate.format_sql">true</property>
    <!-- 是否需要hibernate帮忙创建表
    update:如果已经有表,更新,没有则创建-->
    <property name="hibernate.hbm2ddl.auto">update</property>
    <!-- 配置数据库方言
    如:在mysql中实现分页,关键字是limit,只能在mysql中用
    而在oracle,实现分页用rownum
    该配置就是让hibernate识别不同数据库特有的语句
    -->
    <!-- MySQL5.0之后,type=... 不再有效,所以修改方言中MySQLInnoDBDialect为MySQL5InnoDBDialect -->
    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
    <!-- 把映射文件放到核心配置文件中 -->
    <mapping resource="com/zephon/entity/User.hbm.xml"/>
    </session-factory>
    </hibernate-configuration>
    1. 测试-实现添加操作
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class TestHibernate {
    public static void main(String[] args) {
    //1. 加载hibernate核心配置文件
    //在src下找到名称是hibernate.cfg.xml的文件
    Configuration cfg = new Configuration();
    cfg.configure();

    //2. 创建SessionFactory对象
    //读取hibernate核心配置文件内容,创建sessionFactory
    //在此过程中,根据映射关系,在数据库中把表创建
    SessionFactory sessionFactory = cfg.buildSessionFactory();

    //3. 使用SessionFactory创建session对象
    // 类似于jdbc中的连接
    Session session = sessionFactory.openSession();

    //4. 开启事务
    Transaction tx = session.beginTransaction();

    //5. 写具体逻辑crud操作
    User user = new User();
    user.setUname("小明");
    user.setPwd("123");
    //调用session的方法实现添加
    session.save(user);

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

    //7. 关闭资源
    session.close();
    sessionFactory.close();

    }
    }

Hibernate 核心api

Configuration

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

到src下找到名称hibernage.cfg.xml配置文件,创建对象,将配置文件放到对象中,即加载核心配置文件

SessionFactory(重点)

  1. 使用configuration对象创建sessionFactory对象

    1)创建sessionFactory过程中做的事:

    根据核心配置文件中,数据库配置,映射文件部分,到数据库里根据映射关系创建表(前提是在配置文件中配置了需要创建表)

  2. 创建sessionFactory过程中,该过程特别耗资源,

    解决:在hibernate操作中,建议每个项目一般创建一个sessionFactory对象

    具体实现:写一个工具类,用静态代码块实现,静态代码块在类加载时执行,执行一次

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class HibernateUtils {
    private static Configuration cfg = null;
    private static SessionFactory sessionFactory = null;
    static {
    //加载核心配置文件
    cfg = new Configuration();
    cfg.configure();
    sessionFactory = cfg.buildSessionFactory();
    }

    public static SessionFactory getSessionFactory(){
    return sessionFactory;
    }

    }

Session(重点)

  1. session类似于jdbc中connection

  2. 调用session里面不同的方法实现crud操作

    1)添加 save

    2)修改 update

    3)删除 delete

    4)根据id查询 get

  3. session对象是单线程对象(不能共用,只能自己用)

Transaction

  1. 事务对象

    1
    2
    //4. 开启事务
    Transaction tx = session.beginTransaction();
  2. 事务的提交和回滚

    1
    2
    tx.commit();//提交
    tx.rollback();//回滚
  3. 事务

    1)四个特性

    原子性、一致性、隔离性、持久性

实体类编写规则

  1. 实体类里面的属性是私有的

  2. 私有属性使用对应公开的set、get方法

  3. 要求有一个属性作为唯一值(一般用id值)

  4. 属性建议不使用基本数据类型,使用基本数据类型对应的包装类

    1)八个基本数据类型对应的包装类

    ​ int-Interger

    ​ char-Character

    ​ 其它的都是首字母大写 如:double-Double

    2)使用包装类的原因:

    ​ 如:表示学生的分数,若int score;

    ​ 学生得0分:int score=0;

    ​ 学生没有参加考试,int score=0;不能准确表示

    如果用包装类:Interger score = 0;得0分

    Interger score=null; 没有参加考试

Hibernate主键生成策略

  1. hibernate要求实体类里面有一个属性作为唯一值,对应表主键,主键可以不同生成策略

  2. hibernate主键生成策略有很多的值

    1
    2
    3
    4
    <!-- 设置数据库中增长策略
    native:生成表id值就是主键自动增长
    -->
    <generator class="native"></generator>
  3. 在class属性中的值

  4. 演示使用uuid

    1. 使用uuid生成策略,实体类id属性类型必须改成字符串类型
    2. 配置部分改成uuid

实体类操作

添加

使用session.save方法

1
2
3
4
5
User user = new User();
user.setUname("小红");
user.setPwd("123");
//调用session的方法实现添加
session.save(user);

根据id查询

调用session.get方法

1
2
3
//第一个参数:实体类的class,第二个参数:id值
User user = session.get(User.class,2);
System.out.println(user.getUid()+"-"+user.getUname()+"-"+user.getPwd());

修改

首先查询(根据id查询),再修改值

1
2
3
4
5
6
7
8
//修改uid=2记录的uname值
//1. 根据id查询
User user = session.get(User.class, 2);
//2. 向返回user对象里面设置修改之后的值
user.setUname("小李");
//3. 调用session的方法update修改
//执行过程:到user对象里面找到uid值,根据uid进行修改
session.update(user);

删除

调用session.delete方法

1
2
3
4
5
6
7
8
//删除
//方式一 根据id查询对象(常用)
User user = session.get(User.class, 2);
session.delete(user);
//方式二
User u = new User();
u.setUid(2);
session.delete(u);

saveOrUpdate方法

实体类对象状态是瞬时态时,做添加操作

实体类对象状态是托管态时,做更新操作

实体类对象状态是持久态时,做更新操作

实体类对象状态(概念)

  1. 瞬时态

    对象中没有id值,对象与session没有关联

    1
    2
    3
    User u = new User();
    u.setUname("jack");
    u.setPwd("123");
  2. 持久态

    对象中有id值,与session有关联

    1
    User user = session.get(User.class,1);
  3. 托管态

    对象中有id值,与session没有关联

    1
    2
    User user = new User();
    user.setUid(3);

Hibernate的一级缓存

什么是缓存

  1. 数据存放到数据库里面,数据库本身是文件系统,使用流方式操作文件效率不是很高

    1)把数据存到内存里面,不需要使用流方式,可以直接读内存中的数据

    2)把数据存到内存中,提高读取效率

Hibernate缓存

  1. hibernate框架中提供很多优化方式,hibernate的缓存就是一个优化方式

  2. hibernate缓存特点:

    第一类:hibernate的一级缓存

    1)hibernate的一级缓存默认是打开的

    2)hibernate的一级缓存使用范围,是session的范围,从session创建到session关闭

    3)hibernate的一级缓存中,存储数据必须是持久态数据

    第二类:hibernate的二级缓存

    1)目前已经不使用了,替代技术redis

    2)二级缓存默认不是打开的,需要配置

    3)二级缓存使用范围,是sessionFactory范围

验证一级缓存的存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class TestCasch {
public static void main(String[] args) {
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();

//1根据uid=2查询
//执行第一次get方法,查看是否查询数据库,是否发送sql语句
User user = session.get(User.class, 2);
System.out.println(user.getUname());
//2再根据uid=2查询
//执行第二次get方法,查看是否查询数据库,是否发送sql语句
User user1 = session.get(User.class, 2);
System.out.println(user1.getUname());

transaction.commit();
session.close();
sessionFactory.close();
}

}

Hibernate一级缓存特性

  1. 持久态自动更新数据库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class TestCasch {
    public static void main(String[] args) {
    SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();

    //1.根据id查询
    User user = session.get(User.class,2);
    //2.设置返回对象值
    user.setUname("Lucy");
    //3.调用方法实现
    //session.update(user); //注释了仍然可以更新

    transaction.commit();
    session.close();
    sessionFactory.close();

    }

    }
  2. 执行过程(了解)

    1)第一步查询时会把返回的user持久态对象放到一级缓存和缓存对应的快照区中

    2)第二步设置对象值时会修改user对象里面的值,同时修改一级缓存内容,但不会修改一级缓存对应的快照区中内容

    3)最后提交事务时,会比较一级缓存的内容和对应的快照区内容是否相同,若不同,则需要把一级缓存内容更新到数据库中

Hibernate事务代码规范写法

1.代码结构

1
2
3
4
5
6
7
8
try{
开启事务
提交事务
}catch(){
回滚事务
}finally(){
关闭
}

2.实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void testDemo(){
SessionFactory sessionFactory =null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();

//添加
User user = new User();
user.setUname("小王");
user.setPwd("153");
session.save(user);

transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
session.close();
sessionFactory.close();
}
}

Hibernate绑定session

  1. session类似于jdbc中的connection

  2. Hibernate已经帮实现与本地线程绑定session

  3. 获取与本地线程绑定的session

    1)在hibernate核心配置文件中配置

    1
    2
    3
    <!-- 在hibernate核心配置文件中配置 -->
    <property name="hibernate.current_session_context_class">thread</property>

    2)调用sessionFactory中的方法

    1
    2
    3
    4
    //提供返回与本地线程绑定的session的方法
    public static Session getSessionObject(){
    return sessionFactory.getCurrentSession();
    }

Hibernate的api使用

Query对象

  1. 使用query对象,不需要写sql语句,但要写hql语句

    1)hql:hibernate query language,hibernate提供的查询语言,和普通sql语句相似

    2)hql和sql区别:

    ​ 使用sql操作表和表字段,而使用hql操作实体类和属性

  2. 查询所有记录的hql语句

    from 实体类名

  3. Query对象使用

    1)创建Query对象

    2)调用Query对象里面的方法得到结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
        public void testQuery(){
    SessionFactory sessionFactory =null;
    Session session = null;
    Transaction transaction = null;
    try{
    sessionFactory = HibernateUtils.getSessionFactory();
    // session = sessionFactory.openSession();
    session = HibernateUtils.getSessionObject();
    transaction = session.beginTransaction();

    Query query = session.createQuery("from User");
    List<User> list = query.list();
    for(User u:list){
    System.out.println(u);
    }

    transaction.commit();
    }catch (Exception e){
    transaction.rollback();
    }finally {
    session.close();
    sessionFactory.close();
    }
    }

Criteria对象

  1. 使用这个对象查询时,不需要写语句,直接调用方法实现

  2. 实现过程

    1)创建Criteria对象

    2)调用方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public void testCriteria(){
    SessionFactory sessionFactory =null;
    Session session = null;
    Transaction transaction = null;
    try{
    sessionFactory = HibernateUtils.getSessionFactory();
    // session = sessionFactory.openSession();
    session = HibernateUtils.getSessionObject();
    transaction = session.beginTransaction();

    Criteria criteria = session.createCriteria(User.class);
    List<User> list = criteria.list();
    for(User u:list){
    System.out.println(u);
    }

    transaction.commit();
    }catch (Exception e){
    transaction.rollback();
    }finally {
    session.close();
    sessionFactory.close();
    }

SQLQuery对象

  1. 使用该对象,调用底层sql实现

  2. 实现过程

    1)创建对象

    2)调用方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public void testSQL(){
    SessionFactory sessionFactory =null;
    Session session = null;
    Transaction transaction = null;
    try{
    sessionFactory = HibernateUtils.getSessionFactory();
    // session = sessionFactory.openSession();
    session = HibernateUtils.getSessionObject();
    transaction = session.beginTransaction();

    NativeQuery sqlQuery = session.createSQLQuery("select * from ta_user");
    //默认返回数组形式
    // List<Object[]> list = sqlQuery.list();
    // for(Object[] object:list){
    // System.out.println(Arrays.toString(object));
    // }
    //设置返回对象形式
    sqlQuery.addEntity(User.class);
    List<User> list = sqlQuery.list();
    for(User u:list){
    System.out.println(u);
    }
    transaction.commit();
    }catch (Exception e){
    transaction.rollback();
    }finally {
    session.close();
    sessionFactory.close();
    }
    }

待学

表与表之间的关系(一对多操作、多对多操作 )、hql、QBC等。。。。待学