Hibernate框架(二)

一、持久化类

    1.持久化类的概述

        持久化:将内存中的一个对象持久化到数据库中的过程,Hibernate框架就是用来进行持久化的框架。

        持久化类:一个java对象与数据库的表建立的映射关系,那个这个类在Hibernate中成为持久化类。

                持久化类=java类+映射文件

    2.持久化类的编写规则

        (1)对持久化类提供一个无参构造方法

                        Hibernate底层需要使用反射生成实例。

        (2)属性需要私有,对私有属性提供public的get和set方法

                        Hibernate需要获取、设置对象的值。

        (3)对持久化类提供一个唯一标识OID与数据库主键对应

                        Java中通过对象的地址区分是否是同一个对象,数据库中通过主键确定是否是同一个记录,在Hibernate中通过持久化类的OID的属性区分是否是同一个对象。

        (4)持久化类中尽量使用包装类型

                        基本数据类型的默认值是0,会产生很多歧义。包装类类型默认值是null。

        (5)持久化类不要使用final修饰

                        延迟加载本身是Hibernate一个优化的手段,返回的是一个代理对象(javassist可以对没有实现接口的类产生代理----使用了非常底层的字节码增强技术,继承这个类进行代理)。如果不能被继承,就不能产生代理对象,延迟加载就会失效,load()方法和get()方法效果将一样。

二、主键

    1.主键的分类

        (1)自然主键

                自然主键,主键的本身就是一个字段(实体中的一个具体的属性)

        (2)代理主键

                代理主键,主键的本身不是表中的任一一个字段

        在实际开发中,应尽量使用代理主键。

        一旦自然主键参与到业务逻辑中,后期有可能需要修改源代码。

        好的程序设计应满足OCP原则,即对程序的拓展是open的,对修改源代码是close的。

    2.主键的生成策略

        在实际开发中一般不允许用户手动设置主键,一般将主键交给数据库,手动编写程序进行设置,在Hibernate中为了减少程序编写,提供了很多种主键的生成策略。

        increment:用于为long、short或者int类型生成唯一标识。在单线程中使用。

        sequence:用于为long、short或者int类型生成唯一标识。采用的是序列的方式(一些数据库比如Oracle支持,一些数据库比如MySQL不支持)

        identity:用于为long、short或者int类型生成唯一标识。使用的是数据库底层的自动增强机制,适用于有自动增强机制的数据库(MySQL、MS SQL Server等)。

        uuid:适用于字符串类型主键。使用Hibernate中的随机方式生成字符串主键。

        native:本地策略,可以在identity和sequence中自动切换。

        assigned:Hibernate放弃外键的管理,需要通过手动编写程序或者用户自己设置。

        foreign:外部的,一对一的一种关联映射的情况下使用。

		<!-- 建立类中的属性与表中的主键的联系 -->
		<id name="cust_id" column="cust_id">
			<generator class="native"/>
		</id>

三、持久化类的三种状态

    Hibernate是持久层框架,通过持久化类完成ORM操作。Hibernate为了更好的管理持久化类,将持久化类分为三种状态。

    1.瞬时态(transient)

        这种对象没有唯一的标识OID,没有被Session管理。数据库中没有对应的记录存在。

    2.持久态(persistent)

        这种对象有唯一标识OID,被Session管理。这时缓存中的对象与数据库是同步的。

        注意:该状态可以自动更新数据库。

    3.托管态(detached)

        这种对象有唯一标识OID,没有被Session管理。数据库中有数据,缓存中没有数据,因为数据库中有数据,所以它是可以再被持久化的.

	@Test
	public void fun4() {
		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();
		//瞬时态对象,没有唯一标识OID,没有被Session管理
		Customer customer=new Customer();
		customer.setCust_name("朱茵");
		//持久态对象,有唯一标识OID,被Session管理
		Serializable id = session.save(customer);
		Customer customer2 = session.get(Customer.class, id);
		System.out.println(customer2);
		transaction.commit();
		session.close();
		//托管态对象,有唯一标识OID,不被Session管理
		System.out.println(customer.getCust_name());
	}

