Hibernate入门(二)

2018-06-18 03:21:36来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

一、主键生成策略

1.主键的类型

  • 自然主键: 把有特定业务含义的字段作为了主键 eg: 用户的名字, 身份证号码

  • 代理主键: 把没有特定业务含义的字段作为了主键 eg: id

  开发里面的话通常用代理主键

2.主键的生成策略

2.1概述

? Hibernate中为了更好的维护数据, 提供很多种主键生成策略.

2.2 主键策略类型
  • increment :自动增长,适用类型:short,int,long类型主键.在多进程和集群下不要使用.用的不是数据库的自动增长, hibernate底层的增长策略,select max(id) from customer; 然后+1作为下一条记录的ID.

  • assigned:需要用户手动输入OID的.

  • identity:自动增长,用的是数据库的自动增长。适用类型:short,int,long类型主键.支持自动增长数据库如Mysql

  • sequence:序列,适用类型:short,int,long类型主键.支持序列的数据库如:Oracle.

  • native:本地策略,根据数据库的底层采用使用identity还是sequence.

  • uuid:随机的字符串,适用于字符串类型的主键.

  规则: 如果主键类型是 int short long 用 native

?      如果主键类型是字符串, 用uuid

二、持久化类的编写规则

1.持久化类概述

?   在Hibernate中,用来描述数据库表结构的类,称之为持久化类.

?   Java类与数据库的某个表建立了映射关系.这个类就称为是持久化类

?   持久化类 = Java类 + hbm的配置文件

2.持久化类定义规范

  • 遵循JavaBean定义规范

    ? 类是公有的

    ? 需要一个无参的构造函数

    ? 属性是私有的,需要提供公共的getter和setter方法进行访问属性

  • 必须用一个属性描述数据库表的主键

  • 主键属性的类型必须是引用类型,且需要实现Serializable接口

三、 持久化对象的三种状态

1.概述

?   由持久化类创建的对象就是持久化对象。Hibernate为了管理持久化对象:将持久化对象分成了三个状态.hibernate底层实现过程中,定义的三种状态主要方便开发人员调用session的API.

?   区分三种状态:

?     瞬时态 :没有持久化标识OID的,没有纳入到session的管理.

?     持久态 :有持久化标识OID的,已经纳入到session的管理.

?     托管(游离态)态:有持久化标识OID的,没有纳入到session的管理.

java代码:

/**
 * 区分三种状态:
 * 瞬时态: 没有持久化标识oid,没有纳入Session管理
 * 持久态: 有持久化标识oid,并且纳入了Session管理
 * 托管态: 有持久化标识oid,但没有纳入Session管理
 */    
    @Test
    public void fun01(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        transaction.begin();
        
        User user = new User();//瞬时态
        user.setUname("张三");
        user.setUage(18);
        
        session.save(user);
        System.out.println(user.toString());//持久态
        
        transaction.commit();
        session.close();
        System.out.println(user.toString());//托管态
    }

2.三种状态的转换

2.1瞬时态对象

没有持久化标识OID, 没有被纳入到Session对象的管理

  • 获得:new对象

  • 状态转换:

    ? 瞬时态--->持久态:save()/saveOrUpdate();

    ? 瞬时态--->托管态:把瞬时态对象设置一个id

2.2持久态对象

有持久化标识OID,已经被纳入到Session对象的管理

  • 获得:get()/load()/find()..

  • 状态转换:

    ? 持久态--->瞬时态:session.delete(); (Hibernate中不建议使用的)

    ? 持久态--->托管态:close()/clear()/evict(Object obj);

2.3托管态对象

  有持久化标识OID,没有被纳入到Session对象的管理

  • 获得:new对象,给对象设置id

  • 状态转换:

    ? 托管态-->瞬时态:把对象的id设置为null

    ? 托管态--->持久态:update()/saveOrUpdate();

3.持久态对象可以自动更新数据库

  持久态对象依赖于缓存可以自动更新数据库

  • Java代码

 1     @Test
 2     public void fun05(){
 3         Session session = HibernateUtils.openSession();
 4         Transaction transaction = session.beginTransaction();
 5         transaction.begin();
 6         //持久态对象
 7         User user = session.get(User.class, 1);
 8         user.setUname("李四");
 9         //session.update(user);可以不写,因为当前的user是持久化对象
10 
11         transaction.commit();
12         session.close();
13     }

四、hibernate的缓存

1.缓存概述

?   缓存就是一块内存空间。

?   将数据源(数据库或者文件)中的数据读取出来存放到缓存中,再次获取的时候 ,直接从缓存中获取,这样可以提升程序的性能!

