Hibernate学习笔记总结(一)——Hibernate 3.x 基础

来源:互联网 发布:安卓排雷软件 编辑:程序博客网 时间:2024/06/18 00:07

Hibernate  3.x  基础

 

本文摘自王勇老师的学习笔记,感觉很不错,很全面!


Hibernate出现的原因

直接使用JDBC操作数据库的步骤很繁琐;

JDBC操作的是关系型数据库;

我们用JAVA开发程序,则使用面向对象的思想;

Hibernate正是在这两种不同的模型之间建立关联,Hibernate给我们提供了利用面向对象的思想来操作关系型数据的接口。

 

关系模型(Relational Model)

关系模型把世界看作是由实体(Entity)和联系(Relationship)构成的。

所谓实体就是指现实世界中具有区分与其它事物的特征或属性并与其它实体有联系的对象。在关系模型中实体通常是以表的形式来表现的。表的每一行描述实体的一个实例,表的每一列描述实体的一个特征或属性。

所谓联系就是指实体之间的关系,即实体之间的对应关系。

1:1

1:n

m:n

关系数据库

  字段  主键  外键

 

面向对象三大特征:封装、继承(一般与特殊)、多态(覆盖与重载)

  对象  属性  关系

 

一般与特殊关系(is a)

组成(hasa)

关联及其多重性

1:1

1:n

m:n

双向关联与单向关联

 

对象关系映射(Object Relational Mapping,简称ORM)

ORM是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。

什么是 ORM?

面向对象的开发方法是当今企业级应用开发环境中的主流开发方法

关系数据库是企业级应用环境中永久存放数据的主流数据存储系统

