Hibernate五大关键接口

Hibernate五大关键接口

在Hibernate的API中有5个非常重要的接口:Configuration、SessionFactory、Session、Transaction和Query,它们是Hibernate组成的核心。

Configuration

负责Hibernate配置工作,创建SessionFactory对象,在Hibernate启动过程中,Configuration类的实例首先定位在映射文件位置,读取配置,然后创建SessionFactory对象。
##SessionFactory
SessionFactroy接口负责初始化Hibernate。它充当数据存储源的代理,使用工厂模式创建Session对象。需要注意的是SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。

Session

Session 接口对于Hibernate 开发人员来说是一个最重要的接口。在Hibernate中,实例化的Session是一个轻量级的类,创建和销毁它都不会占用很多资源。这在实际项目中非常很重要,因为在程序中,可能会不断地创建以及销毁Session对象,如果Session 的开销太大,会给系统带来不良影响。但是Session对象是非线程安全的,因此在你的设计中,最好是一个线程只创建一个Session对象。 Session可以看作介于数据连接与事务管理一种中间接口。我们可以将Session想象成一个持久对象的缓冲区,Hibernate能检测到这些持久对象的改变,并及时刷新数据库。我们有时也称Session是一个持久层管理器,因为Session负责执行被持久化对象的增、删、改、查操作,类似于JDBC的Connection和Statement, 诸如存储持久对象至数据库,以及从数据库从获得它们。需要注意的是,Hibernate的Session不同于JSP 应用中的HttpSession。在Hibernate中,我们使用Session这个术语时,指的是Hibernate 自己的Session。

Transaction

负责事务相关的操作,它代表的是Hibernate事务,本质上也是数据库事务。一般在Hibernate的增删改中出现,但是使用Hibernate一般使用Spring去管理事务。

Query

负责执行各种数据查询功能,它可以使用Hibernate特有的HQL语言和SQL语言两种方式。

*.hbm.xml基本配置

Hibernate的基本映射信息的配置文件,也就是系统中每一个类与其对应的数据库表之间
的关联信息,这种配置文件一般命名为:类名.hbm.xml,下面我们通过一个具体的代码示例来看一下类名.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">
<!-- package声明POJO类所在的包,如果不写那么在class中需要填写POJO类的完全限定名 -->
<hibernate-mapping>
<!--
class指一个POJO类
该类必须提供公共的无参构造方法-通过反射产生对象
属性用private修饰,并且生成对应的get/set方法
类不能用final来修饰-hibernate需要产生代理类(cglib),否则出错
name表示POJO类名或者完全限定名
table可选,表示POJO类对应数据库中的表名;如果不写默认是类名
-->
<class name="cn.hibernate.pojo.User" table="user">
<!--
id对应数据库表中的主键
name指实体类的标识属性名
column表示对应数据库表的列名,如果不写则数据库中列名和属性名一致
length表示数据库表中对应数据类型的长度,如果不写有默认长度
type表示类型,如果不写hibernate可以找到对应pojo类的属性的类型
-->
<id name="id">
<!--
主键生成策略
increment:用于为long,short或者int类型生成唯一标识,
只有在没有其他进程往同一张表中插入数据时才能使用.在集群下不要使用
identity:对DB2,MySQL, MS SQL Server, Sybase
和HypersonicSQL的内置标识字段提供支持。
返回的标识符是long, short或者int类型的。
sequence:在支持序列的数据库中使用(oracle),
返回的标识符是long, short或者int类型的。
<generator class="sequence">
<param name="sequence">user_sequence</param>
</generator>
uuid:UUID被编码为一个3216进行数字的字符串.
native:根据底层数据库的能力选择identity,sequence 或者hilo中的一个.
assigned:自己指定主键.
-->
<generator class="native"></generator>
</id>
<!--
实体类的属性
name:指明POJO类属性名称(区分大小写)column:表示对应数据库表的列名,如果不写则数据库中列名和属性名一致
两种写法效果一致.
-->
<property name="username">
<column name="username"></column>
</property>
<property name="password"/>
</class>
</hibernate-mapping>

Hibernate对象生命周期

Hibernate中对象有三种状态: 瞬时状态(Transient)、持久状态(Persistent)、游离状(Detached)。

  • 瞬时状态:刚刚使用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的Java对象被称为临时对象。Session中没有,数据库中没有。
  • 持久化状态:已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象被称为持久化对象。Session中有,数据库中有。
  • 游离状态:已经被持久化,但不处于Session的缓存中。处于游离状态的Java对象被称为游离对象。Session中没有,数据库中有

