Hibernate学习

1. Hibernate简介

简介

下载地址:http://hibernate.org/orm/releases/

Hibernate 是由 Gavin King 2001 年创建的开放源代码的对象关系框架。它强大且高效的构建具有关系对象持久性和查询服务的 Java 应用程序。

Hibernate Java 类映射到数据库表中,从 Java 数据类型中映射到 SQL 数据类型中,并把开发人员从 95% 的公共数据持续性编程工作中解放出来。

Hibernate 是传统 Java 对象和数据库服务器之间的桥梁,用来处理基于 O/R 映射机制和模式的那些对象。

 

 

Hibernate 优势

l Hibernate 使用 XML 文件来处理映射 Java 类别到数据库表格中,并且不用编写任何代码。

为在数据库中直接储存和检索 Java 对象提供简单的 APIs

如果在数据库中或任何其它表格中出现变化,那么仅需要改变 XML 文件属性。

抽象不熟悉的 SQL 类型,并为我们提供工作中所熟悉的 Java 对象。

l Hibernate 不需要应用程序服务器来操作。

操控你数据库中对象复杂的关联。

最小化与访问数据库的智能提取策略。

提供简单的数据询问。

2. Hibernate架构

架构

Hibernate 架构是分层的,作为数据访问层,不必知道底层 API Hibernate 利用数据库以及配置数据来为应用程序提供持续性服务(以及持续性对象)。

下面是一个非常高水平的 Hibernate 应用程序架构视图。

 

下面是一个详细的 Hibernate 应用程序体系结构视图以及一些重要的类。

 

Hibernate 使用不同的现存 Java API,比如 JDBCJava 事务 APIJTA),以及 Java 命名和目录界面(JNDI)。JDBC 提供了一个基本的抽象级别的通用关系数据库的功能, Hibernate 支持几乎所有带有 JDBC 驱动的数据库。JNDI JTA 允许 Hibernate J2EE 应用程序服务器相集成。

Hibernate 应用程序架构所涉及的类对象

 

配置对象

配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造。它代表了 Hibernate 所需一个配置或属性文件。配置对象提供了两种基础组件。

数据库连接:由 Hibernate 支持的一个或多个配置文件处理。这些文件是 hibernate.properties hibernate.cfg.xml

类映射设置:这个组件创造了 Java 类和数据库表格之间的联系。

 

SessionFactory 对象

配置对象被用于创造一个 SessionFactory 对象,使用提供的配置文件为应用程序依次配置 Hibernate,并允许实例化一个会话对象。SessionFactory 是一个线程安全对象并由应用程序所有的线程所使用。

SessionFactory 是一个重量级对象所以通常它都是在应用程序启动时创造然后留存为以后使用。每个数据库需要一个 SessionFactory 对象使用一个单独的配置文件。所以如果你使用多种数据库那么你要创造多种 SessionFactory 对象。

 

Session 对象

一个会话被用于与数据库的物理连接。Session 对象是轻量级的,并被设计为每次实例化都需要与数据库的交互。持久对象通过 Session 对象保存和检索。

Session 对象不应该长时间保持开启状态因为它们通常情况下并非线程安全,并且它们应该按照所需创造和销毁。

 

Transaction 对象

一个事务代表了与数据库工作的一个单元并且大部分 RDBMS 支持事务功能。在 Hibernate 中事务由底层事务管理器和事务(来自 JDBC 或者 JTA)处理。

这是一个选择性对象,Hibernate 应用程序可能不选择使用这个接口,而是在自己应用程序代码中管理事务。

 

Query 对象

Query 对象使用 SQL 或者 Hibernate 查询语言(HQL)字符串在数据库中来检索数据并创造对象。一个查询的实例被用于连结查询参数,限制由查询返回的结果数量,并最终执行查询。

 

Criteria 对象

Criteria 对象被用于创造和执行面向规则查询的对象来检索对象。

3. Hibernate配置

Hibernate 需要事先知道在哪里找到映射信息,这些映射信息定义了 Java 类怎样关联到数据库表。Hibernate 也需要一套相关数据库和其它相关参数的配置设置。所有这些信息通常是作为一个标准的 Java 属性文件提供的,名叫 hibernate.properties。又或者是作为 XML 文件提供的,名叫 hibernate.cfg.xml

我们将考虑 hibernate.cfg.xml 这个 XML 格式文件,来决定在我的例子里指定需要的 Hibernate 应用属性。这个 XML 文件中大多数的属性是不需要修改的。这个文件保存在应用程序的类路径的根目录里。

属性

S.N.

属性和描述

1

hibernate.dialect 
这个属性使 Hibernate 应用为被选择的数据库生成适当的 SQL

2

hibernate.connection.driver_class
JDBC 驱动程序类。

3

hibernate.connection.url 
数据库实例的 JDBC URL

4

hibernate.connection.username
数据库用户名。

5

hibernate.connection.password 
数据库密码。

6

hibernate.connection.pool_size 
限制在 Hibernate 应用数据库连接池中连接的数量。

7

hibernate.connection.autocommit 
允许在 JDBC 连接中使用自动提交模式。

在使用 JNDI 和数据库应用程序服务器然后您必须配置以下属性:

S.N.

属性和描述

1

