Hibernate简介

一、概述

Hibernate是一个开放源代码的的对象关系映射框架。它对jdbc进行了封装,提供了强大,高性能的对象关系模型数据库的持久化服务。Hibernate提供的HQL(Hibernate Query Language)是面向对象的查询语言,它在对象模型数据和关系型数据库之间构建了一条快速,高效,便捷的沟通渠道。

二、Hibernate框架

1.ORM(Object Relation Mapping)称对象关系映射

在编写程序的时候,以面向对象的方式处理数据,在保存数据的时候,却以关系型数据的形式存储到数据库中,所以需要一种能在两者间进行数据转换的机制,这种机制称对象-关系映射机制,简称ORM.

2.实体对象的状态

>自由态

自由状态就是实体对象在内存中自由存在,此时它与数据库无关,自由状态有两个特性:

(1).不处于Session的缓存中,也就是不被任何一个Session实例关联。

(2).在数据中没有对应的记录。

>持久态

持久状态就是实体对象在Hibernate的管理情况下的状态。在持久状态下,实体对象的引用被纳入Hibernate实体容器中加以管理。处于持久状态的实体对象会被Hibernate固化到数据库中。持久状态的特性:

(1).位于一个Session实例的缓存中,也就是说,持久化对象总被一个Session实例关联。

(2).持久化对象和数据库中的相关记录对应。

(3).Session在清理缓存时,会根据持久化对象的属性变化来同步更新数据库。

(4).Session的Save()方法把实体对象从自由状态转变为持久状态。

(5).Session的load()方法或get()方法返回的实体对象总是持久状态。

(6).Session的update(),saveOrUpdate()和lock()方法使实体对象从游离状态转变被持久状态。

>游离态

当处于持久状态的实体对象,其对应的Session关闭以后,这个实体就处于游离状态,可以认为Session对象是实体对象在持久状态的宿主,而实体对象失去这个宿主,也就是这个宿主失效,那这个实体对象就处于游离状态。游离状态的特性:

(1).不再位于Session的缓存中,也可以说游离状态的实体对象不被Session关联。

(2).游离状态是由持久化变来的,因此在数据库中可能还存在与它对应的记录。

3.VO与PO

处于自由状态和游离状态下的实体对象称为值对象(Value Object,VO).

处于持久状态的实体对象称为持久对象(Persistent Object,PO).

VO和PO之间的区别:

1.VO对象包含两种状态,即自由状态和游离状态,是相对独立的对象,处于非管理状态。

2.PO对象处于持久状态,是Hibernate纳入其管理容器的对象,对应数据库中某条记录的Hibernate实体,PO的变化在事物提交的时将反映到数据库中。

3.如果一个PO与其对应的Session实例分离,就会变成VO.

三、Session管理

Session接口是Hibernate向应用程序提供的操作数据库的最主要的接口,它提供了基本的保存,更新,删除和加载Java对象的方法。

Session是由SessionFactory创建的,而SessionFactory的实现是线程安全的,也就是说,多个并发的线程可以同时访问一个SessionFactory并从其中获取Session实例,但Session不是线程安全的,Session中包含了数据库操作的相关信息,所以多个线程共享一个Session将会发生数据共享混乱。

3.1、ThreadLocal模式解决Session共享问题

ThreadLocal不是一个线程的本地实现,即它不是一个线程,而是线程局部变量(Thread Local Variable)。它的作用是为每一个使用这个变量的的线程都提供一个变量值的副本,并且每一个线程都可以独立地改变自己的副本,而不会和其他线程的副本冲突,从线程的角度来看,就好像每一个线程都完全拥有一个该变量一样。

ThreadLocal会给每一个线程提供一个变量的副本,就可以实现线程范围内Session共享,从而避免线程频繁创建和销毁Session,但是需要注意,使用完毕后需要手动关闭。

package com.test;