##对象状态转换相关方法

  1. 瞬时状态转为持久状态
    使用Session对象的save()或saveOrUpdate()方法保存对象后,该对象的状态由瞬时状态转换为持久状态。使用Session对象的get()或load()方法获取对象,该对象的状态是持久状态。
  2. 持久状态转为瞬时状态
    执行Session对象的delete()方法后,对象由原来的持久状态变为瞬时状态,因为此时该对象没有任何的数据库数据关联。
  3. 持久状态转为游离状态
    执行了Session对象的evict()、clear()或close()方法,对象由原来的持久状态转为游离状态。
  4. 游离状态转为持久状态
    重新获取Session对象,执行Session对象的update()或saveOrUpdate()方法,对象由游离状态转为持久状态,该对象再次与Session对象相关联。
  5. 游离状态转为瞬时状态
    执行Session对象的delete()方法,对象由游离状态转为瞬时状态。处于瞬时状态或游离状态的对象不再被其他对象引用时,会被Java虚拟机按照垃圾回收机制处理。
    ##封装一个可重复调用的HibernateUtil.java工具类
public class HibernateUtil {

    private static final ThreadLocal<Session> THREAD_LOCAL = new ThreadLocal<Session>();
    private static SessionFactory sessionFactory = null;
    private static StandardServiceRegistry serviceRegistry = null;

    // 通过静态块初始化对象
    static{
        try {
            serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
            sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
        }catch (Exception e ){
            System.out.println("创建SessionFactory失败");
            e.printStackTrace();
        }
    }

    // 获取session
    public static Session getSession(){
        Session session = THREAD_LOCAL.get();

        if (null == session || !session.isOpen()){
            if (null ==sessionFactory){
                rebuildSessionFactoty();
            }

            session = (null != sessionFactory) ? sessionFactory.openSession() : null;
            THREAD_LOCAL.set(session);
        }
        return session;
    }

    // 初始化SessionFactory
    public static  void rebuildSessionFactoty(){
        try {
            serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
            sessionFactory = new MetadataSources(serviceRegistry)
                    .buildMetadata().buildSessionFactory();
        } catch (Exception e) {
            System.out.println("创建SessionFactory失败");
            e.printStackTrace();
        }
    }

    // 关闭session
    public static void closeSession(){
        Session session = THREAD_LOCAL.get();
        THREAD_LOCAL.set(null);

        if (null != session && session.isOpen()){
            session.close();
        }
    }
}

new -> save -> close -> update

@Test
public void testSave() {
	Session session = null;
	Transaction tx = null;
	User user = null;
	try {
		session = HibernateUtil.getSession();
		tx = session.beginTransaction();
		// 构造对象 -> 瞬时状态,session中没有,数据库中没有
		user = new User();
		user.setUsername("刘德华");
		user.setPassword("123");
		// 调用save() -> 持久状态,user被session管理,session中有,数据库中有
		session.save(user);
		/*
		* 在持久状态下,脏数据检查:当提交事务时或清理缓存时,发现session中的数据和
		* 数据库中的数据不一致时,将会把session中的数据更新到数据库中
		*/
		user.setUsername("张学友");
		// 在保存以后再修改对象将会产生多条sql语句,效率较低,建议在save前修改
		session.flush();
		tx.commit();
	} catch (Exception e) {
		e.printStackTrace();get/load -> clear/evict
		tx.rollback();
	} finally {
		HibernateUtil.closeSession();
	}
		// session被关闭 -> 游离状态,session中没有,数据库中有
		System.out.println("姓名:" + user.getUsername());
		user.setUsername("梁朝伟");
	try {
		session = HibernateUtil.getSession();
		tx = session.beginTransaction();
		// 调用update() -> 持久状态,user被session管理,session中有,数据库中有
		// 如果此时先get()|load()获取到user -> 持久状态,session中有,数据库中有
		// 再调用delete() -> 瞬时状态,sesison中没有,数据库中没有
		session.update(user);
		tx.commit();
	} catch (Exception e) {
		e.printStackTrace();
		tx.rollback();
	} finally {
		HibernateUtil.closeSession();
	} 
	// 游离状态
}

get/load -> clear/evict