?   作用:提升程序的性能

2.Hibernate的缓存类别

?   一级缓存:session对象的缓存,自带的不可卸载的. 一级缓存的生命周期与session一致。

?   二级缓存:二级缓存可以在多个session中共享数据。一般不会用,企业里通常使用Redis

3.一级缓存

?   在 Session 接口的实现中包含一系列的 Java集合,这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期.

?   当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图get()、 load()对象时,会判断缓存中是否存在该对象,有则返回,此时不查询数据库。没有再查询数据库.

    @org.junit.Test
    public void fun03(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        //持久态对象
        User user1 = session.get(User.class, 1);//马上发送一条sql语句
        System.out.println(user1.toString());

        User user2 = session.get(User.class, 1);//马上发送一条sql语句
        System.out.println(user1 == user2);//true

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

测试结果:

Hibernate:
  select
    user0_.uid as uid1_0_0_,
    user0_.uname as uname2_0_0_,
    user0_.uage as uage3_0_0_
  from
    user user0_
  where
    user0_.uid=?
User{uid=1, uname='李四', uage=18}
true

4.一级缓存的内部结构:(缓存区, 快照区)

五、Hibernate的事务

1.事务的概念

?   事务就是逻辑上的一组操作,组成事务的各个执行单元,操作要么全都成功,要么全都失败.

2.事务的特性

?   原子性: 事务不可分割.

?     eg: 张三 1000 李四 1000; 张三给李四转100, 要么转账成功,要么失败

?   一致性: 事务执行的前后数据的完整性保持一致.

?     eg: 张三 1000 李四 1000 =2000; 张三给李四转100, 成功了 张三 900 李四1100 = 2000; 失败

  ? 隔离性: 一个事务执行的过程中,不应该受到其他的事务的干扰.

?   持久性: 事务一旦提交,数据就永久保持到数据库中.

?     eg: 张三 1000 李四 1000, 给李四转520;

3.不考虑隔离性会出现的相关问题

  • 脏读: 一个事务读到了另一个事务未提交的数据.

  • 不可重复读: 一个事务读到了另一个事务已经提交的update数据,导致多次查询结果不一致. 张三 1000 ; 李四 1000

  • 虚读: 一个事务读到了另一个事务已经提交的insert数据,导致多次查询结构不一致.

4.隔离级别

隔离级别含义
READ_UNCOMMITTED 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
READ_COMMITTED 允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生
REPEATABLE_READ 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
SERIALIZABLE 完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

实际开发中,不会选择最高或者最低隔离级别,选择 READ_COMMITTED(oracle 默认)、REPEATABLE_READ (mysql默认)

5.Hibernate配置隔离级别

  hibernate通过在hibernate.cfg.xml的配置文件中设置隔离级别:

<property name="hibernate.connection.isolation">4</property>

  取值

    ? 1: Read uncommitted isolation,读未提交

?     2: Read committed isolation,读已提交,解决脏读。

?     4: Repeatable read isolation,可重复读

?     8: Serializable isolation,串行化

6.hibernate对 session的管理

6.1把Session绑定在当前线程

?   在开发中,通常在业务层进行事物管理,在Dao层操作数据库. 也就是说业务层需要连接(Session)开启事物,Dao层需要连接(Session)操作数据库,如何保证这些连接是同一个呢?

? 在JDBC阶段,我们通过了两种方式解决:

  ? 1.向下传递参数

?   2.绑定到TreadLocal里面.

?   在Hibernate中,Session 对象与本地线程绑定很简单,只需要两步:

  • 在hibernate.cfg.xml文件中,添加属性,开启与本地线程绑定的session

    <property name="hibernate.current_session_context_class">thread</property>
  • 通过SessionFactory的getCurrentSession()方法获得Session

    Session session = sessionFactory.getCurrentSession();

    注意:通过getCurrentSession()方法获得的session,无需调用close方法释放资源。当事物提交或者回滚,会自动释放资源.

6.2 Session获取方式的区别
  • 调用getCurrentSession()方法时,会判断当前线程中是否绑定了session。

    ? 如果绑定了,直接返回线程中绑定的session

    ? 如果没有绑定,先去创建一个session,然后讲session存储到当前线程中,再返回。

  • 调用openSession()方法时,只会创建一个新的session,且不会存储到当前线程。

  • 通过getCurrentSession()方法获得的session,无需调用close方法释放资源. 通过openSession()方法获得的session需要手动释放资源。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:java实现搜索附近地点或人的功能

下一篇:Java内部类