hibernate.connection.datasource 
在应用程序服务器环境中您正在使用的应用程序 JNDI 名。

2

hibernate.jndi.class 
JNDI InitialContext 类。

3

hibernate.jndi.<JNDIpropertyname> 
JNDIInitialContext 类中通过任何你想要的 Java 命名和目录接口属性。

4

hibernate.jndi.url 
JNDI 提供 URL

5

hibernate.connection.username 
数据库用户名。

6

hibernate.connection.password 
数据库密码。

hibernate.dialect属性对应数据库方言:

数据库

方言属性

DB2

org.hibernate.dialect.DB2Dialect

HSQLDB

org.hibernate.dialect.HSQLDialect

HypersonicSQL

org.hibernate.dialect.HSQLDialect

Informix

org.hibernate.dialect.InformixDialect

Ingres

org.hibernate.dialect.IngresDialect

Interbase

org.hibernate.dialect.InterbaseDialect

Microsoft SQL Server 2000

org.hibernate.dialect.SQLServerDialect

Microsoft SQL Server 2005

org.hibernate.dialect.SQLServer2005Dialect

Microsoft SQL Server 2008

org.hibernate.dialect.SQLServer2008Dialect

MySQL

org.hibernate.dialect.MySQLDialect

Oracle (any version)

org.hibernate.dialect.OracleDialect

Oracle 11g

org.hibernate.dialect.Oracle10gDialect

Oracle 10g

org.hibernate.dialect.Oracle10gDialect

Oracle 9i

org.hibernate.dialect.Oracle9iDialect

PostgreSQL

org.hibernate.dialect.PostgreSQLDialect

Progress

org.hibernate.dialect.ProgressDialect

SAP DB

org.hibernate.dialect.SAPDBDialect

Sybase

org.hibernate.dialect.SybaseDialect

Sybase Anywhere

org.hibernate.dialect.SybaseAnywhereDialec

hibernate.cfg.xml解析:

<?xml version="1.0" encoding="GBK"?>  

<!-- 指定Hibernate配置文件的DTD信息 -->  

<!DOCTYPE hibernate-configuration PUBLIC  

    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  

    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">  

<!-- hibernate- configuration是连接配置文件的根元素 -->  

<hibernate-configuration>  

    <session-factory>  

        <!-- 指定连接数据库所用的驱动 -->  

        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>  

        <!-- 指定连接数据库的urlhibernate连接的数据库名 -->  

        <property name="connection.url">jdbc:mysql://localhost/数据库名</property>  

        <!-- 指定连接数据库的用户名 -->  

        <property name="connection.username">root</property>  

        <!-- 指定连接数据库的密码 -->  

        <property name="connection.password">32147</property>  

        <!-- 指定连接池里最大连接数 -->  

        <property name="hibernate.c3p0.max_size">20</property>  

        <!-- 指定连接池里最小连接数 -->  

        <property name="hibernate.c3p0.min_size">1</property>  

        <!-- 指定连接池里连接的超时时长 -->  

        <property name="hibernate.c3p0.timeout">5000</property>  

        <!-- 指定连接池里最大缓存多少个Statement对象 -->  

        <property name="hibernate.c3p0.max_statements">100</property>  

        <property name="hibernate.c3p0.idle_test_period">3000</property>  

        <property name="hibernate.c3p0.acquire_increment">2</property>  

        <property name="hibernate.c3p0.validate">true</property>  

        <!-- 指定数据库方言 -->  

        <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>  

        <!-- 根据需要自动创建数据表 -->  

        <property name="hbm2ddl.auto">update</property>  

        <!-- 显示Hibernate持久化操作所生成的SQL -->  

        <property name="show_sql">true</property>  

        <!-- 将SQL脚本进行格式化后再输出 -->  

        <property name="hibernate.format_sql">true</property>  

        <!-- 罗列所有的映射文件 -->  

        <mapping resource="*/*.hbm.xml"/>  

    </session-factory>  

</hibernate-configuration>  

hibernate.properties文件详解:

## MySQL  

#方言  

hibernate.dialect org.hibernate.dialect.MySQLDialect  

hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect  

hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect  

#驱动  

hibernate.connection.driver_class com.mysql.jdbc.Driver  

#数据库地址  

hibernate.connection.url jdbc:mysql://127.0.0.1/datdabseName  

#用户名  

hibernate.connection.username root  

#密码  

hibernate.connection.password 12345  

#是否在控制台输出sql语句  

hibernate.show_sql true/false  

#设置当创建sessionfactory时,是否根据映射文件自动建立数据库表。 create-drop:表示关闭sessionFactory时,将drop刚建的数据库表。该属性可以是update/create-drop/create  

hibernate.hbm2ddl.auto update/create-drop/create  

  

###########################  

### C3P0 Connection Pool C3P0连接池###  

###########################  

#连接池最大链接数  

hibernate.c3p0.max_size 2  

#连接池最小连接数  

hibernate.c3p0.min_size 2  

#连接池连接的超时时长  

hibernate.c3p0.timeout 5000  

#缓存statements 的数量  

hibernate.c3p0.max_statements 100  

hibernate.c3p0.idle_test_period 3000  

hibernate.c3p0.acquire_increment 2  

hibernate.c3p0.validate true/false  

  

  

############  