@Test
public void testGet1() {
		Session session = null;
		Transaction tr = null;
		User user = null;
	try {
		session = HibernateUtil.getSession();
		tr = session.beginTransaction();
		// get() -> 持久状态,user被session管理,session中有,数据库中有
		// get()会立即查询该对象:范围从session,SessionFactory,数据库
		user = (User) session.get(User.class, 1);
		System.out.println("姓名:" + user.getUsername());
		tr.commit();
		// clear()清除session缓存中所有对象,evict()清除指定对象
		session.clear();
		// session.evict(user);
		// clear()|evict() -> 游离状态,不被session管理,数据库中不会被更改
		user.setUsername("张国荣");
		System.out.println(user.getUsername());
	} catch (Exception e) {
		e.printStackTrace();
		tr.rollback();
	} finally {
		HibernateUtil.closeSession();
	}
	/*get/load的区别:get会立即去查询对象,load在使用才去查询(懒加载),get找不到对象时返回null,load找不到对象时抛异常。*/

} 
@Test
public void testGet2() {
		Session session = null;
		Transaction tr = null;
		User user = null;
	try {
		session = HibernateUtil.getSession();
		tr = session.beginTransaction();
		// get() -> 持久状态,user被session管理,session中有,数据库中有
		// get()会立即查询该对象:范围从session,SessionFactory,数据库
		// get()如果找不到对象不会抛异常,返回null
		user = (User) session.get(User.class, 10);
		System.out.println("姓名:" + user.getUsername());
		tr.commit();
	} catch (Exception e) {
		e.printStackTrace();
		tr.rollback();
	} finally {
		HibernateUtil.closeSession();
	}
} 
@Test
public void testLoad() {
		Session session = null;
		Transaction tr = null;
		User user = null;
	try {
		session = HibernateUtil.getSession();
		tr = session.beginTransaction();
		// load() -> 持久状态
		// load()不会立即去查询对象,到使用时才会查询(懒加载):范围从session,SessionFactory,数
		//据库
		// load()当对象不存在时会抛出org.hibernate.ObjectNotFoundException异常
		user = (User) session.load(User.class, 10);
		System.out.println("姓名:" + user.getUsername());
		tr.commit();
	} catch (Exception e) {
		e.printStackTrace();
		tr.rollback();
	} finally {
		HibernateUtil.closeSession();
	}
}

get/load的区别:get会立即去查询对象,load在使用才去查询(懒加载),get找不到对象时返回null,load找不到对象时抛异常。

update

@Test
public void testUpdate() {
	Session session = null;
	Transaction tr = null;
	User user = null;
	try {
		session = HibernateUtil.getSession();
		tr = session.beginTransaction();
		// 手动构造的瞬时状态对象也可以修改,但是需要指定所有属性,不建议使用
		//user = new User();
		//user.setId(3);
		//user.setUsername("李四");
		// get() -> 持久状态,user被session管理,session中有,数据库中有
		user = (User) session.get(User.class, 2);
		// 通过从数据库中加载该对象然后再修改可以进行判断进而避免异常,提高程序的健壮性
		if (null != user) {
		user.setUsername("老王");
		// update() -> 持久状态,user被session管理,session中有,数据库中有
		session.update(user);
	} 
		tr.commit();
	} catch (Exception e) {
		e.printStackTrace();
		tr.rollback();
	} finally {
		HibernateUtil.closeSession();
	}
}

注意:先获取对象进行判断再更新,可以避免异常,提高程序的健壮性

delete

@Test
public void testDelete() {
	Session session = null;
	Transaction tr = null;
	User user = null;
	try {
		session = HibernateUtil.getSession();
		tr = session.beginTransaction();
		// 手动构造的瞬时状态对象,指定主键也是可以删除该对象的,但是不建议这么用
		//user = new User();
		//user.setId(5);
		// get() -> 持久状态,user被session管理,session中有,数据库中有
		user = (User) session.get(User.class, 10);
		// 通过从数据库中加载该对象然后删除可以进行判断进而避免异常,提高程序的健壮性
		if (null != user) {State Mem Session DB
		// delete() -> 瞬时状态,session中没有,数据库中没有
		session.delete(user);
	}
		tr.commit();
	} catch (Exception e) {
		e.printStackTrace();
		tr.rollback();
	} finally {
		HibernateUtil.closeSession();
	}
}

注意:先获取对象进行判断再删除,可以避免异常,提高程序的健壮性。

对象三种状态的比较

StateMemorySessionDB
Transientynn
Persistentyyy
Detachedyny
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值