import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class LoginDao {
	private Session session=null;
	private Transaction tran=null;
	private static final ThreadLocal<Session> s=new ThreadLocal<Session>();//使用ThreadLocal方式来管理Session
	
	public LoginDao(){
		Configuration config=new Configuration().configure();
		SessionFactory factory=config.buildSessionFactory();
		//this.session=factory.openSession();
		this.session=s.get();//调用ThreadLocal的get方法得到session
		if (session==null) {
			this.session=factory.openSession();
			//this.session=factory.getCurrentSession();//使用这种方法,需要在配置文件中添加相应的配置信息
			s.set(session);//将session 放到ThreadLocal用进行管理
		}
	}
	
	/**
	 * 插入数据
	 */
	public void save(Login login){
		try {
         // Hibernate执行持久化操作需要的七大步
              // 1.读取配置文件
              Configuration config = new Configuration().configure();
              // 2.创建sessionFactory
              SessionFactory factory = config.buildSessionFactory();
              // 3.打开session
              Session session = factory.openSession();
              // 4.开启事务
              Transaction tran=session.beginTransaction();
              // 5.执行持久化操作 this.session.save(login); //6.提交事物 tran.commit();
              // 7.关闭Session
              session.close();
System.out.println("用户信息保存成功"); } catch (RuntimeException e) { if (tran!=null) { tran.rollback(); //throw e; e.printStackTrace(); } }finally{ this.session.close(); } } /** * 更新操作 */ public void update (Login login){ try { tran=session.beginTransaction(); session.update(login); tran.commit(); System.out.println("更新成功"); } catch (HibernateException e) { if (tran!=null) { tran.rollback(); //throw e; e.printStackTrace(); } }finally{ this.session.close(); } } /** * 删除操作 * @param login */ public void delete(Login login){ try { tran=this.session.beginTransaction(); session.delete(login); tran.commit(); System.out.println("删除成功"); } catch (HibernateException e) { if (tran!=null) { tran.rollback(); //throw e; e.printStackTrace(); } }finally{ this.session.close(); } } /** * 根据主键精确查询 * */ public Login getLoginByid(String name){ Login login=null; String hql="from Login as l where l.username=?"; Query query=this.session.createQuery(hql); query.setString(0, name); Iterator list=query.list().iterator(); if (list.hasNext()) { login=(Login)list.next(); } System.out.println("主键精确查询"); this.session.close(); return login; } public List queryAll(){ List list=null; String hql="from Login as l"; Query query =this.session.createQuery(hql); list=query.list(); System.out.println("查询所有记录"); this.session.close(); return list; } /** * 根据用户名进行模糊查询的操作 */ public List queryLike(String name){ List list=null; String hql="from Login l where l.username like ?"; Query query =this.session.createQuery(hql); query.setString(0, "%"+name+"%"); list=query.list(); System.out.println("模糊查询"); this.session.close(); return list; } }

3.2、openSession()和getCurrentSession()解析

Hibernate的SessionFactory类除了提供openSession()来返回Session外,还提供了getCurrentSession()方法,此方法是Hibernate的3.0.1版本之后才增加的,通过这个方法同样可以得到一个Session,但是这两个方法之间还是有区别的,它们之间的区别如下:

1.getCurrentSession()创建的Session会绑定当当前线程,而openSession()不会。

2.getCurrentSession()创建的Session会在事物回滚或事物提交后自动关闭,而openSession()创建的必须手动关闭,(调用的Session的close()方法)

注意:

(1).当使用本地事务(jdbc事务)时,需要在Hibernate.cfg.xml文件的<session-factory>节点中添加如下代码:

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

(2).当使用的是全局事务(JTA事务)时,需要在hibernate.cfg.xml文件的<session-factory>节点中添加如下代码:

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

如果使用getCurrentSession()方法,而没有在配置文件中添加以上的这些内容,那么编译不会报错,但是在运行程序时会出错,“No CurrentSessionContext configured!”,另外由于使用getCurrentSession()方法不需要手动关闭Session,所以不需要调用Session的close()方法。

3.3、Session的使用

3.3.1、save()方法

Session的Save()方法使一个自由对象(也称临时对象)转变为持久对象。调用Session的save()方法需要完成3件事:

1.把对象加入Session的缓存中,使它进入持久化状态。

2.选用映射文件指定的标识符生成器,为持久化对象分配唯一的OID.

3.计划执行一个insert语句,把对象当前的属性值装到insert语句中。

需要注意的是在save()方法后,在事务commit()方法之前,又修改了持久化对象的属性,哪个当session在清理的时候,会额外执行一个SQL update操作。

User user = new User();
user.setPassword("123");
user.serUsername("xiazhongwei");
Session session = sessionFactory.openSession();
Transaction tran = session.beanTransaction();
session.save(user);
user.setPassword("456");
tran.commit();
session.close();

  第一条:inser into USER (ID ,USERNAME,PASSWORD) values(1,"xiazhongwei","123");

第二条: update USER SET USERNAME="xiazhongwei",PASSWORD="456" where id=?

3.3.2、persist()方法

 persist()方法与save()方法作用类似,也能把一个自由对象转变为持久对象。

需要注意persist()方法是在hibernate3中才出现的它实现了EJB3规范中定义的持久化语义,当调用persist()方法时,并不一定会立即为持久化对象的OID赋值,而有可能在Session清理的时候才为oid赋值。另外咋事务边界以外调用persist()方法,这个方法不会计划执行一个insert语句。。

3.3.3、update()方法

执行session的update方法使一个游离的对象变为持久对象,并计划执行一条update语句。会完成一下操作:

1.把游离对象加入当前session的缓存中,使它变为持久化对象。

2.计划执行一条update语句。

3.Session只有在清理缓存的时候才会执行update语句,及使多次修改对象的数据也只会在清理缓存的时候执行一次update语句。

3.3.4、saveOrUpdate()方法

如果传入的是临时对象,就调用save()方法,如果传入的是游离对象,就调用update方法,而如果传入的是持久化对象就直接返回。

3.3.5、load()方法

方法是根据给定的OID从数据库中加载一个持久化对象。load()方法当数据库中不存在与oid对应的记录时,load()方法跑出org.hibernate.ObjectNotFoundException异常。

3.3.6、get()方法

get()方法和load()方法相似,都是使用oid检索持久化对象,get()方法当数据库中不存在与oid对应的记录时,get()方法返回null.

和load()方法的还有一个区别是两者采用了不同的检索策略,在默认情况下所有的持久化对象都使用延迟加载策略,<class name="com.entity.User" table="USER" lazy="true">如果不加lazy属性默认也是true,如果给lazy属性改为false那么load()方法就会立即加载。但是get()方法则忽略class元素的lazy属性,也就是说不管lazy属性写的什么值,get()方法都会采用立即加载的策略。

那么何时该使用load何时该使用get呢?

(1).如果加载一个对象的目的是为了访问它的各个属性,那么可以使用get()方法。

(2).如果加载一个对象是为了删除它或者简历与别的对象的关联关系,可以用load()方法。

3.3.7、delete()方法

delete()方法即可以删除持久对象,也可以删除游离对象,当调用delete()方法时,如果传入的参数是游离对象,会先使游离对象与当前session关联,使游离对象变为持久对象,,而如果参数传入的是持久对象的时候,则会忽略这一步。

delete()方法也是在session清理缓存的时候执行一条delete语句。

原文地址:https://www.cnblogs.com/ablejava/p/5720958.html