### JNDI (java naming directory interface)Java命名目录接口###  

###当无需hibernate自己管理数据源而是直接访问容器管理数据源 使用JNDI  

############  

#指定数据源JNDI名字  

hibernate.connection.datasource dddd  

#文件系统下  

hibernate.jndi.class com.sun.jndi.fscontext.RefFSContextFactory  

hibernate.jndi.url file:/  

  

#网络  

#指定JND InitialContextFactory 的实现类,该属性也是可选的。如果JNDI与Hibernate持久化访问的代码处于同一个应用,无需指定该属性  

hibernate.jndi.class com.ibm.websphere.naming.WsnInitialContextFactory  

#指定JNDI提供者的URL,该属性可选 如果JNDI与Hibernate持久化访问的代码处于同一个应用,无需指定该属性  

hibernate.jndi.url iiop://localhost:900/  

  

#指定链接数据库用户名  

hibernate.connection.username  root  

#指定密码  

hibernate.connection.password  1111  

#指定方言  

hibernate.dialect org.hibernate.dialect.MySQLDialect  

  

#######################  

### Transaction API   事务属性说明###  

#######################  

  

#指定是否在事务结束后自动关闭session   

hibernate.transaction.auto_close_session true/false  

#指定session是否在事务完成后自动将数据刷新到底层数据库  

hibernate.transaction.flush_before_completion true/false  

  

## 指定hibernate所有的事务工厂的类型,该属性必须是TransactionFactory的直接或间接子类  

  

hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory  

hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory  

  

## 该属性值是一个JNDI名,hibernate将使用JTATTransactionFactory从应用服务器中取出JTAYserTransaction  

  

jta.UserTransaction jta/usertransaction  

jta.UserTransaction javax.transaction.UserTransaction  

jta.UserTransaction UserTransaction  

  

## 该属性值为一个transactionManagerLookup类名,当使用JVM级别的缓存时,或在JTA环境中使用hilo生成器策略时,需要该类  

  

hibernate.transaction.manager_lookup_class org.hibernate.transaction.JBossTransactionManagerLookup  

hibernate.transaction.manager_lookup_class org.hibernate.transaction.WeblogicTransactionManagerLookup  

hibernate.transaction.manager_lookup_class org.hibernate.transaction.WebSphereTransactionManagerLookup  

hibernate.transaction.manager_lookup_class org.hibernate.transaction.OrionTransactionManagerLookup  

hibernate.transaction.manager_lookup_class org.hibernate.transaction.ResinTransactionManagerLookup  

4. Hibernate会话

会话

Session 用于获取与数据库的物理连接。 Session 对象是轻量级的,并且设计为在每次需要与数据库进行交互时被实例化。持久态对象被保存,并通过 Session 对象检索找回。

Session 对象不应该长时间保持开放状态,因为它们通常不能保证线程安全,而应该根据需求被创建和销毁。Session 的主要功能是为映射实体类的实例提供创建,读取和删除操作。这些实例可 能在给定时间点时存在于以下三种状态之一:

瞬时状态: 一种新的持久性实例,被 Hibernate 认为是瞬时的,它不与 Session 相关联,在数据库中没有与之关联的记录且无标识符值。

持久状态:可以将一个瞬时状态实例通过与一个 Session 关联的方式将其转化为持久状态实例。持久状态实例在数据库中没有与之关联的记录,有标识符值,并与一个 Session 关联。

脱管状态:一旦关闭 Hibernate Session,持久状态实例将会成为脱管状态实例。

Session 实例的持久态类别是序列化的,则该 Session 实例是序列化的。一个典型的事务应该使用以下语法(如果 Session 引发异常,则事务必须被回滚,该 session 必须被丢弃):

Session session = factory.openSession();

Transaction tx = null;

try {

   tx = session.beginTransaction();

   // do some work

   ...

   tx.commit();

}

catch (Exception e) {

   if (tx!=null) tx.rollback();

   e.printStackTrace();

}finally {

   session.close();

}

 

Session 接口方法

序号

Session 方法及说明

1

Transaction beginTransaction()
开始工作单位,并返回关联事务对象。

2

void cancelQuery()
取消当前的查询执行。

3

void clear()
完全清除该会话。

4

Connection close()
通过释放和清理 JDBC 连接以结束该会话。

5

Criteria createCriteria(Class persistentClass)
为给定的实体类或实体类的超类创建一个新的 Criteria 实例。

6

Criteria createCriteria(String entityName)
为给定的实体名称创建一个新的 Criteria 实例。

7

Serializable getIdentifier(Object object)
返回与给定实体相关联的会话的标识符值。

8

Query createFilter(Object collection, String queryString)
为给定的集合和过滤字符创建查询的新实例。

9

Query createQuery(String queryString)
为给定的 HQL 查询字符创建查询的新实例。

10

SQLQuery createSQLQuery(String queryString)
为给定的 SQL 查询字符串创建 SQLQuery 的新实例。

11

void delete(Object object)
从数据存储中删除持久化实例。

12

void delete(String entityName, Object object)
从数据存储中删除持久化实例。

13

Session get(String entityName, Serializable id)
返回给定命名的且带有给定标识符或 null 的持久化实例(若无该种持久化实例)。

14

