Hibernate笔记一

一、Configuration类和作用

import org.hibernate.cfg.Configuration;

public class HibernateUtils {
	
	// ctrl + shift + x
	private static final Configuration CONFIG;
	private static final SessionFactory FACTORY;
	
	// 编写静态代码块
	static{
		// 加载XML的配置文件
		CONFIG = new Configuration().configure();
		// 构造工厂
		FACTORY = CONFIG.buildSessionFactory();
	}
	
	/**
	 * 从工厂中获取Session对象
	 * @return
	 */
	public static Session getSession(){
		return FACTORY.openSession();
	}
	
	/**
	 * // 从ThreadLocal类中获取到session的对象
	 * @return
	 */
	public static Session getCurrentSession(){
		
		return FACTORY.getCurrentSession();
	}
}

1. Configuration类

Configuration对象用于配置并且启动Hibernate。

* Configuration对象用于配置并且启动Hibernate。
* Hibernate应用通过该对象来获得对象-关系映射文件中的元数据,以及动态配置Hibernate的属性,然后创建SessionFactory对象。

2. Configuration类的其他应用

加载配置文件的种类,Hibernate支持xml和properties类型的配置文件

如果采用的是properties的配置文件,那么通过Configuration configuration = new Configuration();

但是需要自己手动加载映射文件
* 例如:config.addResource("Student.hbm.xml");

* 如果采用的XML的配置文件,通过Configuration configuration = new Configuration().configure();加载配置文件

二、SessionFactory工厂类

是生成Session对象的工厂类

1、SessionFactory类的特点

一般应用使用一个SessionFactory,最好是应用启动时就完成初始化。

* 由Configuration通过加载配置文件创建该对象。
* SessionFactory对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存。
* 预定义SQL语句
                * 使用Configuration类创建了SessionFactory对象是,已经在SessionFacotry对象中缓存了一些SQL语句
                * 常见的SQL语句是增删改查(通过主键来查询)
                * 这样做的目的是效率更高
 * 一个SessionFactory实例对应一个数据库,应用从该对象中获得Session实例。
* SessionFactory是线程安全的,意味着它的一个实例可以被应用的多个线程共享。
* SessionFactory是重量级的,意味着不能随意创建或销毁它的实例。如果只访问一个数据库,只需要创建一个SessionFactory实例,且在应用初始化的时候完成。
* SessionFactory需要一个较大的缓存,用来存放预定义的SQL语句及实体的映射信息。另外可以配置一个缓存插件,这个插件被称之为Hibernate的二级缓存,被多线程所共享

三、Session接口

应避免多个线程使用同一个Session实例,应为每次客户请求分配独立的Session实例

Session是在Hibernate中使用最频繁的接口。也被称之为持久化管理器。它提供了和持久化有关的操作,比如添加、修改、删除、加载和查询实体对象

* Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心
* Session是线程不安全的
* 所有持久化对象必须在 session 的管理下才可以进行持久化操作
* Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久化操作的数据都缓存在 session 对象处
* 持久化类与 Session 关联起来后就具有了持久化的能力

常用的方法:

* save(obj)
* delete(obj)  
* get(Class,id)
* update(obj)
* saveOrUpdate(obj)                   
* createQuery() 

四、Transaction接口

 Transaction是事务的接口
常用的方法
        * commit()                -- 提交事务
        * rollback()            -- 回滚事务
    
特点
        * Hibernate框架默认情况下事务不自动提交.需要手动提交事务
        * 如果没有开启事务,那么每个Session的操作,都相当于一个独立的事务

 

五、持久化类 

一个Java类(JavaBean),这个Java类与表建立了映射关系就可以成为是持久化类。

1、自然主键和代理主键

* 自然主键:对象本身的一个属性.创建一个人员表,每个人都有一个身份证号.(唯一的)使用身份证号作为表的主键.自然主键

* 代理主键:不是对象本身的一个属性.创建一个人员表,为每个人员单独创建一个字段.用这个字段作为主键.代理主键