字母O起源于“对象”(Object),而R则来自于“关系”(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和表现层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。

当你开发一个应用程序的时候(不使用O/RMapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息等等。而这些代码写起来总是重复的。

 

对象-关系映射模式

属性映射  类映射  关联映射

一对一  一对多  多对多

 

Hibernate

    对象/关系映射一直都是数据库技术中的难点,尽管人们提出了许多方案解决这个问题,但都不能完全做到即便利又高效。EJB的推出让人们看到了希望,但实践证明实体Bean的效率并不高,并且还十分难于被初学者理解。由Gavin King创建的Hibernate框架,从某种程序上正在朝着正确的方向迈进,并且得到越来越多IT从业人员的认可。就像当年的Struts框架一样,Hibernate也已经在许多项目中得到广泛应用。Hibernate由于投注了更多的精力在提升效率上,使用起来又十分方便,新版的EJB规范正在向Hibernate方向靠拢。正是由于得到广泛的认可,Hibernate已经成为程序员必须掌握的技术之一。

 

Hibernate能帮助我们利用面向对象的思想,开发基于关系型数据库的应用程序

第一:将对象数据保存到数据库

第二:将数据库数据读入对象中

基于B/S的典型三层架构




 

 

 


 

Hibernate的基本组件

实体类   实体类映射文件

重点学习的部分

Hibernate配置文件

辅助工具

 

Hibernate核心接口:




 

 

 

Configuration

概述:

    Configuration 类负责管理Hibernate 的配置信息,即加载Hibernate配置文件(hibernate.cfg.xml)。它包括如下内容:

Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(hibernate.cfg.xml )。

Hibernate映射文件(*.hbm.xml)。

Hibernate配置的两种方法:

属性文件(hibernate.properties)

       调用代码:Configuration cfg = newConfiguration();

XML文件(hibernate.cfg.xml)

      调用代码:Configuration cfg = new Configuration().configure();

 

SessionFactory(会话工厂)

概述:

    它与数据库绑定,一个数据库对应一个SessionFactory,关于数据库中的所有东西(例如:表之间的关联)都放在SessionFactory中了,二级缓存与SessionFactory相关,二级缓存就是进程级的缓存,就相当于Web中的Application对象,因此它是重量级的,它的创建时间比较耗时,所以该对象只创建一个,不要频繁创建。

    应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。它在多个应用线程间进行共享。通常情况下,整个应用只有唯一的一个会话工厂——例如在应用初始化时被创建。然而,如果你使用Hibernate访问多个数据库,你需要对每一个数据库使用不同的会话工厂(即:需要为每个数据库都创建一个会话工厂)。

    会话工厂缓存了生成的SQL语句和Hibernate在运行时使用的映射元数据。

调用代码:

       SessionFactorysessionFactory = cfg.buildSessionFactory();

说明:SessionFactory由Configuration对象创建,所以每个Hibernate配置文件,实际上是对SessionFactory的配置。

 

Session(会话)

概述:

    它是操纵Hibernate进行CRUD(增、删、改、查)操作的,即Hibernate在进行CRUD操作时必须使用Session,Session不同于JDBC中的Connection。也可以这样理解Session对Connection又进行了一层包装,打开一个Session并不等于打开一个Connection,因为Session的功能要比Connection强,Session不仅具有Connection的功能,还具有管理一级缓存的功能,例如:在Hibernate中保存一个对象,Hibernate要完成两个功能,一是发出相应的SQL语句将数据存储到数据库表中,另一个功能是把当前这个对象放入到缓存中。

Session不是线程安全的,它代表与数据库之间的一次操作,它的概念介于Connection和Transaction之间,由于不是线程安全的,所以不能多线程共享使用,否则会产生莫明其妙的问题,Session通常是一个业务请求过来,就open出一个Session,业务请求完毕后Session随之关闭,通常是Session关闭后,与该Session对应的事务就关闭了,即一个业务请求对应一个事务。

Session也称为持久化管理器,因为它是与持久化有关的操作接口。

Session通过SessionFactory打开,在所有的工作完成后,需要关闭。

它与Web层的HttpSession没有任何关系。

 调用代码

      Session session= sessionFactory.openSession();

 

持久化对象的状态

瞬时对象(Transient Objects)

    使用new 操作符初始化的对象不是立刻就持久的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回收。特点是:数据库中没有与之对应的记录。

持久化对象(Persist Objects)

    持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的——它们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。特点是:数据库中有与之对应的记录,同时session中也有该记录对应的对象存在,即受session管理。

离线对象(Detached Objects)

    Session关闭之后,持久化对象就变为离线对象。离线表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理。特点是:数据库中有与之对应的记录,同时session中没有该记录对应的对象存在,即不受session管理。

 

持久化对象的生命周期(lifecycle)

 


  

 

 

Transaction(事务)

概述:

    它将应用代码从底层的事务实现中抽象出来——这可能是一个JDBC事务,一个JTA用户事务或者甚至是一个公共对象请求代理结构(CORBA)——允许应用通过一组一致的API控制事务边界。这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性。

调用代码:

    Transaction tx =session.beginTransaction();

 注:使用Hibernate进行操作时必须显式的调用Transaction(默认:autoCommit=false)。

 

Query接口

概述:

    Query(查询)接口允许你在数据库上执行查询并控制查询如何执行。查询语句使用HQL或者本地数据库的SQL方言编写。

调用代码:

    Query query =session.createQuery("from User");

注意:

    在Hibernate 3.x中不建议使用如下包中的类:

      org.hibernate.classsic.*

    这个包下面的类,是Hibernate 3.x为了向下兼容Hibernate 2.x才保留下来的。

Hibernate的对象关系映射

映射文件的基本结构举例

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

       "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

       "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <classname="com.domain.User">

        <idname="id">

           

        </id>

        <property name="name"/>

       

   </class>

</hibernate-mapping>

 

hibernate-mapping元素:

可以包含的子元素

class –描述被映射的类

subclass/joined-subclass– 在继承关系的映射中会用到

query –将查询语句定义在配置文件中

 

class元素:

常用属性

name – 实体类的类名

table –被映射到数据库表的名称

可以包含的常见子元素

id – 主键定义

property– 属性定义

关系映射定义(一对多、多对一等)

 

主键 - id:

被映射的类必须要有一个id定义

通常使用逻辑主键

逻辑主键:没有意义的唯一标识符

业务主键:有意义的唯一标识符

Hibernate使用generator类来生成主键

Hibernate自带了很多generator(不同的主键生成策略)

int/long– native

String- uuid

我们也可以定义自己的generator,实现IdentifierGenerator接口,一般情况下不需要实现自己的generator。

 

主键生成策略generator

generator  主键生成器,每个主键都必须定义相应的主键生成策略。它用来为持久化类实例生成唯一的标识。

Hibernate内置的主键生成策略

数据库提供的主键生成机制。identity、sequence(序列)。

外部程序提供的主键生成机制。increment(递增)(这种策略在做集群时,不应该使用,因为该策略是在同一个JVM中是唯一的) ,hilo(高低位) ,seqhilo(使用序列的高低位 ),uuid.hex(使用了IP地址+JVM的启动时间(精确到1/4秒)+系统时间+一个计数器值(在JVM中唯一)),uuid.string。

其它:native(本地),assigned(手工指定),foreign(外部引用)。

 

普通属性映射 - property:

<property name="property_name"/>

可使用的常见属性如下:

name – 对应类的属性名称

type – 指定属性的类型,一般情况下可以不用指定,由hibernate自动匹配(可参考文档中的有关说明)

length –指定长度

column –指定属性所对应的数据库字段的名称,如果不指定,就是属性的名称

 

实体类的设计原则:

实现一个默认的(即无参数)构造方法。

提供一个标识属性(即id,当然也可以用别的名称,它一般和业务无关),这个属性就是与数据库中的主键字段对应的。

使用非final类型的类,即实体类最好不定义成final类型的,否则在使用时,有时Hibernate会抛出异常。

为实体类的中属性提供setter/getter方法,属性的访问控制符可以是private,但是其对应的setter/getter方法的访问控制符一般为public。