SessionFactory getSessionFactory()
获取创建该会话的 session 工厂。

15

void refresh(Object object)
从基本数据库中重新读取给定实例的状态。

16

Transaction getTransaction()
获取与该 session 关联的事务实例。

17

boolean isConnected()
检查当前 session 是否连接。

18

boolean isDirty()
session 中是否包含必须与数据库同步的变化?

19

boolean isOpen()
检查该 session 是否仍处于开启状态。

20

Serializable save(Object object)
先分配一个生成的标识,以保持给定的瞬时状态实例。

21

void saveOrUpdate(Object object)
保存(对象)或更新(对象)给定的实例。

22

void update(Object object)
更新带有标识符且是给定的处于脱管状态的实例的持久化实例。

23

void update(String entityName, Object object)
更新带有标识符且是给定的处于脱管状态的实例的持久化实例。

 

5. Hibernate 持久化类

Hibernate 的完整概念是提取 Java 类属性中的值,并且将它们保存到数据库表单中。映射文件能够帮助 Hibernate 确定如何从该类中提取值,并将它们映射在表格和相关域中。

Hibernate 中,其对象或实例将会被存储在数据库表单中的 Java 类被称为持久化类。若该类遵循一些简单的规则或者被大家所熟知的 Plain Old Java Object (POJO) 编程模型,Hibernate 将会处于其最佳运行状态。以下所列就是持久化类的主要规则,然而,在这些规则中,没有一条是硬性要求。

所有将被持久化的 Java 类都需要一个默认的构造函数。

为了使对象能够在 Hibernate 和数据库中容易识别,所有类都需要包含一个 ID。此属性映射到数据库表的主键列。

所有将被持久化的属性都应该声明为 private,并具有由 JavaBean 风格定义的 getXXX setXXX 方法。

l Hibernate 的一个重要特征为代理,它取决于该持久化类是处于非 final 的,还是处于一个所有方法都声明为 public 的接口。

所有的类是不可扩展或按 EJB 要求实现的一些特殊的类和接口。

POJO 的名称用于强调一个给定的对象是普通的 Java 对象,而不是特殊的对象,尤其不是一个 Enterprise JavaBean

6. Hibernate映射类型

6.1. 原始类型

映射类型

Java 类型

ANSI SQL 类型

integer

int java.lang.Integer

INTEGER

long

long java.lang.Long

BIGINT

short

short java.lang.Short

SMALLINT

float

float java.lang.Float

FLOAT

double

double java.lang.Double

DOUBLE

big_decimal

java.math.BigDecimal

NUMERIC

character

java.lang.String

CHAR(1)

string

java.lang.String

VARCHAR

byte

byte java.lang.Byte

TINYINT

boolean

boolean java.lang.Boolean

BIT

yes/no

boolean java.lang.Boolean

CHAR(1) ('Y' or 'N')

true/false

boolean java.lang.Boolean

CHAR(1) ('T' or 'F')

6.2. 日期和时间类型

映射类型

Java 类型

ANSI SQL 类型

date

java.util.Date java.sql.Date

DATE

time

java.util.Date java.sql.Time

TIME

timestamp

java.util.Date java.sql.Timestamp

TIMESTAMP

calendar

java.util.Calendar

TIMESTAMP

calendar_date

java.util.Calendar

DATE

6.3. 二进制和大型数据对象

映射类型

Java 类型

ANSI SQL 类型

binary

byte[]

VARBINARY (or BLOB)

text

java.lang.String

CLOB

serializable

any Java class that implements java.io.Serializable

VARBINARY (or BLOB)

clob

java.sql.Clob

CLOB

blob

java.sql.Blob

BLOB

6.4. JDK 相关类型

映射类型

Java 类型

ANSI SQL 类型

class

java.lang.Class

VARCHAR

locale

java.util.Locale

VARCHAR

timezone

java.util.TimeZone

VARCHAR

currency

java.util.Currency

VARCHAR

 

7. Hibernate 映射文件

一个对象/关系型映射一般定义在 XML 文件中。映射文件指示 Hibernate 如何将已经定义的类或类组与数据库中的表对应起来。

映射文件可以用工具生成,工具包括 XDoclet, Middlegen AndroMDA

xxx.hbm.xml文件解析:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

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

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

<!--

根元素,可以指定类的具体包名、延迟加载等,一般不配置,默认即可

schema:指定映射数据库的schema(模式/数据库),如果指定该属性,则表名会自动添加该schema前缀  

    package:指定包前缀 指定持久化类所在的包名 这样之后calss子元素中就不必使用全限定性的类名  

    default-cascade="none":默认的级联风格,表与表联动。  

    default-lazy="true":默认延迟加载  

 -->

<hibernate-mapping default-lazy="false" package="com.fukai.hibernate">

<!--

定义java实体和数据库中标的对应关系

