Hibernate总结

                                                                         Hibernate总结

一、ORM(Object Relation Mapping):对象关系映射,是一种程序技术

一、Hibernate是一种对象关系映射框架

JNDI:

JNDI(Java Naming and Directory Interface,Java命名和目录接口 )提供了一种统一的方式,可以用在网络上查找和访问服务。通过指定一个资源名称,该名称对应于数据库或命名服务中的一个记录,同时返回数据库连接建立所必须的信息。
JNDI主要有两部分组成:应用程序编程接口和服务供应商接口。应用程序编程接口提供了Java应用程序访问各种命名和目录服务的功能,服务供应商接口提供了任意一种服务的供应商使用的功能。
 
JDBC:
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序

3.3 分水岭 :3.3之前需要单独引入Annotationjar

 

JPA 是在HIbernate作者参与的情况下完成的一个规范。

 

JPA是一个标准,可以看成是一个接口,旗下统领着N多个具体框架。

 

hibernate的基本特征是完全面向对象的程序设计语言到关系数据库的 映射,

在Hibernate中使用持久化对象PO(Persistent Object)完成持久化操作,对PO的操作必须在Session管理下才能同步到数据库,

但是这里的Session并非指HttpSession,可以 理解为基于JDBC的Connnection,

Session是Hibernate运作的中心,对象的生命周期、事务的管理、数据库的存取都与 Session息息相关,

首先,我们需要知道,SessionFactory负责创建Session,SessionFactory是线程安全的,多个并 发线程可以同时访问一个SessionFactory 并从中获取Session实例。

而Session并非线程安全,也就是说,如果多个线程同时使用一个Session实例进行数据存取,则将会导致 Session 数据存取逻辑混乱.

因此创建的Session实例必须在本地存取空上运行,使之总与当前的线程相关。 这里就需要用到ThreadLocal,在很多种Session 管理方案中都用到了它.

ThreadLocal 是Java中 一种较为特殊的线程绑定机制通过ThreadLocal存取的数据,总是与当前线程相关,也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间

从而为多线程环境常出现的并发访问问题提供了一种隔离机制,ThreadLocal并不是线程本地化的 实现,而是线程局部变量。

也就是说每个使用该变量的线程都必须为该变量提供一个副本,每个线程改变该变量的值仅仅是改变该副本的值,而不会影响其他线程的 该变量的值,ThreadLocal是隔离多个线程的数据共享,

不存在多个线程之间共享资源,因此不再需要对线程同步。

 

二、关于Hibernate中session的线程安全问题

 session在多线程下不安全,当两个应用程序拿到同一个session对象时,就会出现脏读和死锁问题

解答:Hibernate中用openSession()打开的session是线程不安全的

   Hibernate中用getCurrentSession()打开的是一个线程安全的,是获取与当前线程绑定的一个session

Hibernate中两个缓存,
sessionFactory是重量级的,线程安全,也叫一级缓存
session是轻量级的,线程不安全,也叫二级缓存

Session的使用原则就是一个线程一个session,session一次一个事务
解决session线程不安全的二种解决方案:
1.通过Threadlocal类可以把session绑定在当前线程上,


2.也可以直接通过hbm配置文件设定current_session_context_class-thread
  然后通过SessionFactory.getCurrentSession()获得

以上两种解决方案有一点不同,就是用第二种方式时,当我们的事物提交后,session会自动关闭,而用第一种方式需要我们手动关session

 

 

 

 SessionFactory:线程安全,保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。在SessionFactory中内置了连接池。其有两个常用方法:

 

 openSession()  --从连接池中随机获取一个连接

 

 getCurrentSession()  --SessionThreadLocal绑定,确保在一次请求中,

 

只有一个Session对象。

 

   通常一个应用只会初始化一个SessionFactory(代表一个连接池)

 

1getCurrentSession()openSession()的区别?

 

* 采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()创建的session则不会

 

* 采用getCurrentSession()创建的sessioncommitrollback时会自动关闭,而采用openSession()创建的session必须手动关闭

 

2、使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置:

 

* 如果使用的是本地事务(jdbc事务)

 

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

 

* 如果使用的是全局事务(jta事务)

 

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

 

Creates Sessions. Usually an application has a single SessionFactory. Threads servicing client requests obtain Sessions from the factory.
Implementors must be threadsafe.
SessionFactorys are immutable. The behaviour of a SessionFactory is controlled by properties supplied at configuration time. These properties are defined on Environment.

 

 

对比ThreadLocalsynchronized同步机制

相同点:

        1ThreadLocal和线程同步机制都能解决多线程中相同变量的访问冲突问题。

不同点:

       1、适用的情况不同

        在同步机制中,使用同步保证同一时间只有一个线程访问,不能同时访问共享资源,否则就是出现错误。ThreadLocal则隔离了相关的资源,并在同一个线程中可以共享这个资源。彼此独立,修改不会影 响到对方。

       2、最终实现的效果不同

       对于多线程资源共享问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

 

4.Transaction 代表事务

commit(); 提交事务,rollback();  回滚事务
 如果没有开启事务,那么每个Session的操作,都相当于一个独立的事务

 

 

关于loadget方法区别的说明:

 

Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象。

 

其区别在于:

如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObjectNotFoundException

Load方法可返回实体的代理类实例,而get方法永远直接返回实体类。

 

/** *//**
  * get()方法的执行顺序如下:
  * a):首先通过idsession缓存中查找对象,如果存在此id的对象,直接将其返回
  * b):在二级缓存中查找,找到后将 其返回。
  * c):如果在session缓存和二级缓存中都找不到此对象,则从数据库中加载有此ID的对象
  * 因此get()方法并不总是导致SQL语句,只有缓存中无此数据时,才向数据库发送SQL 
  */

 

 /** *//**
  * get()的区别:
  * 1:在立即加载对象(当hibernate在从数据库中取得数据组装好一个对象后
  * 会立即再从数据库取得数据此对象所关联的对象)时,如果对象存在,
  * load()get()方法没有区别,都可以取得已初始化的对象;但如果当对
  * 象不存在且是立即加载时,使用get()方法则返回null,而使用load()
  * 抛出一个异常。因此使用load()方法时,要确认查询的主键ID一定是存在
  * 的,从这一点讲它没有get方便!
  * 2:在延迟加载对象(Hibernate从数据库中取得数据组装好一个对象后,
  * 不会立即再从数据库取得数据组装此对象所关联的对象,而是等到需要时,
  * 都会从数据库取得数据组装此对象关联的对象)时,get()方法仍然使用
  * 立即加载的方式发送SQL语句,并得到已初始化的对象,而load()方法则
  * 根本不发送SQL语句,它返回一个代理对象,直到这个对象被访问时才被
  * 初始化。
  */

 

1. Hibernate 的检索方式有哪些?

  ① 导航对象图检索  
  ② OID检索  
  ③ HQL检索  
  ④ QBC检索  
  ⑤ 本地SQL检索

 

 

posted @ 2016-08-25 16:31  回青  阅读(257)  评论(0编辑  收藏  举报