四、Hibernate的缓存

    1.什么是缓存

        是一种优化的方式,将数据存入到内存中,使用的时候直接从内存中获取,不用通过存储源。

    2.Hibernate的一级缓存

        Hibernate的一级缓存就是指Session缓存,Session缓存是一块内存空间,用来存放相互管理的java对象,在使用Hibernate查询对象的时候,首先会使用对象属性的OID值在Hibernate的一级缓存中进行查找,如果找不到的时候,才会到数据库中查找相应的数据。Hibernate的一级缓存就是减少对数据库的访问次数

        一级缓存的特点:

            (1)当应用程序调用Session接口中的save()、update()、saveOrUpdate()时,如果Session缓存中没有相应的对象,Hibernate就会自动的把从数据库中查询出来的对象信息加入到一级缓存中。

            (2)当调用Session接口的load()、get()方法一级Query接口的list()、iterator()方法时,会判断缓存中是否存在该对象,有则返回,不会查询数据库,如果没有,再去数据库中查询相应对象,并添加到一级缓存中。

            (3)当调用Session接口的close()方法时,Session缓存会被清空。

五、Hibernate的事务管理

    1.什么是事务

        事务(Transaction)是指逻辑上的一组操作,组成这组操作的各个逻辑单元要么全部成功,要么全部失败。

    2.事务特性

        原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。

        一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。

        隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。

        持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

    3.事务隔离级别

        (1)事务的并发读问题

                脏读:读取到另一个事务未提交数据;

                不可重复读:两次读取不一致;

                幻读(虚读):读到另一事务已提交的数据。

      (2)四大隔离级别

        4个等级的事务隔离级别,在相同数据环境下,使用相同的输入,执行相同的工作,根据不同的隔离级别,可以导致不同的结果。不同事务隔离级别能够解决的数据并发问题的能力是不同的。

            1.SERIALIZABLE(串行化)

                    不会出现任何并发问题,因为它是对同一数据的访问是串行的,非并发访问的;

                    性能最差;

            2.REPEATABLE READ(可重复读)(MySQL)

                    防止脏读和不可重复读,不能处理幻读问题

                    性能比SERIALIZABLE好

            3.READ COMMITTED(读已提交数据)(Oracle)

                    防止脏读,没有处理不可重复读,也没有处理幻读;

                    性能比REPEATABLE READ好

            4.READ UNCOMMITTED(读未提交数据)

                    可能出现任何事务并发问题

                    性能最好

    4.Hibernate中设置事务隔离级别

        在hibernate.cfg.xml文件中的<session-factory>标签中,配置如下信息:

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

        该配置中的属性有如下值:

                1-----Read uncommitted isolation

                2-----Read committed isolation

                4-----Repeatable read isolation

                8----Serializable isolation

六、Hibernate线程绑定的Session

package cn.yfy.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtils {
	public static final Configuration configuration;
	public static final SessionFactory sessionFactory;
	static {
		configuration = new Configuration().configure();
		sessionFactory = configuration.buildSessionFactory();
	}
	//得到一个Session对象
	public static Session openSession() {
		return sessionFactory.openSession();
	}
	//得到当前线程的Session对象
	public static Session getCurrentSession(){
		return sessionFactory.getCurrentSession();
	}
}

        若要使用SessionFactory的getCurrentSession()对象,还需要在hibernate.cfg.xml中配置如下信息:

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

        该配置中的属性有如下值:

                thread-----对象的生命周期与本地线程绑定

                jta-----对象的生命周期与JTA事务绑定

                managed-----Hibernate委托程序来管理Session对象的生命周期

七、Hibernate的其他API

    1.Query

        Query接口用于接受HQL,查询多个对象。

        HQL:Hibernate Query Language:Hibernate查询语言,面向对象。

	@Test
	public void fun2() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// 查询Customer关联的表中的所有数据
		// String hql="from Customer";
		/**
		 * 通过Session获得Query接口 
		 * 条件查询 
		 * 设置参数
		 */
		// String hql="from Customer where cust_name like ?";
		// Query query = session.createQuery(hql);
		// query.setParameter(0, "刘%");

		/**
		 * 设置分页查询 
		 * 设置参数,两个参数分别为sql语句中的limit x,y
		 */
		String hql = "from Customer";
		Query query = session.createQuery(hql);
		query.setFirstResult(0);
		query.setMaxResults(3);
		List<Customer> list = query.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}
    2.Criteria

        OBC(Query By Criteria)

            更加面向对象的一种查询方式。

	@Test
	public void fun6() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		//通过Session获取Criteria对象
		Criteria criteria = session.createCriteria(Customer.class);
		//条件查询,条件为cust_name属性 模糊查询 "刘%"
		criteria.add(Restrictions.like("cust_name","刘%"));
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		transaction.commit();
	}
    3.SQLQuery

        SQLQuery用于接收SQL,一般在特别复杂的情况下使用SQLQuery。

猜你喜欢

转载自blog.csdn.net/fy_java1995/article/details/80536590