name:持久化类的java全限定名

        table:对应数据库表名,默认持久化类名作为表名

        proxy:指定一个接口,在延迟装载时作为代理使用,也可在这里指定该类自己的名字

        mutable:默认为true,设置为false时则不可以被应用程序更新或删除,等价于所有<property>元素的update属性为false,表示整个实例不能被更新

        dynamic-insert:默认为false,动态修改那些有改变过的字段,而不用修改所有字段

        dynamic-update:默认为false,动态插入非空值字段

        select-before-update:默认为false,在修改之前先做一次查询,与用户的值进行对比,有变化都会真正更新

        optimistic-lock:默认为version(检查version/timestamp字段),取值:all(检查全部字段)、dirty(只检查修改过的字段);  

        none(不使用乐观锁定),此参数主要用来处理并发,每条值都有固定且唯一的版本,版本为最新时才能执行操作;  

       如果需要采用继承映射,则class元素下还会增加<subclass.../>元素等用于定义子类。  

 -->

<class name="Employee" table="employee">

<!--

定义主键及其生成规则,type指定存入数据库的字段类型,一般与java实体对应

type:指定该标识属性的数据类型,该类型可以是Hibernate的内建类型,也可以是java类型,如果是java类型则需要使用全限定类名(带包名)。该属性可选,如果没有指定类型, 则hibernate自行判断该标识属性数据类型。通常建议设定。  

            name:标识属性的名字

            column:表主键字段的名字,如果不填写与name一样

-->

<id name="id" type="int" column="id">

<!--

相关规则在《Hibernate各种主键生成策略与配置详解》博客中解释

    -->

<generator class="native" />

</id>

<!--   

            <version/>:使用版本控制来处理并发,要开启optimistic-lock="version"和dynamic-update="true"

            name:持久化类的属性名

            column:指定持有版本号的字段名;  

         -->  

        <version name="version" column="version"/> 

         

<!--

property标签定义java实体中属性和数据库中列的对应关系

name:标识属性的名字,以小写字母开头  

column:表字段的名字,如果不填写与name一样

length:字段长度,默认为255

not-null:true/false,是否有非空约束,默认为false

type:Hibernate 映射类型,即数据库该列的类型,一般与java实体属性类型相同

            update/insert=:默认为true,表示可以被更新或插入

            access:指定Hibernate访问持久化类属性的方式。默认property。property表示使用setter/getter方式。field表示运用java反射机制直接访问类的属性

            formula="{select。。。。。}":该属性指定一个SLQ表达式,指定该属性的值将根据表达式类计算,计算属性没有和它对应的数据列

            formula属性允许包含表达式:sum,average,max函数求值的结果

            例如:formula="(select avg(p.price) from Product P)"  

 -->

<property name="name" column="name" type="string"/>

<!--   

                              组件映射:把多个属性打包在一起当一个属性使用,用来把类的粒度变小。

         --> 

            <component name="属性,这里指对象">  

                <property name="name1"></property>  

                <property name="name2"></property>  

            </component>  

        <!----------------------- Hibernate O/R映射 ------------------------>  

        <!--

关联映射,用于处理对象与对象之间的关联关系

type:指定关联关系方式,包含:

many-to-one:多对一

one-to-many:一对多

many-to-many:多对多

one-to-one:一对一

 -->

<many-to-one name="关联实体对象" class="关联对象类路径" column="关联" cascade="关联方式"/>

        <!--   

            <join>:一个对象映射多个表,该元素必须放在所有<property>之后。  

         -->  

        <join table="tbl_test:子表名">  

            <key column="uuid:子表主键"></key>  

        <property name="name1:对象属性" column="name:子表字段"></property>  

    </join>  

    

    <!--

set集合属性的映射:重点消化

name:指定要映射的set集合的属性

table:集合属性要映射的表

key:指定集合表(t_address)的外键字段

element:指定集合表的其他字段

type:元素类型,一定要指定

-->

<set name="address" table="t_address">

    <key column="uid"></key>

    <element column="address" type="string"></element>

</set>

<!--

List集合属性的映射

    name:指定要映射的list集合的属性

    table:集合属性要映射的表

    key:指定集合表(t_addressList)的外键字段

    element:指定集合表的其他字段

    type:元素类型,一定要指定

    list-index:是list集合一定要指定的,指定排序列的名称,因为list是有序的

-->

<list name="addressList" table="t_addressList">

<key column="uid"></key>

<list-index column="idx"></list-index>

<element column="address" type="string"></element>

</list>

 

<!--

Map映射

name:指定要映射的map集合的属性

table:集合属性要映射的表

key:指定集合表(t_addressMap)的外键字段

element:指定集合map的其他字段value

type:元素类型,一定要指定

map-key:指定map的key

-->

<map name="addressMap" table="t_addressMap">

<key column="uid"></key>

<map-key type="string" column="shortName"></map-key>

<element type="string" column="address"></element>

</map> 

</class>

</hibernate-mapping>        

8. Hibernate注释

使用注释和使用xxx.hbm.xml文件逻辑相同,但是,使用注释有助于代码理解和维护,可以精简代码。

使用注释需要的jar包:

hibernate-annotations.jar

hibernate-comons-annotations.jar

ejb3-persistence.jar

Hibernate注释详细分析地址:

http://docs.jboss.org/hibernate/annotations/3.4/reference/zh_cn/html_single/

简单注释示例:

import java.util.Date;

import javax.persistence.*;

 

//定义当前类为映射实体bean

@Entity

//指定当前bean对应的数据库表,目录和schema的名字,如果不用table标签,表名默认为实体bean的短类名(实体名称),不带包名

@Table(name = "employee" )