创建表的时候尽量使用代理主键创建表

 2、主键的生成策略

1. increment:适用于short,int,long作为主键.不是使用的数据库自动增长机制.
        * Hibernate中提供的一种增长机制.
            * 先进行查询    :select max(id) from user;
            * 再进行插入    :获得最大值+1作为新的记录的主键.        
        * 问题:不能在集群环境下或者有并发访问的情况下使用.    
2. identity:适用于short,int,long作为主键。但是这个必须使用在有自动增长数据库中.采用的是数据库底层的自动增长机制.
        * 底层使用的是数据库的自动增长(auto_increment).像Oracle数据库没有自动增长.   
3. sequence:适用于short,int,long作为主键.底层使用的是序列的增长方式.
        * Oracle数据库底层没有自动增长,想自动增长需要使用序列.    
4. uuid:适用于char,varchar类型的作为主键.
        * 使用随机的字符串作为主键.    
5. native:本地策略.根据底层的数据库不同,自动选择适用于该种数据库的生成策略.(short,int,long)
        * 如果底层使用的MySQL数据库:相当于identity.
        * 如果底层使用Oracle数据库:相当于sequence.
6. assigned:主键的生成不用Hibernate管理了.必须手动设置主键.    

3、持久化对象的状态

 

Hibernate为了管理持久化类:将持久化类分成了三个状态
            * 瞬时态:Transient  Object
                * 没有持久化标识OID, 没有被纳入到Session对象的管理.
            * 持久态:Persistent Object
                * 有持久化标识OID,已经被纳入到Session对象的管理.
            * 脱管态:Detached Object
                * 有持久化标识OID,没有被纳入到Session对象的管理.


    1. 瞬时态    -- 没有持久化标识OID, 没有被纳入到Session对象的管理
        * 获得瞬时态的对象
            * User user = new User()
        * 瞬时态对象转换持久态
            * save()/saveOrUpdate();
        * 瞬时态对象转换成脱管态
            * user.setId(1)
    2. 持久态    -- 有持久化标识OID,已经被纳入到Session对象的管理
        * 获得持久态的对象
            * get()/load();
        * 持久态转换成瞬时态对象
            * delete();  --- 比较有争议的,进入特殊的状态(删除态:Hibernate中不建议使用的)
        * 持久态对象转成脱管态对象
            * session的close()/evict()/clear();
    3. 脱管态    -- 有持久化标识OID,没有被纳入到Session对象的管理
        * 获得托管态对象:不建议直接获得脱管态的对象.
            * User user = new User();
            * user.setId(1);
        * 脱管态对象转换成持久态对象
            * update();/saveOrUpdate()/lock();
        * 脱管态对象转换成瞬时态对象
            * user.setId(null);
    4. 注意:持久态对象有自动更新数据库的能力!!!

六、Session对象的一级缓存

自带的不可卸载的.一级缓存的生命周期与session一致.一级缓存称为session级别的缓存.

二级缓存可以在多个session中共享数据,二级缓存称为是sessionFactory级别的缓存。默认没有开启,需要手动配置才可以使用的

 * Session接口中,有一系列的java的集合,这些java集合构成了Session级别的缓存(一级缓存).将对象存入到一级缓存中,session没有结束生命周期,那么对象在session中存放着
* 内存中包含Session实例 --> Session的缓存(一些集合) --> 集合中包含的是缓存对象!

在同一个Session对象中两次查询,可以证明使用了缓存

Hibernate框架是利用快照机制来完成的(SnapShot)做到数据发生变化时进行同步操作的呢

* Session.clear()                        -- 清空缓存。
* Session.evict(Object entity)            -- 从一级缓存中清除指定的实体对象。
* Session.flush()                        -- 刷出缓存

七、事务相关的概念