public class Employee {

/**

 * 针对属性的注释可以写在属性前,也可以写在属性的get()方法前,根据访问类型来确定,尽量避免混合使用

 * 访问类型:

 * property:在getter方法上注释

 * field:在字段上注释

 * Hibernate根据@Id 或  @EmbeddedId 的位置来判断访问类型,本示例都在字段上注释

 */

//定义当前字段为主键

@Id

/*

 * 指定bean属性和表中字段之间对应关系

 * name:可选,对应表中字段名,没有时被修饰字段名对应表列名

 * nullable:可选,设置该属性是否可以为空(默认值true)

 * unique:可选,是否在该列上设置唯一约束(默认值false)

     * insertable: 可选,该列是否作为生成的insert语句中的一个列(默认值true)

     * updatable: 可选,该列是否作为生成的update语句中的一个列(默认值true)

     * String columnDefinition(): 可选,为这个特定列覆盖SQL DDL片段 (这可能导致无法在不同数据库间移植,默认值"")

     * String table() default "":可选,定义对应的表(默认为主表)

     * int length() default 255:可选,列长度(默认值255)

     * int precision() default 0:  可选,列十进制精度(decimal precision)(默认值0)

     * int scale() default 0: 可选,如果列十进制数值范围(decimal scale)可用,在此设置(默认值0)

 */

@Column(name="id",nullable=true,unique=true,length=32)

/*

 * 定义主键的生成策略

 * TABLE:使用一个特定的数据库表格来保存主键。

 * SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。

 * IDENTITY:主键由数据库自动生成(主要是自动增长型)

 * AUTO:主键由程序控制,默认值。

 * 对于oracle想使用各自的Sequence,设置如下:

 * @GeneratedValue(strategy = GenerationType.AUTO,generator="PROMOTION_SEQ")

 * @SequenceGenerator(name="PROMOTION_SEQ",sequenceName="PROMOTION_SEQ")

 * 另外:对于自动增长后,在数据表中的相应字段,要设置字段为auto_increment.

 */ 

@GeneratedValue(strategy=GenerationType.SEQUENCE)

@SequenceGenerator(name = "UUID")

private int id;

/*

 * 乐观锁定版本控制,用于检测更新冲突

 * hibernate中可以自定义类型,建议使用numeric类型

 */

@Version

@Column(name = "version")

private Integer version;

/*

 * 定义当前字段为零时帮助字段,即:实体不应表中没有该属性对应的列

 * 实体bean中所有的非static和非transient的属性都可以被持久化

 */

@Transient

private String name;

//字段前没有定义注释时,默认一个@Basic

private int num;

/*

 * 可以用于说明字段的生成策略

 * 默认的是即时获取,也可以设置为延迟获取(fetch = FetchType.LAZY)

 * 即时获取:hibernate创建当前bean实例时,即时获取当前属性在数据库中对应的值

 * 延迟获取:hibernate创建当前bean实例时,不会即时获取当前属性在数据库中对应的值,只有在调用当前属性时才从数据库获取对应值

 */

@Basic(fetch = FetchType.LAZY)

private String address;

 

/*

 * 定义时间类型的属性,匹配数据库中的date(日期)、time(时间)、timestamp(日期+时间)

 */

@Temporal(TemporalType.TIME)

@Column(name = "date")

private Date date;

/*

 * 一对一关系,一般用于对象和对象之间,使用外键关联,并且外键必须添加唯一约束

 * 主表的操作同时关联副表的操作

 * CascadeType.PERSIST: 如果一个实体是受管状态, 或者当persist()函数被调用时, 触发级联创建(create)操作

 * CascadeType.MERGE: 如果一个实体是受管状态, 或者当merge()函数被调用时, 触发级联合并(merge)操作

 * CascadeType.REMOVE: 当delete()函数被调用时, 触发级联删除(remove)操作

 * CascadeType.REFRESH: 当refresh()函数被调用时, 触发级联更新(refresh)操作

 * CascadeType.ALL: 以上全部

 * 其余关联关系方式相同

 */

@OneToOne(cascade = CascadeType.ALL)

/*

 * 定义关联字段,一般用外键

 */

@JoinColumn(name="passport_fk")

private Department department;

省略get()/set()方法

}

 

9. Hibernate 查询语言-HQL学习

Hibernate 查询语言(HQL)是一种面向对象的查询语言,类似于 SQL,但不是去对表和列进行操作,而是面向对象和它们的属性。

HQL 中一些关键字比如 SELECT FROM WHERE 等,是不区分大小写的,但是一些属性比如表名和列名是区分大小写的。

HQL中,操作的是对象和对象的属性,与数据库列名无关

/****************************简单语句****************************/

/*

 * 与sql类似,不过hql操作的是实体属性,sql操作的是表列名

 * from bean类名  where 条件 bean属性名

 * 下边语句中蓝色关键字用法和sql中相同

 */

select t.name from Student as t where t.id = 10 order by t.date desc;

 

/**************************group by语句**************************/

/*

 * 和sql中用法相同,但操作的是bean属性

 */

SELECT SUM(E.salary), E.firtName FROM Employee E GROUP BY E.firstName;

 

/**************************使用命名参数**************************/

/*

 * 处理参数变化比较大的需求

 */

String hql = "FROM Employee E WHERE E.id = :employee_id";

Query query = session.createQuery(hql);

query.setParameter("employee_id",10);

List results = query.list();

 

/***********************update/delete语句***********************/

/*

 * hibernate3开始,提供了executeUpdate()方法,可是执行update和delete操作

 */

String hql1 = "UPDATE Employee set salary = :salary WHERE id = :employee_id";

String hql2 = "DELETE Employee set salary = :salary WHERE id = :employee_id";

Query query1 = session.createQuery(hql1);

Query query2 = session.createQuery(hql2);

query.setParameter("salary", 1000);

query.setParameter("employee_id", 10);

int result1 = query1.executeUpdate();

int result2 = query2.executeUpdate();

 

/**************************insert语句*************************/

/*

 * 有点过程的味道

 */

 insert into employee(firstname, lastname, salary) select firstname, lastname, salary from old_employee

 

/***************************聚合方法**************************/

S.N.

方法

描述

1

avg(property name)

属性的平均值

2

count(property name or *)

属性在结果中出现的次数

3

max(property name)

属性值的最大值

4

min(property name)

属性值的最小值

5

sum(property name)

属性值的总和

 

/***************************分页查询**************************/

S.N.

方法&描述

1

Query setFirstResult(int startPosition) 
该方法以一个整数表示结果中的第一行,0 行开始。

2

Query setMaxResults(int maxResult) 
这个方法告诉 Hibernate 来检索固定数量,即 maxResults 个对象。

 

String hql = "FROM Employee";

Query query = session.createQuery(hql);

query.setFirstResult(1);

query.setMaxResults(10);

List results = query.list();

10. Hibernate缓存

使用缓存,降低了应用程序访问数据库的频次,有利于提高程序的运行效率。

Hibernate缓存方案图:

 

一级缓存

第一级缓存是 Session 缓存并且是一种强制性的缓存,所有的要求都必须通过它。Session 对象在它自己的权利之下,在将它提交给数据库之前保存一个对象。

如果你对一个对象发出多个更新,Hibernate 会尝试尽可能长地延迟更新来减少发出的 SQL 更新语句的数目。如果你关闭 session,所有缓存的对象丢失,或是存留,或是在数据库中被更新。

 

二级缓存

第二级缓存是一种可选择的缓存并且第一级缓存在任何想要在第二级缓存中找到一个对象前将总是被询问。第二级缓存可以在每一个类和每一个集合的基础上被安装,并且它主要负责跨会话缓存对象。

任何第三方缓存可以和 Hibernate 一起使用。org.hibernate.cache.CacheProvider 接口被提供,它必须实现来给 Hibernate 提供一个缓存实现的解决方法。

 

查询层次缓存

Hibernate 也实现了一个和第二级缓存密切集成的查询结果集缓存。

这是一个可选择的特点并且需要两个额外的物理缓存区域,它们保存着缓存的查询结果和表单上一次更新时的时间戳。这仅对以同一个参数频繁运行的查询来说是有用的。

 

第二级缓存

Hibernate 使用默认的一级缓存并且你不用使用一级缓存。让我们直接看向可选的二级缓存。不是所有的类从缓存中获益,所以能关闭二级缓存是重要的。

Hibernate 的二级缓存通过两步设置。第一,你必须决定好使用哪个并发策略。之后,你使用缓存提供程序来配置缓存到期时间和物理缓存属性。

 

并发策略

一个并发策略是一个中介,它负责保存缓存中的数据项和从缓存中检索它们。如果你将使用一个二级缓存,你必须决定,对于每一个持久类和集合,使用哪一个并发策略。

l Transactional:事务型并发访问策略

l Read-write:读写型并发访问策略

l Nonstrict-read-write:非严格读写型并发访问策略

l Read-only:只读型并发访问策略

 

缓存提供者

在考虑你将为你的缓存候选类所使用的并发策略后你的下一步是挑选一个缓存提供者。Hibernate 让你为整个应用程序选择一个单独的缓存提供者。

n EHCache:它能在内存或硬盘上缓存并且集群缓存,而且它支持可选的 Hibernate 查询结果缓存。

n OSCache:支持在一个单独的 JVM 中缓存到内存和硬盘,同时有丰富的过期策略和查询缓存支持。

n warmCache :一个基于 JGroups 的聚集缓存。它使用集群失效但是不支持 Hibernate 查询缓存。

n JBoss Cache:一个也基于 JGroups 多播库的完全事务性的复制集群缓存。它支持复制或者失效,同步或异步通信,乐观和悲观锁定。Hibernate 查询缓存被支持。

 

每一个缓存提供者都不和每个并发策略兼容。以下的兼容性矩阵将帮助你选择一个合适的组合。

策略/提供者

Read-only

Nonstrictread-write

Read-write

Transactional

EHCache

X

X

X

 

OSCache

X

X

X

 

SwarmCache

X

X

 

 

JBoss Cache

X

X

 

 

 

总结:

hibernate 总共有三种形式的缓存,分为二级:一级session级别的缓存,二级sessionfactory级别的缓存。二级缓存有两种形式,一是外部插件(EHCache),二是查询缓存,查询缓存基于外部插件存在,要使用查询缓存,必须先配置好二级缓存。 2.一级缓存和二级缓存都是根据Id来加载于缓存的 3.查询缓存大多数是用来缓存实体属性的结果集的,如果查询结果为实体对象的集合时,查询缓存里就只有实体对象的Id 4.当访问指定id的对象时,查找顺序是:一级缓存 ---> 查询缓存(实体Id) ---> 外部缓存(实体数据) ---> 数据库