事务相关概念

    1. 什么是事务
        * 事务就是逻辑上的一组操作,组成事务的各个执行单元,操作要么全都成功,要么全都失败.
    2. 事务的特性
        * 原子性    -- 事务不可分割.
        * 一致性    -- 事务执行的前后数据的完整性保持一致.
        * 隔离性    -- 一个事务执行的过程中,不应该受到其他的事务的干扰.
        * 持久性    -- 事务一旦提交,数据就永久保持到数据库中.
    3. 如果不考虑隔离性:引发一些读的问题
        * 脏读            -- 一个事务读到了另一个事务未提交的数据.
        * 不可重复读    -- 一个事务读到了另一个事务已经提交的update数据,导致多次查询结果不一致.
        * 虚读            -- 一个事务读到了另一个事务已经提交的insert数据,导致多次查询结构不一致.
    4. 通过设置数据库的隔离级别来解决上述读的问题
        * 未提交读:以上的读的问题都有可能发生.
        * 已提交读:避免脏读,但是不可重复读,虚读都有可能发生.
        * 可重复读:避免脏读,不可重复读.但是虚读是有可能发生.
        * 串行化:以上读的情况都可以避免.
    5. 如果想在Hibernate的框架中来设置隔离级别,需要在hibernate.cfg.xml的配置文件中通过标签来配置
        * 通过:hibernate.connection.isolation = 4 来配置
        * 取值
            * 1—Read uncommitted isolation
            * 2—Read committed isolation
            * 4—Repeatable read isolation
            * 8—Serializable isolation

丢失更新的问题

    1. 如果不考虑隔离性,会产生写入数据的问题,这一类的问题叫丢失更新的问题。
    2. 例如:两个事务同时对某一条记录做修改,就会引发丢失更新的问题。
        * A事务和B事务同时获取到一条数据,同时再做修改
        * 如果A事务修改完成后,提交了事务
        * B事务修改完成后,不管是提交还是回滚,如果不做处理,都会对数据产生影响
    
    3. 解决方案有两种
        * 悲观锁
            * 采用的是数据库提供的一种锁机制,如果采用做了这种机制,在SQL语句的后面添加 for update 子句
                * 当A事务在操作该条记录时,会把该条记录锁起来,其他事务是不能操作这条记录的。
                * 只有当A事务提交后,锁释放了,其他事务才能操作该条记录
        
        * 乐观锁
            * 采用版本号的机制来解决的。会给表结构添加一个字段version=0,默认值是0
                * 当A事务在操作完该条记录,提交事务时,会先检查版本号,如果发生版本号的值相同时,才可以提交事务。同时会更新版本号version=1.
                * 当B事务操作完该条记录时,提交事务时,会先检查版本号,如果发现版本不同时,程序会出现错误。
    
    4. 使用Hibernate框架解决丢失更新的问题
        * 悲观锁
            * 使用session.get(Customer.class, 1,LockMode.UPGRADE); 方法
        
        * 乐观锁
            * 1.在对应的JavaBean中添加一个属性,名称可以是任意的。例如:private Integer version; 提供get和set方法
            * 2.在映射的配置文件中,提供<version name="version"/>标签即可。

 Hibernate框架中,使用session对象开启事务,所以需要来传递session对象,框架提供了ThreadLocal的方式

 需要在hibernate.cfg.xml的配置文件中提供配置

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

使用SessionFactory的getCurrentSession()方法,获取当前的Session对象。并且该Session对象不用手动关闭,线程结束了,会自动关闭

public static Session getCurrentSession(){
	return factory.getCurrentSession();
}

想使用getCurrentSession()方法,必须要先配置才能使用

八、查询方式

1、Query查询接口

Query query = session.createQuery("from Customer");
Query query = session.createQuery("from Customer where name = ?");
Query query = session.createQuery("from Customer where name = :aaa and age = :bbb");
query.setString("xiaotu", "小兔");
List<Customer> list = query.list();

2、Criteria查询接口

Criteria criteria = session.createCriteria(Customer.class);
Criteria criteria = session.createCriteria(Customer.class);
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.eq("name", "小兔"));
List<Customer> list = criteria.list();

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值