11. Hibernate 批处理

批处理用于处理将大量数据上传至数据库的问题。

处理逻辑:

默认情况下,hibernate会将所有对象以id为标识符存于会话层缓存中,如果数据量过大,会造成内存溢出。而事实上,在这个操作中我们不需要缓存存任何东西,只需要将数据直接写入数据库就可以了。所以,解决方法是按批次写入并清理缓存数据,这样就大大减少了缓存压力。

Session session = SessionFactory.openSession();

Transaction tx = session.beginTransaction();

for ( int i=0; i<100000; i++ ) {

    Employee employee = new Employee(.....);

    //将数据写入缓存

    session.save(employee);

    if( i % 50 == 0 ) { //定义每50条数据为一批次

        //将缓存中的数据插入数据库,使缓存中数据和数据库中的数据保持一致

        session.flush();

        //清理缓存

        session.clear();

    }

}

tx.commit();

session.close();

 

12. Hibernate 拦截器

拦截器是针对一个持续对象在它被保存,更新,删除或上传之前,添加对其的业务逻辑(检查或操作其属性等)的方法。

 

实现方式:

实现Interceptor 接口

l 继承EmptyInterceptor (实现了Interceptor, Serializable的类),重写其中方法,建议使用,只需要将需要的父类方法重写即可

Interceptor接口方法说明:

import org.hibernate.Interceptor;

 

public class MainApp implements Interceptor {

/*

 * 当Hibernate事务通过Hibernate的事务控制开始时调用。如果事务是通过其他方式控制的,就不会被调用

 */

@Override

public void afterTransactionBegin(Transaction arg0) {

}

/*

 * 在事务被提交或回滚之后调用

 */

@Override

public void afterTransactionCompletion(Transaction arg0) {

}

/*

 * 在事务提交之前调用(但包含在回滚之前)

 */

@Override

public void beforeTransactionCompletion(Transaction arg0) {

}

/*

 * 当 flush() 方法在一个 Session 对象上被调用时被调用

 */

@Override

public int[] findDirty(Object arg0, Serializable arg1, Object[] arg2, Object[] arg3, String[] arg4, Type[] arg5) {

return null;

}

/*

 * 获取一个完全加载的实体实例,它是在外部缓存的

 */

@Override

public Object getEntity(String arg0, Serializable arg1) throws CallbackException {

return null;

}

/*

 * 获取持久或瞬态实例的实体名称

 */

@Override

public String getEntityName(Object arg0) throws CallbackException {

return null;

}

/*

 * 在一个持续的类被实例化时被调用

 */

@Override

public Object instantiate(String arg0, EntityMode arg1, Serializable arg2) throws CallbackException {

return null;

}

/*

 * 区分瞬态和分离的实体。返回值决定了与当前会议有关的实体的状态

 * true:瞬时实体

 * false:实体是分离的

 */

@Override

public Boolean isTransient(Object arg0) {

return null;

}

/*

 * 在集合被创建时调用

 */

@Override

public void onCollectionRecreate(Object arg0, Serializable arg1) throws CallbackException {

}

/*

 * 在集合被删除时调用

 */

@Override

public void onCollectionRemove(Object arg0, Serializable arg1) throws CallbackException {

}

/*

 * 在集合被更新时调用

 */

@Override

public void onCollectionUpdate(Object arg0, Serializable arg1) throws CallbackException {

}

/*

 * 在一个对象被删除前被调用

 */

@Override

public void onDelete(Object arg0, Serializable arg1, Object[] arg2, String[] arg3, Type[] arg4)

throws CallbackException {

}

/*

 * 在当 Hibernate 探测到一个对象在一次 flush(例如,更新操作)中是脏的(例如,被修改)时被调用

 */

@Override

public boolean onFlushDirty(Object arg0, Serializable arg1, Object[] arg2, Object[] arg3, String[] arg4,

Type[] arg5) throws CallbackException {

return false;

}

/*

 * 在对象被初始化之前调用。拦截器可能会改变“状态”,也就是被传播到持久对象。

 * 注意,当这种方法被调用时,实体将会是一个空的未初始化的类实例

 */

@Override

public boolean onLoad(Object arg0, Serializable arg1, Object[] arg2, String[] arg3, Type[] arg4)

throws CallbackException {

return false;

}

/*

 * 调用sql字符串之前调用

 */

@Override

public String onPrepareStatement(String arg0) {

return null;

}

/*

 * 这个方法在一个对象被保存前被调用

 */

@Override

public boolean onSave(Object arg0, Serializable arg1, Object[] arg2, String[] arg3, Type[] arg4)

throws CallbackException {

return false;

}

/*

 * 在一次 flush 已经发生并且一个对象已经在内存中被更新后被调用

 */

@Override

public void postFlush(Iterator arg0) throws CallbackException {

}

/*

 * 在一次 flush 前被调用

 */

@Override

public void preFlush(Iterator arg0) throws CallbackException {

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值