SlideShare a Scribd company logo
精通 Hibernate java 对象持久化技术祥解 Hibernate 入门 OR 映射技术 通过 Hibernate API 操纵数据库 检索策略和方式 数据库事务、并发、缓存与性能优化 高级配置。
Hibernate 入门 案例 Hibernate 关系数据库 Customer 类 BusinessService 类 对象关系型映射 Hibernate API Hibernate 配置文件 Customers 表
Hibernate 入门 创建配置文件 hibernate.dialect=net.sf.hibernate.dialect.OracleDialect hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver hibernate.connection.url=jdbc:oracle:thin:peopres/peopres@127.0.0.1:1521:oracle9 hibernate.connection.username=peopres hibernate.connection.password=peopres hibernate.show_sql=true
Hibernate 入门 创建持久化类 public   class  Customer  implements  Serializable { private   static   final   long  serialVersionUID = 5431991012351413505L; private  Long id; private  String name; private  String email; …… public  Customer() { } public  Long getId() { return  id; } public   void  setId(Long id) { this .id = id; } public  String getName() { return  name; }
Hibernate 入门 创建数据库 drop database if exists SAMPLEDB; create database SAMPLEDB; use SAMPLEDB; create table CUSTOMERS ( ID bigint not null primary key, NAME varchar(15) not null, EMAIL varchar(128) not null, PASSWORD varchar(8) not null,  PHONE int ,  ADDRESS varchar(255), SEX char(1) , IS_MARRIED bit, DESCRIPTION text, IMAGE blob, BIRTHDAY date, REGISTERED_TIME timestamp );
Hibernate 入门 创建对象 - 关系映射文件 <hibernate-mapping> <class name=&quot;mypack.Customer&quot; table=&quot;CUSTOMERS&quot;> <!--id  主键  --> <id name=&quot;id&quot; column=&quot;ID&quot; type=&quot;long&quot;> <generator class=&quot;increment&quot; /> </id> <!--  名称  --> <property name=&quot;name&quot; column=&quot;NAME&quot; type=&quot;string&quot;  not-null=&quot;true&quot; /> …… </class> </hibernate-mapping>
Hibernate 入门 把 customer 持久化类映射到 customers 表 <class>: 类和表的映射 <class name=&quot;mypack.Customer“ table=&quot;CUSTOMERS&quot;> <id>: 持久化类的 OID 和表主键映射 <id name=&quot;id&quot; column=&quot;ID&quot; type=&quot;long&quot;> <generator class=&quot;increment&quot; /> </id> <property> <property  name=&quot;email&quot;    column=&quot;EMAIL&quot;    type=&quot;string&quot;    not-null=&quot;true&quot; />
Hibernate 入门 java 、 hibernate 、 sql 类型对应关系 TIMESTAMP REGISTERED_TIME timestamp java.sql.TimeStamp registeredTime DATE BIRTHDAY date java.sql.Date birthday BLOB CLOB BIT CHAR(1) INT Varchar(15) Sql 类型 IMAGE DESCRIPTION IS_MARRIED SEX PHONE NAME Cutomers 字段名 binary text boolean character int string hibernate byte[] java.lang.String boolean char int java.lang.String java Phone Sex Married Description Name image Customer 类属性
Hibernate 入门 通过 API 操作数据库
Hibernate 入门 通过 API 操作数据库
Hibernate 入门 Hibernate 初始化 1 、创建 configuration 对象,把 hibernate.properties 文件读入内存。 2 、 add (……)把映射文件读入内存 3 、 buildSessionFactory ()数据源。重量级对象。
Hibernate 入门 Hibernate 初始化 访问 Session 接口 save() update() delete() load() find()
Hibernate 入门
第一章  Java 对象持久化概述 Hibernate 是什么 连接 java 应用程序和关系型数据库的中间件 对 JDBC API 封装,负责对象持久化 位于持久化层,封装所有的数据访问细节,使业务逻辑层更关注于业务逻辑。 一种 ORM 映射工具。
第一章  Java 对象持久化概述 应用程序的分层体系结构 数据库 应用程序层 数据库 表述层 应用程序层 双层体系结构 三层体系结构 表述层:提供与用户交互的 GUI 。 业务逻辑层:实现各种业务逻辑。 数据库层:负责存放和管理应用的持久性数据。
第一章  Java 对象持久化概述 应用程序的分层体系结构 区分物理层和逻辑层 物理分层:每一层运行在单独的机器上,意味 着创建分布式软件系统。 逻辑分层:在单个的软件模块中完成特定的功 能。 不作特别说明,软件分层指的是逻辑分层。
第一章  Java 对象持久化概述 应用程序的分层体系结构 软件层的特征 1. 每个层由一组相关的类或组件构成,共同完 成特定功能。 2.  层之间存在自上而下的依赖关系。不存在 跨层访问。 3. 每个层对上层公开 API ,但具体的实现细节 对外透明。
第一章  Java 对象持久化概述 应用程序的分层体系结构 软件分层的优点 1. 伸缩性 : 能否支持更多用户。 2. 可维护性 : 需求变化时,影响一部分,不影 响其它部分的代码。 3. 可扩展性 : 增加薪功能的难以程度。 4. 可重用性 : 代码没冗余,满足多种需求。 5. 可管理性 : 管理系统的难易程度。
第一章  Java 对象持久化概述 应用程序的分层体系结构 软件分层缺点 1. 设计人员要求高 2. 体细结构合理划分,耗时大 3. 调试困难 4. 对于规模较小的应用,软件分层会降低开发 效率。
第一章  Java 对象持久化概述 应用程序的分层体系结构 Java 应用的持久化层 表述层 业务逻辑层 数据库层 表述层 业务逻辑层 持久化层 数据库层
第一章  Java 对象持久化概述 Hibernate 中间件特性 应用 1 业务逻辑层 应用 2 业务逻辑层 应用 3 业务逻辑层 持久化层 (hibernate) 数据库 1 数据库 2 数据库 3 持久化层封装了数据访问的细节,为业务逻辑层提供了面向对象的 API 。完善的持久化层应该 达到的目标: 1. 代码重用性高,可完成所有的数据访问操作。 2. 如果需要的话,能够支持多种数据库平台。 3. 具有相对独立性,当持久化层变化时,不会影响上层实现。
第一章  Java 对象持久化概述 软件模型 概念模型:模拟问题域中的真实实体。描述每个实体的概念和属性及实体间关系。不描述实体行为。实体间的关系有一对一、一对多和多对多。 客户 Name age 订单 orderNumber price 1 *
第一章  Java 对象持久化概述 软件模型 关系数据模型:在概念模型的基础上建立起来的,用于描述这些关系数据的静态结构。有以下内容组成: 1. 若干表 2. 表的所有索引 3. 视图 4. 触发器 5. 表与表之间的参照完整性 Customers 表 ID<PK> NAME AGE ORDERS 表 ID<pk> CustomerID<fk> Order_number price
第一章  Java 对象持久化概述 软件模型 域模型:在软件的分析阶段创建概念模型,在软件设计阶段创建域模型。 组成部分: 1. 具有状态和行为的域对象。 2. 域对象之间的关联。
第一章  Java 对象持久化概述 软件模型 域对象 (domain object): 构成域模型的基本元素就是域对象。对真实世界的实体的软件抽象,也叫做业务对象 (Business Object(BO)). 域对象可代表业务领域中的人、地点、事物或概念。 域对象分为以下几种 : 实体域对象:通常是指业务领域中的名词。 (plain old java object) 。 过程域对象:应用中的业务逻辑或流程。依赖 于实体域对象,业务领域中的动词。如 发出订单、登陆等。 事件域对象:应用中的一些事件(警告、异常)。
第一章  Java 对象持久化概述 软件模型 域对象间的关系 1. 关联:类间的引用关系。以属性定义的方式表现。 关联可分为一对一、一对多和多对多。 还可分为单项关联和双向关联。 Order Customer
第一章  Java 对象持久化概述 软件模型 域对象间的关系 2. 依赖:类之间访问关系。无需定义成属性。在 A 中访问 B 中的 方法或属性,或者 A 负责实例化 B 。 BusinessService Customer
第一章  Java 对象持久化概述 软件模型 域对象间的关系 3. 聚集 (Aggregation) :整体与部分的关系。例人与手的关系。部分类的对象不能单独存在,他的生命周期依赖于整体类的对象的生命周期,整体消失时,部分也随之消失。 Person hand:set Hand ……
第一章  Java 对象持久化概述 软件模型 域对象间的关系 4. 一般化( Generalization ):类之间继承关系。 Employee name HourEmployee rate SalaryEmployee salary
第一章  Java 对象持久化概述 软件模型 域对象的持久化概念 实体域对象在内存中创建后,不能永久存在。将实体域对象永久保存起来,就是持久化的过程。通常只有实体域对象需要持久化,过程域对象和事件域对象一般不需要持久化。广义持久化指增、删、改、查。 内存 Customer 对象 order 对象 数据库 持久化 重新加载到内存
第一章  Java 对象持久化概述 直接通过 JDBC API 。
第一章  Java 对象持久化概述 ORM 简介 对象 - 关系映射 (ORM ,即 Object-Relation Mapping). 指单个组件中负责所有实体域对象的持久化,封装数据访问细节。 域模型 (对象、属性、关联、继承和多态) ORM API ORM  实现 关系数据模型 (表、字段、索引、主键和外键) 业务逻辑层 对象 - 关系映射文件 (xml) 持久化层 数据库层 参照 ORM  充当业务逻辑层和数据库层之间的桥梁
第一章  Java 对象持久化概述 ORM 简介 对象 - 关系映射的概念 域模型 Address 类 Province city street zipcode Customer 类 id name homeAddress comAddress 关系数据模型 Customer 类 ID …… HOME_PROVINCE HOME_CITY …… COM_PROVINCE COM_CITY …… 注:域模型中类的数目要比关系数据模型中 表的数目多。 表的列(字段) 表的行(记录) 表 面向关系概念 属性 类 对象 面向对象概念
第一章  Java 对象持久化概述 ORM 简介 ORM 中间件的使用方法 采用元数据来描述对象 - 关系映射细节,元数据通常采用 xml 格式,并存放在专门的对象 - 关系映射文件中。只要配置了持久化类与表的映射关系, orm 中间件在运行时就能够参照映射文件的信息,把域对象持久化到数据库中。 public void deleteCustomer(Customer c){ Session session = getSession(); session.delete(c); } 执行步骤如下: 1. 运用反射机制,获得 Customer 对象的 Customer.class 类。 2. 参照映射文件得到 Customer 类对应的表的信息,以及和 Customer 类关联的类以及 相应的表信息。 3. 根据以上信息生成 SQL 语句。 4. 调用 hibernate API ,执行该语句。
第一章  Java 对象持久化概述 Hibernate API 简介 1. 提供访问数据库操作 (session,transaction,query) 2. 配置 hibernate 接口 (configuratioin) 3. 回调接口 (Interceptor,Lifecycle,Validatable) 4. 用于扩展的功能接口 (UserType,CompositeUserType, IdentifierGenerator) Hibernate 对 JDBC 做了轻量级的封装。所谓轻量级是 指 Hibernate 并没有完全封装 JDBC , java 应用既可以 通过 HibernateAPI 来访问数据库,还可直接通过 JDBC  API 访问数据库。
第一章  Java 对象持久化概述 Hibernate API 简介 Hibernate 核心接口 1.Configuration  配置 hibernate ,根启动 hibernate ,创建 sessionFactory 对象。 2.SessionFactory  初始化 hibernate ,充当数据源代理,创建 session 对象。线程安全的,可被多个线程共享。重量级的, 需要一个很大的缓存,用于存放于定义的 sql 语句和映射元数 据等。用户还可为它配置一个缓存插件,称为二级缓存。 3.Session  使用最广泛,也被称为持久化管理器,它提供和持久 化相关的操作。增、删、改、查等。不是线程安全的,避免多 个线程共享。轻量级的,创建和销毁不需要消耗太多资源。 Session 中有一个缓存,称为一级缓存。存放当前工作单元加 载的对象。
第一章  Java 对象持久化概述 Hibernate API 简介 Hibernate 核心接口 ( 续 ) 4.Transaction hibernate 数据库事务接口, 它对底层的事务接口作了封装 . 底层事务接 口包括 : JDBC API JTA(java Transaction API) CORBA(common object request Broker architecture)
第一章  Java 对象持久化概述 Hibernate API 简介 Hibernate 核心接口 ( 续 ) 5.Query 和 Criteria 接口:都是查询接口, query 实例 包装了 HQL 查询语句, hql 是面向对象的,他引用类 名及类的属性名,而不是表名和字段名。 Criteria 接 口完全封装了基于字符串形式的查询语句,比 query 接口更面向对象,他擅长执行动态查询。 sessoin 接口的 find 方法也具有数据查询功能,但他 只是执行一些简单的 hql 查询语句的快捷方式,远没 有 query 接口功能强大。
第一章  Java 对象持久化概述 Hibernate API 简介 回调接口 1.Lifecycle 和 Validatable 接口: lifecycle 接口能使 持久化类响应被加载、保存和删除事件。 Validatable 接口使持久化类的接口被保存之前进行 数据验证。这种方式强迫持久化类实现特定接口, 使 hibernate API 渗透到持久化类中,会影响可移 植性,不值得推荐。 2.Interceptor :不必由持久化类来实现。可定义专门实现该接口的类,负责响应持久化类的实例被加载、保存、更新或删除的事件。
第一章  Java 对象持久化概述 Hibernate API 简介 Hibernate 映射类型接口 1.PrivateType 类:映射 java 基本数据类型,包括 ByteType 、 ShortType 、 IntegerType 、 LongType 、 FloatType 、 DoubleType 、 CharactorType 、 BooleanType 。 2.DateType :映射 java 日期类型。 3.BinaryType :映射 Byte[] 类型。 Query.setParameter(“name”,”name”,Hibernate.STRING)
第一章  Java 对象持久化概述 Hibernate API 简介 可供扩展的接口 hibernate 提供的多数功能是可配置的,允许用户选择适当的内置策略。如可配置如下数据库方言 : hibernate.dialect=net.sf.hibernate.dialect.MySQLDialect hibernate.dialect=net.sf.hibernate.dialect.OracleDialect hibernate.dialect=net.sf.hibernate.dialect.SybaseDialect
Java 对象持久化概述 Hibernate API 简介 可供扩展的接口 如果 hibernate 内置的策略不能满足需求时,允许用户自定义实现接口或扩展特定的类。 Hibernate 的扩展点包括: 主键生成策略: IdentifierGenerator sql 方言: Dialect 抽象类 缓存机制: cache 和 cacheprovider 接口 jdbc 连接管理器: connectionprovider 等
Java 对象持久化概述 小结 表现层 业务逻辑层 持久化层 (orm 中间件、负责封装数据访问细节 ) 数据库层 实体域对象 ( 业务数据 ) 过程域对象 ( 业务逻辑 )
第四章 对象 - 关系映射基础 本章解决的问题 1. 持久化类没有 getXXX 和 setXXX 方法。 2. 持久化类的属性在库中没有对应的字段,或 字段没有对应的属性 3. 控制 hibernate 的 insert 、 update 语句。 4. 设置从持久化类映射到数据库表,以及持久 化类的属性映射到数据库表的字段的命名策 略。
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 Hibernate 中持久化类的访问者有两个: 1.Java 应用程序 2.hibernate( 何时调用 get 、 set 方法 ?) Customer 对象 getXXX() 方法 setXXX() 方法 hibernate Java 应用程序 用户 界面 数据库 Java 应用程序不能访问持久化类的 private 方法,而 hibernate 没有这 个限制,它可以访问各种级别的方法。
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 基本数据类型和包装类型 基本数据类型和包装类型对应的 hibernate 映射类型相同。 <property name=“price” type=“double” column=“PRICE” /> 基本类型可直接运算、无法表达 null 、数字类型的默认值为 0 。 包装类默认值是 null 。当对于默认值有业务意义的时候需要使用包装类。
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 Hibernate 访问持久化类属性的策略 1.propertye  默认值:表明 hibernate 通过 getXXX 和 setXXX 来访问类属性。推荐使用。提高域模型透明性。 2.field:hibernate 通过 java 反射机制直接访问类属性。对于没有 javabean 方法的属性可设置该访问策略。 <property name=“name” access=“field” /> 除了设置 property 属性的 access 为 field 和 property 之外 还可以自定义访问策略,需要创建实现 net.sf.hibernate. property.PropertyAccessor 接口的类 。
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 class Customer{ … .. private String firstname ; private String lastname ; public String getName(){ return firstname + “ ” + lastname ; } public void setName(String name){ StringTokenizer t = new StringTokenizer(name); firstname = t.nextToken(); lastname = t.nextToken(); } }
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 在 customer.hbm.xml 文件中无需映射 firstname 和 lastname 属性,而是映射 name 属性 。 <property name =“name” column=“NAME” /> 尽管类中并没有 name 属性,由于 hibernate 不是直接访问 Name 属性,而是调用 get 、 set 方法,因此建立了 Firstname 、 Lastname 和表之间的联系。 Hibernate getName() setName() CUSTOMERS 表 Name 字段 Customer 类 firstname lastname
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 不管在类中是否存在 name 属性,只要在 Customer.hbm.xml 文件中映射了 name 属性,在 hql 语句中就能访问他。 Session.find(“from customer as c where c.name=‘tom’”) 如果改成: <property name=“name” column=“NAME” access=“field”> 后过如何?
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 在 customer 类的 setOrders ()方法中加入程序逻辑。 Public void setOrders(Set orders){ this.orders = orders ; calprice(); } Public calprice(){ …… setAvgPrice(avgprice); }
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 在 setSex ()方法中加入数据验证逻辑 Public void setSex(char sex){ if(sex != ‘M’ && sex != ‘F’){ throw new IllegalArgumentException(“Invalid sex”); } this.sex = sex; }
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 设置派生属性 利用 <property> 元素的 formula 属性,用来设置一个 sql 表达式, hibernate 将根据它来计算出派生属性的值。 <property name=“totalprice”  formula=“(select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=ID)” /> <property name=“unitprice”  formula=“BASE_PRICE*QUANTITY” />
第四章 对象 - 关系映射基础 持久化类的属性及访问方法 控制 insert 、 update 语句 若为 true ,等价于所有的 <property> 元素的 dynamic-update 为 true ,更新一个对象时,动态生成 update 语句,语句中仅包含取值不为 null 的字段。默认 false 。 若为 true ,等价于所有的 <property> 元素的 dynamic-insert 为 true ,保存一个对象时,动态生成 insert 语句,语句中仅包含取值不为 null 的字段。默认 false 。 若为 true ,更新一个对象时,会生成动态 update 语句,只有这个字段取值不为 null 才会把它包含到 update 语句中。默认为 false 。 若为 true ,保存一个对象时,会生成动态 insert 语句,只有这个字段取值不为 null 才会把它包含到 insert 语句中。默认为 false 。 若为 false ,等价于所有的 <property> 元素的 update 属性为 false ,整个实例不能被更新。默认为 true 。 若为 false , update 语句不包含该字段,该字段永远不能被更新。默认值为 true 。 若为 false ,在 insert 语句中不包含该字段,该字段永远不能被插入。默认值 true 。 作用 <property> insert 属性 <property> update 属性 <class> mutable 属性 <property> dynamic-insert 属性 <property> dynamic-update 属性 <class> dynamic-insert 属性 <class> dynamic-update 属性 映射属性
第四章 对象 - 关系映射基础 处理 sql 引用表示符 在 SQL 语法中,表示符是指用于为数据库表、视图、字段或索引等名字的字符串,常规表示符不包括空格,也不包含特殊字符,因此无需使用引用符号。如果数据库表名或列名包含特殊字符,可以使用引用表示符。 <property name=“description” column=“`CUSTOMER DESCRIPTION`” />
第四章 对象 - 关系映射基础 设置类的包名 如果在一个映射文件中包含多个类,并且这些类位于同一个包中,可以设置 <hibernate-mapping> 元素的 package 属性,避免为每个类提供完整的类名。 <hibernate-mapping package=“mypack”> <class name=“customer” table=“cu..” > …… </class> </hibernate-mapping> <hibernate-mapping> <class name=“mypack.customer” table=“cu..” > …… </class> </hibernate-mapping>
第五章 映射对象标识符 Java 按地址区分同一个类的不同对象,关系 数据库用主键区分同一条记录, Hibernate 使用 OID 来建立内存中的对象和数据库中记 录的对应关系。对象的 OID 和数据库的表的 主键对应。为保证 OID 的唯一性,应该让 Hibernate 来为 OID 付值。
第五章 映射对象表示符 关系数据库按主键区分不同记录 主键必备条件: 1.  不允许 null 2. 唯一,不重复 3. 之永远不会改变 自然主键:把具有业务含义的字段作为主键叫做自然主 键。
第五章 映射对象表示符 关系数据库按主键区分不同记录 把主键定义为自动增长类型 在 my SQL 中,把字段设为 auto_increment 类型,数据库会自 动为主键付值。 在 ms SQL server 中,把字段设为 identity 类型,数据库会自 动为主键付值。 从序列 (sequence) 中获取自动增长的描述符 create sequence seq_customer increment by 2 start with 1 insert into customers  values(seq_customer.curval,’..’)
第五章 映射对象表示符 Java 语言按内存地址区分不同的对象 == 和 equals() 方法。
第五章 映射对象标识符 Hibernate 中用对象标识符 (OID) 来区分对象 OID 是关系数据库中的主键在 java 对象模型中的等价物。在运行时, hibernate 根据 OID 来维持 java 对象和数据库记录的对应关系。 Customer c1 = (Customer)session.load(Customer.class,new Long(1)); Customer c2 = (Customer)session.load(Customer.class,new Long(1)); Customer c3 = (Customer)session.load(Customer.class,new Long(3)); c1 == c2 ? c1 == c3 ? <id name=“id” type=“long” column=“ID”> <generator class=“increment” /> </id> <generator> 子元素用来设定表示符生成器。 Hibernate 提供了表识符生成器接 口: net.sf.hibernate.id.IdentifierGenerator, 并提供了多种内置的实现。
第五章 映射对象标识符 适用于自然主键。由 java 程序负责生成标识符。不能把 setID() 方法声明为 Private 的。尽量避免使用自然主键。 适用于代理主键。 Hibernate 采用 128 位的 UUID 算法来生成标识符。该算法 能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。 适用于代理主键。根据底层数据库对自动生成表示符的能力来选择 identity 、 sequence 、 hilo 适用于代理主键。 Hibernate 根据 hign/low 算法生成标识符。 Hibernate 把特定表的字段作为“ hign” 值。默认情况下,采用 hibernate_unique_key 表的 next_hi 字段。 适用于代理主键。 Hibernate 根据底层数据库序列生成标识符。条件是数据库支持序列。 适用于代理主键。由底层数据库生成表识符。条件是数据库支持自动增长数据类型。 适用于代理主键。由 hibernate 自动以递增的方式生成表识符,每次增量为 1 描述 Increment Identity Sequence Hilo Uuid.hex Native assigned 表示符生成器
第五章 映射对象表示符 Hibernate 内置标识符用法 increment select max(id) from table; <id name=“id” type=“long” column=“ID”> <generator class=“increment”/> </id> 适用范围: 1 。由于不依赖与底层数据库,适合所有的数据库系统。 2 。单个进程访问同一个数据库的场合,集群环境下不推荐适用。 3 。 OID 必须为 long 、 int 或 short 类型,如果把 OID 定义为 byte 类型,抛异常。
第五章 映射对象表示符 Hibernate 内置标识符用法 Identity 由底层数据库生成标识符 . 需要把字段定义成自增型。 my sql  中为 auto_increment ms sql server 中为 identity <generator  class=“identity” />
第五章 映射对象表示符 Hibernate 内置标识符用法 sequence <id name=“id” type=“long” column=“ID”> <generator class=“sequence”> <param name=“sequence”>tester_id_seq</param> </generator> </id> 适用范围: 地层数据库要支持序列。 Oracle DB2 SAP 等。 OID 必须为 long 、 int 或 shot 类型。
第五章 映射对象表示符 Hibernate 内置标识符用法 hilo <id name=“id” type=“long” clomn=“ID”> <generator name=“hilo”> <param name=“table”>hi_value</param> <param name=“column”>next_value</param> <param name=“max_lo”>100</param> </generator> </id> 使用范围: 该机制不依赖于地层数据库,因此适用于所有的数据库系统。 OID 必须为 long 、 int 、 short 类型,如果为 byte 类型的话,会抛出异常。 Net.sf.hibernate.id.IdentifierGeneratorException:this id generator generates Long 、 integer 、 short 。
第五章 映射对象表示符 Hibernate 内置标识符用法 native <id name=“id” type=“native” column=“ID”> <generator class=“native” /> </id> 适用范围: 该类型能根据地层数据库系统的类型,自动选择合适的标识符生成器,因此很适合于跨数据 库的平台,即在同一个应用中需要连接多种数据库系统的场合。 OID 与以上类同。
第五章 映射对象表示符 映射自然主键 映射单个自然主键 <id name=“id” column=“NAME” type=“string”> <generator class=“assigned” /> </id> <version name=“version” column=“VERSION” unsaved-value=“0” />
第五章 映射对象表示符 映射自然主键 映射复合主键 <composite-id> <key-property name=“name” column=“NAME” type=“string”> <key-property name=“companyId” column=“COMPANY_ID” type=“long”> </composite-id> <version name=“version” column=“VERSION” unsaved-value=“0” /> 使用联合主键的持久化类需要实现 serializable 接口和覆盖 equals() 、 hashCode() 方法。 可以使用 customId 属性来设置连联合主键 <composite-id name=“costomerid” class=“mypack.CustomerId”> <key-property name=“name” column=“NAME” type=“string”> <key-property name=“companyId” column=“COMPANY_ID” type=“long”> </composite-id>
第六章 映射一对多关联关系 Order 到 Customer 的多对一单向关联 Customer  到 Order 的一对多单向关联 Customer  到 Order 的一对多双向关联
第六章 映射一对多关联关系 建立多对一的单向关联关系 <many-to-one name=“customer”  column=“CUSTOMER_ID”  class=“..Customer” not-null=“true”> <property name=“***”> ?
第六章 映射一对多关联关系 建立多对一的单向关联关系 ( 续 ) many-to-one 属性 : name: 设定待映射的持久化类的名字。 column: 设定和持久化类的属性对应的表的外键。 class: 设定持久化类的属性的类型。 not-null: 是否允许为空。
第六章 映射一对多关联关系 tx = session.beginTransaction(); Customer c =  new  Customer(); c.setName(&quot;TOM&quot;); session.save(c); ? 会有什么后果 Order o1 =  new  Order(); o1.setOrderNumber(&quot;1&quot;); o1.setCustomer(c); Order o2 =  new  Order(); o2.setOrderNumber(&quot;1&quot;); o2.setCustomer(c); session.save(o1); session.save(o2); tx.commit();
第六章 映射一对多关联关系 建立多对一的单向关联关系 <many-to-one>not-null 属性 tx = session.beginTransaction(); Customer c =  new  Customer(); c.setName(&quot;TOM&quot;); //session.save(c); ? 会有什么后果 Order o1 =  new  Order(); o1.setOrderNumber(&quot;1&quot;); o1.setCustomer(c); Order o2 =  new  Order(); o2.setOrderNumber(&quot;1&quot;); o2.setCustomer(c); session.save(o1); session.save(o2); tx.commit();
第六章 映射一对多关联关系 建立多对一的单向关联关系 级联保存和更新 当 hibernate 持久化一个临时对象时,在默认情况下,他不会自动持久化所关联的其他临时对象,会抛出 TransientObjectException. 如果设定 many-to-one 元素的 cascade 属性为 save-update 的话,可实现自动持久化所关联的对象。 <many-to-one name=“customer”  column=“CUSTOMER_ID”  class=“..Customer” cascade=“save-update” not-null=“true” /> <property name=“***”> ?
第六章 映射一对多关联关系 映射一对多双向关联关系 Class Customer{ … public Set orders = new Set(); public Set getOrders(){ return orders; } public void setOrders(Set orders){ this.orders = orders; } … } <set name=“orders”  cascade=“save-update”> <key column=“CUSTOMER_ID” /> <one-to-many class=“..Order” /> </set> Customer c = new Customer(“TOM”); Order o1 = new Order(“11”); O1.setCustomer(c); c.getOrders().add(o1); session.save(c); tx.commit();
第六章 映射一对多关联关系 映射一对多双向关联关系 ( 续 ) Hibernate 要求在持久化类中定义集合属性时,必须把属性声明为接口类型,如 Set 、 Map 、 List. 声明为接口类型可提高持久化类的透明性,当 hibernate 调用 setOrders() 方法时,传递的参数是 Hibernate 自定义的实现该接口类的实例。如果定义成类 ( 如 HashSet) 型,强迫 hibernate 把该类型的实例传给他。 通常在定义集合属性时,直接初始化为一个实现类的实例。 private Set orders = new HashSet(); 可避免空指针异常。
第六章 映射一对多关联关系 映射一对多双向关联关系 ( 续 ) <set name=“orders”  cascade=“save-update”> <key column=“CUSTOMER_ID” /> <one-to-many class=“..Order” /> </set> name: 设定待映射持久化类的属性名。 cascade: 设定级联操作的程度。 key 子属性 : 设定与所关联的持久化类对应的标 的外键。 one-to-many 子属性 : 设定所关联的持久化类。
第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 Customer c = (Customer)session .load(Customer.class,new Long(2)); Order o = (Order)session.load(Order.class,new Long(2)); o.setCustomer(c); c.getOrders().add(o); tx.commit(); -------------------------------------------------------------- Update orders set …... Update orders set …… hibernate 执行两条更新语句。
第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 ( 续 ) Hibernate 会自动清理缓存中的所有持久化对象,按照持久化对象的改变 来同步更新数据库,因此执行了上述的两条更新语句。 重复执行多余的 sql 语句会影响 java 性能,解决这也问题的办法是把 <set> 元素的 inverse 属性设为 true, 该属性的默认值是 false 。 <set name=“orders” cascade=“save-update”  inverse=“true” > <key column=“CUSTOMER_ID” /> <one-to-many class=“mypack.Order” /> </set> Customer 和 order 的双向关联中, customer 端的关联只是 order 端关联 的镜像。当 hibernate 同时探测到持久化对象 customer 和 order 的状态均 发生变化时,仅按照 order 对象状态更新数据库。
第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 ( 续 ) Customer c = (Customer)session.load(…)); Order o = (Order)session.load(…); o.setCustomer(c); //c.getOrders().add(c); tx.commit(); -------------------------------------------------------------------- 以上代码仅设置了 order 对象的 customer 属性, hibernate 仍然会按照 order 对象的状态 的变化来同步更新数据库,执行以下 sql 语句: Update orders set order_number=‘…’,customer_id=2 where id = 2
第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 ( 续 ) Customer c = (Customer)session.load(……); Order o = (Order)session.load(……); //o.setCustomer(c); c.getOrders().add(c); tx.commit(); -------------------------------------------------------------------- 以上代码仅设置了 customer 对象的 orders 属性,由于 <set> 元素的 inverse 属性为 true ,因此, hibernate 不会按照 customer 对象的状态 变化来同步更新数据库。
第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 结论: 1. 在映射一对多的双向关联关系时,应该在 one 方把 inverse 属性设为 true ,这可以提高性能。 2. 在建立两个对象的关联时,应该同时修改关联两端的相应 属性: Customer.getOrders().add(order); Order.setCustomer(customer); 这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务 逻辑层的程序代码不受 Hibernate 实现类的影响。同理,当删 除双向关联的关系时,也应该修改关联两端的对象的相应属性: Customer.getOrders().remove(order); Order.setCustomer(null);
第六章 映射一对多关联关系 映射一对多双向关联关系 级联删除 Customer customer = (Customer)session.load(Customer.class,new Long(2)); Session.delete(customer); tx.commit(); -------------------------------------------------------------------------------------- 如果 cascade 属性取默认值 none ,不会自动删除和 customer 关联的其他持久化对象。如 果希望删除 customer 时,自动删除和 customer 关联的 order 对象,可把 cascade 属性设 为 delete 。 <set name=“orders” cascade=“delete” inverse=“true”> <key column=“CUSTOMER_ID” /> <one-to-many class=“mypack.Order” /> </set> 再运行删除方法的时候,会自动删除 order 对象,此时 hibernate 执行如下语句: Delete from customer where customer_id = 1; Delete customer where id = 1;
第六章 映射一对多关联关系 映射一对多双向关联关系 父子关系 Customer customer = (Customer)session.load(……); Order order = (Order)customer.getOrders().iterator().next(); // 删除关联关系 customer.getOrders().remove(order); order.setCustomer(null); tx.commit(); -------------------------------------------------------------------------------------- 如果 cascade 为默认值 none , hibernate 会执行如下语句: Update orders set Customer_id = null where ID = 2; 如果希望程序自动删除不再和 customer 关联的 order 对象,可以把 cascade 属性设为 all-delete-orphan 。 <set name=“orders” cacade=“add-delete-orphan” inverse=“true”> <key column=“CUSTOMER_ID” /> <one-to-many class=“mypack.Order” /> </set> Delete from orders where CUSTOMER_ID = 2 and ID = 2
第六章 映射一对多关联关系 映射一对多双向关联关系 父子关系 当 customer.hbm.xml 的 <set> 元素的 cascade 属性取值为 all-delete-orphan,Hibernate 会按照如下方式处理 customer 对象: 1. 当保存或更新 customer 对象时,级联保存或更新所有关联的 order 对象,相当于 save-update. 2. 当删除 customer 对象时,级联删除所有的 order 对象,相当于 delete 。 3. 删除不再和 customer 对象关联的所有 order 对象。 当关联双方存在父子关系时,就可以把父方的 cascade 属性设为 all-delete-orphan. 所谓父子关系:是指父方来控制子方的持久化生命周期,子方对象必 须和一个父方对象关联。
第七章 操纵持久化对象 Session 接口提供增、删、改、查功能。 Session 中有一个缓存,位于缓存中对象处 于持久化状态,他和数据库中的记录相对 应。 Session 能够在某些时间点,按照缓存 中的持久化对象的属性变化来同步更新数据 库,这一过程被称为清理缓存。除了持久化 状态还有游离态和临时态。
第七章 操纵持久化对象 Java 对象在 JVM 中的生命周期 Customer c = new Customer(“TOM”,new HashSet()); Order o1 = new Order(“Tom_order001”,null); Order o2 = new Order(“Tom_order002”,null); o1.setCustomer(c); c.getOrders().add(o1); o1 = null; o2 = null; c = null;
第七章 操纵持久化对象 理解 session 的缓存 当 session 的 save() 方法持久化一个对象 时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图 load() 对象时,会判断缓存中是否存在该对象,有则返回。
第七章 操纵持久化对象 理解 session 的缓存 ( 续 ) Customer c = new Customer(“TOM”,new HashSet()); session.save(c); Long id = c.getId(); c = null; Customer c2 = (Customer)session.load(Customer.class,id); tx.commit(); session.close(); c2.getName(); C2 = null; --------------------------------------------------------------------------------------------- 缓存的作用: 1 。减少访问数据库的频率。 2 。保证缓存中的对象与数据库中的相关记录保持同步。 3 。当缓存中的持久化对象之间存在循环关联关系时, Session 会保证不出现访问对象图的死循 还,以及由死循环引起的 JVM 堆栈溢出异常。 提示: 当 session 加载了 customer 对象后,会为 customer 对象的值类型的属性复制一份快照。当清理 缓存时,通过比较对象的当前属性和快照,来判断对象的那些属性发生了变化。
第七章 操纵持久化对象 理解 session 的缓存 Session 在清理缓存时,按照以下顺序执行 sql 语句。 1 。按照应用程序调用 save ()方法的先后顺序,执行所有的对实体进行插入的 insert 语句。 2 。所有对实体进行更新的 update 语句。 3 。所有对实体进行删除的 delete 语句。 4 。所有对集合元素进行删除、更新或插入的 sql 语句。 5 。执行所有对集合进行插入的 insert 语句。 6 。按照应用程序调用 delete ()方法的先后执行。 默认情况下: 1 。当应用程序 commit ()方法的时候,先清理缓存,然后在向数据库提交事务。 2 。当调用 find ()或 iterator ()时,如果对象属性发生变化,会先清理缓存,以保证查询结果 能够反映持久化对象的最新状态。 3 。显式调用 flush ()。 --------------------------------------------------------------------------------------------- 提示: Commit ()和 flush ()方法的区别: Flush 进行清理缓存的操作,执行一些列 sql 语句,但不提交事务; commit 方法先调用 flush 方 法,然后提交事务。提交事务意味着对数据库操作永久保存下来。
第七章 操纵持久化对象 理解 session 的缓存 session.setFlushMode(FlushMode.AUTO); 清理 清理 清理 Session 的 flush () 不清理 清理 清理 Session 的 commit () 不清理 不清理 清理 Session 的 查询方法 FlushMode.AUTO FlushMode.COMMIT FLushMode.NEVER 清理缓存的模式
第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 临时状态 (transient) :刚刚用 new 语句创建,没有被持久化,不处于 session 中。该对象 成为临时对象 持久化状态 (persistent) :已经被持久化,加入到 session 的缓存中。该状态的对象为持久 化对象。 游离状态 (detached) :已经被持久化,但不处于 session 中。该状态的对象为游离对象。
第七章 操纵持久化对象 结束生命周期 结束生命周期 c2 = null; 处于游离态 转变为游离态 处于持久化状态 转变为持久化状态 临时状态 状态 处于生命周期中 处于生命周期中 处于生命周期中 处于生命周期中 开始生命周期 生命周期 tx = session.beginTransaction(); Customer c = new Customer(“Tom”,new HashSet); Session.save(c) Long id=c.getId(); c = null; Customer c2 = (Customer)session.load(Customer.class,id); tx.commit(); session.close(); c2,getName(); 程序代码
第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 临时对象特征 不处于 session 中,不被任何 session 关联。 数据库中没有对应的记录。 以下情况,对象进入临时状态: 1.new  语句刚创建了一个对象。 2.session 的 delete 方法使持久化对象或游离 对象转变为临时对象,对于游离对象,该方法从数 据库中删除记录,对于持久化对象,该方法从数据 库中删除记录,还要删除缓存中的对象。
第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 持久化对象特征 1. 位于一个 session 缓存中,总是被一个 session 关联。 2. 持久化对象和数据库记录相对应。 3. 清理缓存时,会根据对象属性变化,同步更新数据库。 4.save 把临时对象转变为持久化对象。 5.load 或 find 或 get 返回的对象总是持久化状态。 6.find 方法返回的 list 存放的都是持久化对象。 7.update 、 save 、 SaveOrUpdate 和 Lock 方法使游离对象装变 为持久化对象。 在实际的应用程序中应该避免一个 java 对象被多个 session 实例关 联,会导致重复执行 sql 语句,并且极容易出现一些并发问题。
第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 游离对象特征 1. 不再位于 session 的缓存中,游离对象不被 session 关联。 2. 游离对象由持久化转变过来的,因此在数据 库中可能还存在与它对应的记录(前提条 件是没有其他程序删除了这条记录)。
第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 游离对象特征 在以下情况下,持久化对象转变为游离对象: 1.close 方法使缓存被清空,缓存中的所有的 对象都变为游离对象。如果没有引用他们 的话,他们就会结束生命周期。 2.evict 方法从缓存中删除一个持久化对象, 使他变为游离态对象。当缓存中保存了大量的持久 化对象时,会消耗许多内存空间,使用该方法删掉 一些对象来节省空间。
第七章 操纵持久化对象 Session 的增、删、改、查方法 save : 1. 对象加入缓存,成为持久化对象。 2.<id name=“id”  cloumn=“ID”  type=“long”> <generator class=“increment”> </id> session.save(c,new Long(9))
第七章 操纵持久化对象 Session 的增、删、改、查方法 update : 将游离对象转变为持久化对象。不论对象属性 是否发生变化,该方法都会执行 update 操作。如果希望仅当属性变化时才执行 update 语句的话可进行如下配置: <class name=“…”  table=“…”  select-before-update=“true”>
第七章 操纵持久化对象 Session 的增、删、改、查方法 saveOrUpdate : 该方法同时包含 save 和 update 方法,如果参数是临时对象就用 save 方法,如果是游离对象就用 update 方法,如果是持久化对象就直接返回。 临时对象判断法: 1 。 OID 为 null 2 。具有 version 属性并取值为 null 3 。在映射文件中为 <id> 元素设置了 unsaved-value 属性,并且 OID 属性取值与属 性匹配。 4 。在映射文件中为 <version> 元素设置了 unsaved-value 属性,并且 version 属性取 值与属性匹配。 5 。自定义了 Interceptor 实现类,并且 isUnsaved 方法返回 Boolean.true 如果 id 的类型为 long ,则默认值为 0 ,此时需要在配置文件中设置 id 的 unsaved-value 为 0 。
第七章 操纵持久化对象 Session 的增、删、改、查方法 load 和 get : 从数据库加载指定的 OID 持久化对象。 如果数据库中不存在该记录时, load 方法会 抛出异常,而 get 方法返回 null 。
第七章 操纵持久化对象 Session 的增、删、改、查方法 delete 如果参数是持久化对象,就执行一个 delete 语句,若为游离对象,先使游离对象被 session 关联,使他变为持久化对象,然后计划执行一个 delete 语句。
第七章 操纵持久化对象 Session 的增、删、改、查方法 包含 all 和 delete-orphan 的行为。 all-delete-orphan 删除所有和当前对象解除关联关系的对象。 包含 save-update 和 delete 的行为。 删除对象时,级联删除关联的对象。 保存或更新当前对象时,级联保存关联的临时对象,更新关联的游离对象。 忽略关联对象,默认值 描述 none save-update delete delete-orphan all cascade 属性值
第七章 操纵持久化对象 与触发器协同工作 Session.save(c); Session.flush(); Session.refresh(c); ----------------------------------------------------------------- 触发器的行为导致缓存与数据库中的数据不一致。解决办法是执行完 操作后,立即调用 session 的 flush 方法和 refresh 方法,迫使缓存与 数据库同步。 Session 的 update 操作方法盲目的激活触发器 如果游离状态的对象的属性和数据库一致,则更新操作是多余的。 为避免这种情况: <class name=“” table=“” select-before-update=“true”> …… </class>
第七章 操纵持久化对象 利用拦截器 (interceptor) 生成审计日志 不依赖于具体的数据库平台,可看成持久化层的 拦截器。 当执行 save 、 update 、 saveorupate 、 flush 方法时,会调用拦截器方法。 实现 Inteceptor 接口。
第七章 操纵持久化对象 利用拦截器 (interceptor) 生成审计日志 Inteceptor 1.findDirty(): 查脏对象 2.Instantiate ():构造实例前调用 3.isUnsaved (): saveorupdate 方法调用该方法,判断用 save 还是 update 4.onDelete :删除对象前调用 5.onFlushDirty : flush 方法检查到脏对象时调用此方法。 6.onLoad ():初始化持久化对象时调用此方法。 7.onSave(): 保存对象前调用该方法。 8.postFlush ():执行完 flush 方法之前调用本方法。
public class AuditLogInterceptor implements Interceptor, Serializable { private Session session; private Set inserts=new HashSet(); private Set updates=new HashSet(); public void setSession(Session session){ this.session=session; } public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types){ if ( entity instanceof Auditable ) { updates.add(entity); } return false; } public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { return false; } public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { if ( entity instanceof Auditable ) { inserts.add(entity); } return false; } public void postFlush(Iterator entities) { try{ Iterator it=updates.iterator(); while(it.hasNext()){ Auditable entity=(Auditable)it.next(); AuditLog.logEvent(&quot;update&quot;,entity,session); } it=inserts.iterator(); while(it.hasNext()){ Auditable entity=(Auditable)it.next(); AuditLog.logEvent(&quot;insert&quot;,entity,session); } }catch(Exception e){e.printStackTrace();} finally{ inserts.clear(); updates.clear(); } } }
第七章 操纵持久化对象
第八章 映射组成关系
第八章 映射组成关系 Class customer{ …… Address homeAddress ; Address comAddress ; …… } Table customers{ …… home_province home_city home_street com_province com_city com_street  …… } <compont name=“homeaddress” class=“mypack.Address”> <parent name=“customer” /> <property name=“street” type=“string” column=“HOME_STREET” /> <property name=“city” type = “string” cloumn=“HOME_CITY” /> <property name=“street” type = “string” cloumn=“HOME_STREET” /> </component> <compont name=“comaddress” class=“mypack.Address”> <parent name=“customer” /> <property name=“street” type=“string” column=“COM_STREET” /> <property name=“city” type = “string” cloumn=“COM_CITY” /> <property name=“street” type = “string” cloumn=“COM_STREET” /> </component>
第八章 映射组成关系 映射组成关系 区分值和实体 持久化类的属性分为两种:值 (value) 类型和实体类型 (entity) 类型。值类型没有 OID ,不能被单独持久化,他的生命周期依赖于所属的持久化类的对象的生命周期,组件类型就是一种值类型;实体类型有 OID ,可单独持久化。
第八章 映射组成关系 映射组成关系 访问由组成关系的持久化类 1.Conf.addClass(Customer.class).addClass(Address.class); 抛映射异常,原因是 Address.hbm.xml 文件没找到。 2. Customer c = new Customer(); c.setHomeAddress(new Address()); c.setComAddress(new Address()); …… Session.save(c); ----------------------------------------------------------------------------------------- Session.save(new Address()); 映射异常: unkown entity class.
第八章 映射组成关系 映射复合组成关系 Computer 类和他的组件类
第八章 映射组成关系 映射复合组成关系 <component name=&quot;cpuBox&quot; class=&quot;mypack.CpuBox&quot;> <parent name=&quot;computer&quot; /> <property name=&quot;type&quot; type=&quot;string&quot; column =&quot;CPUBOX_TYPE&quot; /> <component name=&quot;graphicsCard&quot; class=&quot;mypack.GraphicsCard&quot;> <parent name=&quot;cpuBox&quot; /> <property name=&quot;type&quot; type=&quot;string&quot; column =&quot;GRAPHICSCARD_TYPE&quot; /> </component> <many-to-one   name=&quot;vendor&quot;   column=&quot;CPUBOX_VENDOR_ID&quot;   class=&quot;mypack.Vendor&quot;   not-null=&quot;true&quot;  /> </component>
第九章  Hibernate 映射类型 内置映射类型 布尔 CHAR(1) boolean Boolean true_false 布尔 BIT boolean Boolean boolean 布尔 CHAR(1) boolean Boolean yes_no 变长串 VARCHAR String string 定长字符 8 位含 2 位小数部分 8 4 1 2 8 4 取值范围 CHAR(1) NUMERIC DOUBLE FLOAT TINYINT SMALLINT BIGINT INTEGER sql char Character String java.math.BigDecinimal double Double float Float byte Byte short Short long Long int Integer java integer int  long short byte float double big_decimal character Hibernate
第九章  Hibernate 映射类型 java 时间和日期类性 YYYY-MM-DD YYYYMMDDHHMMSS YYYYMMDDHHMMSS HH:MM:SS YYYY-MM-DD 取值范围 DATE TIMESTAMP TIMESTAMP TIME DATE sql java.util.Calendar java.util.Calendar util.Date sql.timestamp util.Date sql.Time util.Date sql.Date java date time timestamp calendar calendar_date Hibernate
第九章  Hibernate 映射类型 大对象类型的映射 不允许以上类型来定义 OID BLOB sql.Blob blob CLOB BARBINARY(BLOB) CLOB VARBINARY(BLOB) sql sql.Clob 实现类 String byte[] java binary text serializable clob Hibernate
第九章  Hibernate 映射类型 大对象类型的映射 如果持久化类的字段为 blob 或 clob 类型,保存时需要包含两步: ---------------------------------------------------------------------------------------------- Customer c = new Customer(); // 现保存一个空的 clob 实例 c.setDescription(Hibernate.createClob()); session.save(c); session.flush(); // 锁定记录 session.refresh(customer,LockMode.UPGRADE); oracle.sql.CLOB clob = c.getDescription(); // 写入大文本 java.io.Writer pw = clob.getCharacterOutputStream(); pw.write(longtext); pw.close(); tx.commit(); session.close();
第九章  Hibernate 映射类型 JDK 自带的个别 java 类的映射类型 VARCHAR VARCHAR VARCHAR VARCHAR sql java.util.Currency java.util.TimeZone java.util.Locale java.lang.Class java class locale timezone currency Hibernate
第九章  Hibernate 映射类型 使用 hibernate 内置的映射类型 java 应用程序 java.lang.String hibernate hibernate 映射类型: string jdbc Driver 标准 sql 类型: varchar my sql 类型: varchar oracle : varchar2
第九章  Hibernate 映射类型 客户华映射类型 customer 类 -------------------- id:Long email:String phone:Integer hibernate 内置类型 -------------------- long string ? customers 表 -------------------- ID BIGINT EMAIL VARCHAR(50) PHONE VARCHAR(8)
第九章  Hibernate 映射类型 客户华映射类型
第九章  Hibernate 映射类型 客户华映射类型 1 。设置表中的字段类型。 private static final int[] sql_types = {Types.VARCHAR}; public int[] sqltypes(){ return sql_types}; 2. 设置 java 类型。 returnedClass(); 3. 是否是可变类 isMutable(); 4. 深度拷贝,生成快照。 deepCopy(); 5.equals() 方法判断字段属性是否和快照相同。 6. 调用 nullSafeGet() 方法来取得字段的属性值。 public Object nullSafeGet(ResultSet rs,String[] names,Object owner){ if(rs.wasNull()) return null; String phone = rs.getString(name[0]); return new Integer(phone); } 7. 调用 nullSafeSet 方法来把 phone 属性添加到 insert  语句中。 ----------------------------------------------------------------------------------------------- <property name=“phone” type=“mypack.PhoneType” column=“PHONE” />
public   class  Address  implements  Serializable { private   final  String province; private   final  String city; private   final  String street; private   final  String zipcode; public   boolean  equals(Object o) { if  ( this  == o) return   true ; if  (!(o  instanceof  Address)) return   false ; final  Address address = (Address) o; if  (!province.equals(address.province)) return   false ; if  (!city.equals(address.city)) return   false ; if  (!street.equals(address.street)) return   false ; if  (!zipcode.equals(address.zipcode)) return   false ; return   true ; } public   int  hashCode() { int  result; result = (province ==  null  ? 0 : province.hashCode()); result = 29 * result + (city ==  null  ? 0 : city.hashCode()); result = 29 * result + (street ==  null  ? 0 : street.hashCode()); result = 29 * result + (zipcode ==  null  ? 0 : zipcode.hashCode()); return  result; } }
public   class  AddressUserType  implements  UserType { private   static   final   int [] SQL_TYPES = { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR };// 设置和 Address 类的四个属性对应的字段的 sql 类型。 public   int [] sqlTypes() { return  SQL_TYPES; } // 设置所映射的 java 类 public  Class returnedClass() { return  Address. class ; } // 指明 Address 类是不可变类 public   boolean  isMutable() { return   false ; } // 返回 Address 类的快照,由于 Address 类是不可变类,因此直接返回既可。 public  Object deepCopy(Object value) { return  value; // Address is immutable } // 比较对象是否和快照相等 public   boolean  equals(Object x, Object y) { if  (x == y) return   true ; if  (x ==  null  || y ==  null ) return   false ; return  x.equals(y); }
public   class  AddressUserType  implements  UserType { // 从结果集中读取四个属性,构造成 Address 对象。 public  Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws  HibernateException, SQLException { if  (resultSet.wasNull()) return   null ; String province = resultSet.getString(names[0]); String city = resultSet.getString(names[1]); String street = resultSet.getString(names[2]); String zipcode = resultSet.getString(names[3]); return   new  Address(province, city, street, zipcode); } // 把 Address 对象中的属性添加到预处理语句中。 public   void  nullSafeSet(PreparedStatement statement, Object value,  int  index) throws  HibernateException, SQLException { if  (value ==  null ) { statement.setNull(index, Types.VARCHAR); statement.setNull(index + 1, Types.VARCHAR); statement.setNull(index + 2, Types.VARCHAR); statement.setNull(index + 3, Types.VARCHAR); } else  { Address address = (Address) value; statement.setString(index, address.getProvince()); statement.setString(index + 1, address.getCity()); statement.setString(index + 2, address.getStreet()); statement.setString(index + 3, address.getZipcode()); } } }
<property name=&quot;name&quot; type=&quot;mypack.NameCompositeUserType&quot; > <column name=&quot;FIRSTNAME&quot; length=&quot;15&quot; /> <column name=&quot;LASTNAME&quot; length=&quot;15&quot; /> </property> <property name=&quot;homeAddress&quot; type=&quot;mypack.AddressUserType&quot; > <column name=&quot;HOME_STREET&quot; length=&quot;15&quot; /> <column name=&quot;HOME_CITY&quot; length=&quot;15&quot; /> <column name=&quot;HOME_PROVINCE&quot; length=&quot;15&quot; /> <column name=&quot;HOME_ZIPCODE&quot; length=&quot;6&quot; /> </property> <property name=&quot;comAddress&quot; type=&quot;mypack.AddressUserType&quot; > <column name=&quot;COM_STREET&quot; length=&quot;15&quot; /> <column name=&quot;COM_CITY&quot; length=&quot;15&quot; /> <column name=&quot;COM_PROVINCE&quot; length=&quot;15&quot; /> <column name=&quot;COM_ZIPCODE&quot; length=&quot;6&quot; /> </property>
第十章  Hibernate 的检索策略 hibernate 的检索策略简介 类级别和关联级别可选的检索策略及默认的检索策略 load get find load 运行时行为受影响的 session 的检索方法 一对多和多对多为立即检索 多对一和一对一关联为外连接检索 立即 默认的检索策略 立即 延迟 迫切左外连接检索 立即 延迟 可选的检索策略 类级别 关联级别 检索策略的作用域
第十章  Hibernate 的检索策略 三种检索策略的运行机制 hibernate 的检索策略简介 ( 续 ) 通过左外连接加载与检索方法指定的对象关联的对象。 延迟加载与检索方法指定的对象关联对象。可设定批量检索数量。 立即加载关联的对象、可设定批量检索数量 关联接别 不适用 延迟加载检索方法指定的对象 立即加载检索方法制定的对象 类级别 立即 延迟检索 迫切左外 检索策略的类型
第十章  Hibernate 的检索策略 hibernate 的检索策略简介 ( 续 ) 映射文件中用于设定检索策略的几个属性 合理取值 3~10 之间, class 和 set 存在。 如果为 true ,适用迫切左外连接检索。在 <many-to-one> 和 <one-to-one> <set> 中存在。 如果为 true ,延迟加载, class 和 set 有此属性 描述 1 <many-to-one> 和 <one-to-one> 中为 auto , 在 <set> 元素中为 false 。 false 默认值 正整数 auto true false true false 可选值 lazy out-join batch-size 属性
第十章  Hibernate 的检索策略 类级别的检索策略  立即 <class ...... lazy=“false”> 延迟检索 <class ...... lazy=“true”> if(!Hibernate.isInitialized(c)){ Hibernate.initialize(c); }
第十章  Hibernate 的检索策略 一对多和多对多关联的检索策略( set ) 无意义 延迟检索。 迫切左外联接。 立即检索 策略 true false true false out-join false false true true lazy
第十章  Hibernate 的检索策略 一对多和多对多关联的检索策略 立即检索 延迟检索 批量延迟检索 批量立即检索 迫切左外连接检索
第十章  Hibernate 的检索策略 多对一和一对一的检索策略 立即 延迟 迫切左外连接 迫切左外连接 迫切左外连接 延迟 检索 order 时对 customer 对象的检索策略 false true false true false true customer 类的 lazy 属性 auto auto true true false false order 类 <many-to-one> 的 outer-join 属性
第十章  Hibernate 的检索策略 比较三种检索策略 (1) 对应用程序完全透明,不管对象处于持久化状态还是游离状态,都可从一个对象导航到另一个对象。 (2) 使用了外连接, select 语句少 由应用程序决定需要加载哪些对象,可以避免执行多余的 select 语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间。 对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象 优点 (1) 多对一或一对一关联 (2) 需要立即访问的对象 (3) 数据库有良好的表连接性能。 (1) 一对多或者多对多关联 (2) 应用程序不需要立即访问或者根本不会访问的对象 (1) 类级别 (2) 应用程序需要立即访问的对象 (3) 使用了二级缓存 优先考虑使用的场合 (1) 可能会加载应用程序不需要访问的对象,浪费内存。 (2) 复杂的数据库表连接也会影响检索性能。 应用程序如果希望访问游离状态的代理类实例,必须保证她在持久化状态时已经被初始化。 (1)select 语句多 (2) 可能会加载应用程序不需要访问的对象,浪费许多内存空间。 缺点 立即检索 延迟检索 迫切左外连接检索 检索策略
第十一章  hibernate 检索方式 1 。对象导航图 2 。 OID 检索 3 。 HQL 检索 4 。 QBC 检索 5 。本地 SQL 检索
第十一章  hibernate 检索方式 检索方式简介 HQL 检索方式 1 。在查询语句中设定各种查询条件 2 。支持投影,仅检索出对象的部分属性 3 。支持分页 4 。连接查询 5 。分组查询 6 。内置聚集函数 7 。调用用户自定义的函数 8 。嵌入式查询 9 。动态绑定参数 Query query = session.createQuery(“from Customer as c where c.name=:custoerNa me and c.age = :customerAge”); query.setString(“customerName”,”Tom”); query.setInteger(“customerAge,21); query.list();
第十一章  hibernate 检索方式 检索方式简介 QBC 检索方式 主要由 Criteria 、 Criterion 接口和 Expression 类组成,他支持在运行时动态生成查询语句。 ------------------------------------------------------------------------------------------ Criteria criteria = session.createCriteria(Customer.class); Criterion c1 = Expression.like(“name”,”T%”); Criterion c2 = Expression.eq(“age”,new Integer(21)); criteria.add(c1) criteria.add(c2); criteria.list(); ------------------------------------------------------------------------------------------ 方法链编程: session.createCriteria(Customer.class).add(Expression.like(“name”,”%T”)) .add(Expression.eq(“age”,new Integer(21))) .list();
第十一章  hibernate 检索方式 检索方式简介 SQL 检索方式 Query query = session.createSQLQuery(“select {c.*} from CUSTOMERS c where  c.NAME like :customerName and c.AGE=:customerAge”,”c”, Customer.class); // 动态绑定参数 query.setString(“customerName”,”T%”); query.setInteger(“customerAge”,new Integer()21); // 执行 sql select 语句,返回查询结果。 List list = query.list();
第十一章  hibernate 检索方式 检索方式简介 使用别名 from Customer as c where c.name = :customerName as  可省略。
第十一章  hibernate 检索方式 检索方式简介 多态查询 session.createQuery(“from Employee”); 查询出所有的实体 from java.lang.serializable (支持接口) from java.lang.Object
第十一章  hibernate 检索方式 检索方式简介 对查询结果排序 hql  查询: session.createQuery(“from Employee c order by c.name”); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”)); 检索方式简介 分页查询 hql  查询: session.createQuery(“from Employee c order by c.name”).setFirstResult(97) .setMaxResults(10); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”)) .setFirstResult(97).setMaxResult(10).list();
第十一章  hibernate 检索方式 检索方式简介 检索单个对象 hql  查询: session.createQuery(“from Employee c order by c.name”) .setMaxResults(1).uniqueResult(); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”)) .setMaxResult(1).uniqueResult();
第十一章  hibernate 检索方式 检索方式简介 绑定参数 hql  查询: session.createQuery(“from Employee c where c.name =:customerName”); query.setString(“customer”,”Tom”); ---------------------------------------------------- ............................c.name=? query.setString(0,”Tom”);
第十一章  hibernate 检索方式 检索方式简介 在影射文件中定义命名查询语句 <class> ....... </class> <query name=“findCustomersByName”> <![CDATA[from Cusomter c where c.name like:name]]> </query> ------------------------------------------------------------------ query = session.getNamedQuery(“findCustomersByName”); query.setString(“name”,”Tom”); query.list();
第十一章  hibernate 检索方式 设定查询条件 Express.not(Express.in()) not in Express.between() between Express.not(Express.between()) not between 含义 Express.in() Express.isNotNull() Express.isNull() Express.le() Express.lt() Express.ge() Express.not(Express.eq()) Express.eq() QBC 运算方法 in is not null is null <= < >= <> = HQL 运算符 比较运算 范围运算符 运算类型
第十一章  hibernate 检索方式 设定查询条件 ( 续 ) Expression.or()| Expression.disjunction() or Expression.not() not 含义 Expression.and()| Expression.conjunction() Expression.like() QBC 运算方法 and like HQL 运算符 字符串模式匹配 逻辑 运算类型
第十一章  hibernate 检索方式 连接查询 适用于不存在关联关系的持久化类 不支持 ClassA,ClassB 交叉连接 不支持 right out join | out join 右外连接 迫切左外连接 左外连接 隐式内连接 不支持 不支持 left out join  out join FetchMode.EAGER left out join fetch out join fetch 适用于由关联关系的持久化类 适用范围 不支持 Criteria.createAlias() QBC 语法 inner join fetch | join fetch inner join | join HQL 语法 内连接 迫切内连接 程序中指定的连接查询类型
第十一章  hibernate 检索方式 连接查询 迫切左外连接 HQL: createQuery(“from Customer c left outer join fetch c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class).setFetchMode(“orders”,FetchMode.EAGER) .add(Expression.like(“name”,”T”,MatchMode.START))
第十一章  hibernate 检索方式 连接查询 左外连接 HQL: createQuery(“from Customer c left join c.orders o where c.name like ‘T%’”);
第十一章  hibernate 检索方式 连接查询 内连接 HQL: createQuery(“from Customer c inner join c.orders o where c.name like ‘T%’”); HQL: createQuery(“from Customer c join c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class). .add(Expression.like(“name”,”T”,MatchMode.START)) .createCriteria(“orders”) .add(Expression.like(“orderNumber”,”T”,MatchMode.START));
第十一章  hibernate 检索方式 连接查询 迫切内连接 HQL: createQuery(“from Customer c inner join fetch c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class). .setFetchMode(“orders”,FetchMode.EAGER) .createAlias(“orders”,”o”) .add(Expression.like(“this.name”,”T”,MatchMode.START)) .add(Expression.like(“o.orderNumber”,”T”,MatchMode.START))
第十一章  hibernate 检索方式 连接查询 隐式内连接 HQL: createQuery(“from Order o where o.customer.name like ‘T%’“); 等价于 : from Order o join o.customer c where c.name like ‘T%’ QBC: 不支持
第十一章  hibernate 检索方式 连接查询 右外连接 HQL: from Customer c right outer join c.orders o where o.name like ‘T%’  等价于 : from Customer c right join c.orders o where o.name like ‘T%’
第十一章  hibernate 检索方式 连接查询 使用 SQL 风格的交叉连接和隐式内连接 HQL: 交叉连接查询 :from Customer,Order  标准 SQL 风格的内连接 :from Customer c inner join c.orders SQL 风格的隐式内连接查询 :from Customer c,Order o where c.id = o.customer_id
第十一章  hibernate 检索方式 连接查询 关联级别运行时的检索策略 1. 若在 HQL 、 QBC 代码中没有显式指定检索策 略,使用映射文件中的检索策略。但 HQL 总是忽略 映射文件中设置的迫切左外连接检索策略。 2. 若代码中显示指定了检索策略,则覆盖映射文件中 的检索策略。 3. 目前的 hibernate 版本只允许在一个查询语句中迫切 左外连接检索一个集合。 4.HQL 支持各种各样的连接查询。
第十一章  hibernate 检索方式 报表查询 投影查询 指查询结果仅包括部分实体或实体的部分属 性。通过 select 来实现。 from Customer c join c.orders o where o.orderNumber like ‘T%’ 如果希望查询结果中只包含 Customer 对象,可使用以下形式: select c from Customer c join c.orders o where o.orderNumber like T%’ session.createQuery(“select c.id,c.name,o.orderNumber from Customer c join c.orders o where o.orderNumber like ‘T%’”) ----------------------------------------------------------------------------------- 对应的 sql 语句为: select c.ID,c.NAME,o.ORDER_NUMBER from CUSTOMERS c inner join  ORDERS o on c.ID-=o.CUSTOMER_ID where o.ORDER_NUMBER like’T%’ ------------------------------------------------------------------------------------ 过滤重复元素 createQuery(“select distinct c.name from customer c”);
第十一章  hibernate 检索方式 报表查询 使用聚集函数 createQuery(“select count(*) from Customer c”).uniqueResult(); createQuery(“select avg(c.age) from Customer  c”).uniqueResult(); createQuery(“select max(c.age),min(c.age) from  Customer c”).uniqueResult(); 分组查询 : createQuery(“select c.name,count(c) from Customer group by  c.name”);
第十一章  hibernate 检索方式 高级查询技巧 动态查询: session.createCriteria(Customer.class) .add(Expression.like(“name”,name.toLowerCase()),MatchMode.ANYWHERE) .add(Expression.eq(“age”,new Integer(11))); 集合过滤: hql : createQuery(“from Order o where o.customer=:customer and o.price>100  order by o.price”).setEntity(“customer”,customer).list(); 使用集合过滤: session.createFilter(customer.getOrders(),”where this.price > 100 order by this.price”).list(); 子查询: from Customer c where 1 < (select count(o) from c.orders o); 本地 SQL 查询: String sql=“select cs.ID as {c.id},cs.NAME as {c.name},cs.AGE as {c.age} from CUSTOMERS cs where cs.ID = 1”; Query query = session.createSQLQuery(sql,”c”,Customer.class); 第二个参数是类的别名,在 SQL 语句中,每个字段的别名必须位于打括号内。
第十一章  hibernate 检索方式 查询性能优化 iterate 方法 query1=session.createQuery(“from Customer c”); List result1 = query1.list(); Query query2 = session.createQuery(“from Customer c where c.age < 30”); Iterator it = query2.iterator(); query 接口的 iterate 方法首先检索 ID 字段,然后根据 ID 字段到一级缓存、二级缓存中查 找,有则返回,否则查库。
第十一章  hibernate 检索方式 查询性能优化 查询缓存 在 hibernate.properties 中的 hibernate.cache.use_query_cache=true query = session.createQuery(“from Cusotmer c where c.age>:age”); query.setInteger(“age”,new Integer(1)); query.setCacheable(true); ------ 如果想更加细粒度的控制查询缓存,可设置缓存区域 query.setCacheRegion(“customer”)
第十一章  hibernate 检索方式 小结 适合动态生成查询语句 支持动态查询,编程麻烦 对动态查询语句的支持 用户可扩展 criteria 接口 编译时被解析,更易排错 更加面向对象 不支持报表查询和子查询。有限的连接查询 将语句肢解成一组 criteria ,较差 QBC 检索 不具扩展性 运行时被解析 基于字符串形式的 sql 支持各种查询 优点:和 sql 相近,易读 HQL 检索 可读性 功能 查询语句形式 何时被解析 可扩展性 比较方面
数据库事务与并发 在应用中采用悲观锁和乐观锁 当 hibernate 向库中 save 或 update 一个对象时,会自动使用这种锁模式。该模式仅供 hibernate 使用,在应用程序中不该使用它。 同 LockMode.UPGRADE. 对于 oracle ,执行 select ... for update no wait 语句, nowait 表明如果执行该语句的事务不能立即获得悲观锁,不会等待其他事务解锁,而是立即抛出一个异常。 不管缓存有无,都查库,同上,如果数据库系统支持悲观锁,执行 select ... for update 操作,否则执行普通的 sql 语句。 不管缓存中是否存在,都查库,如果映射文件中设置了版本元素,就执行版本检查,比较缓存中的对象和库中的版本是否一致。 如果缓存中存在该对象则返回,否则查库,默认值。 LockMode.NONE LockMode.READ LockMode.UPGRADE LockMode.UPGRADE_NOWAIT LockMode.WRITE session.get(Accout.class,new Long(1),LockMode.UPGRADE)
数据库事务与并发 在应用中采用悲观锁和乐观锁 由应用程序实现悲观锁 如果数据库不支持 select ... for update 语句时,可由应用程序来实现悲观锁。这需要在 表中建个锁字段,可以是布尔值。 true 表示锁定态, false 表示空闲态。 步骤: 1 。根据 lock 字段判段记录的状态 2 。若锁定了,一直等待。直到空闲。 3 。如果空闲,改成锁定态。 4 。更新记录,改称空闲态,解除锁定。
数据库事务与并发 在应用中采用悲观锁和乐观锁 利用 hibernate 的版本控制实现乐观锁 <version> 和 <timestamp> 都具有版本控 制的功能, <verion> 利用一个递增的整数 来跟踪记录的版本, <timestamp> 用时间 戳来跟踪记录的版本。 使用版本: create table a( ... VERSION intger ... ) 使用版本: <id name=“*” column=“”> <generator ..> </id> <version name=“version”  column=“VERSION”> 使用版本: class Account{ ... private int version; ... } 在影射文件中, <verion> 元素必须跟在 <id> 之后。
数据库事务与并发 在应用中采用悲观锁和乐观锁 利用 hibernate 的版本控制实现乐观锁 使用 <timestamp> 除了 <version> 元素外, <timestamp> 元素也同样的版本控制功能。使用 <timestamp> 元素步骤如下: 使用版本: create table a( ... timestamp timestamp; ... ) 使用版本: <id name=“*” column=“”> <generator ..> </id> <timestamp name=“timestamp”  column=“TIMESTAMP”> 使用版本: class Account{ ... private Date timestamp; ... } 在影射文件中, <timestamp> 元素必须跟在 <id> 之后。
数据库事务与并发 比较 Session 的 lock() 方法与 update() 方法 会计划执行一个 update 语句 update .. where id=1 and VERSION=0; 当清理缓存时才会执行这个 update 语句,并进行版本检查,如果库中没有匹配的记录,抛出 StaleObjectStateException 异常 不会计划执行一个 update 语句。 执行 update 方法时不会立即进行版本检查,只有当 session 在清理缓存时,真正执行 update 语句时才进行版本检查。 udate() 都能使一个游离对象与当前会话关联 如果设定了 LockMode.READ 模式,则立即进行版本检查,执行类似以下形式的 select 语句: select ID from ACCOUNTS where ID=1 and VERSION=0; 如果数据库中没有匹配的记录,就抛出 StaleObjectStateException. lock() 相似之处 不同之处 比较两个方法
影射继承关系 关系树的每个具体类对应一个表 companys 表 -------------- ID NAME HE 表 -------------- ID<pk> Custome_ID<fk> NAME SE 表 -------------- ID<pk> company_id<fk> NAME
影射继承关系 company 类 SE 类 HE 类 Employee 类 company.hbm.xml SE.hbm.xml HE.hbm.xml company 表 SE 表 HE 表
影射继承关系 关系树的每个具体类对应一个表 <class name=“HE”...> ... <propery name=“rate” type=“string” column=“RATE”> ... </class> <class name=“SE”...> ... <propery name=“salary” type=“string” column=“RATE”> ... </class>
影射继承关系 关系树的根类对应一个表 company 类 SE 类 HE 类 Employee 类 company.hbm.xml Employee.hbm.xml company 表 Employee 表
影射继承关系 <class name=“employee” table=“employee”> <id ...></id> <discriminator column=“EMPLOYEE_TYPE” type=“string”/> ... <subclass name=“HE” discriminator-value=“HE”> <propery name=“rate” column=“RATE” type=“double”/> </subclass> <subclass name=“SE” discriminator-value=“SE”> <propery name=“salary” column=“SALARY” type=“double”/> </subclass> </class>
映射继承关系 每个类对应一个表 <class name=“employee” table=“employee”> <id ...> </id> ... <joined-subclass name=“HE” table=“HE”> <key column=“employee_id”/> <property name=“salary” column=“salary” type=“string”> </joined-subclass> <joined-subclass name=“SE” table=“SE”> <key column=“employee_id”/> <property name=“rate” column=“rate” type=“string”> </joined-subclass> </class>
映射继承关系 映射多对一多态关联 ClassD ClassB ClassC ClassA
映射继承关系 映射多对一多态关联 表 D ----------- ID(PK) A_TYPE A_ID D1 表 B --------- A1 B1 表 C --------- A1 B1
映射继承关系 映射多对一多态关联 <any name=“a” meta-type=“string” id-type=“long” cascade=“save-update”> <meta-value value=“B” class=“ClassB” /> <meta-value value=“C” class=“ClassC” /> <column name=“A_TYPE” /> <column name=“A_ID” /> </any>
第十六章 映射值类型集合 set: 集合中的对象不按特定的方式排序,每 又重复对象。 TreeSet 能按照特定方式 排序。 list: 集合中的对象按索引位置排序,可有重 复对象,允许按照对象在集合中的索引 位置检索对象。 map: 集合中的每个元素包含一个键值对, 没有重复的 key 对象, value 对象可重复。 TreeMap 按特定方式排序。
第十六章 映射值类型集合 映射 set <set name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID”> <element column=“FILENAME” type=“string” not-null> </set> name: 指定 customer 类的 images 属性名 table: 指定和 images 属性对应的表为 images 。 lazy: 如果为 true ,表示延迟检索。 Customer 中有一个集合类型的属性 images ,用来存放所有的图片名,则在 Customer 中的定义如下: Set images = new HashSet(); Customers 表 ID<<pk>> ... images 表 Customer_id(fk) FileName(pk)
第十六章 映射值类型集合 映射 Bag <idbag name=“images” table=“IMAGES” lazy=“true”> <colllection-id type=“long” column=“ID”> <generator class=“increment”/> </collection-id> <key column=“CUSTOMER_ID” /> <element column=“FILENAME” type=“string” not-null=“true”> </idbag> bag 集合中的对象不按特定方式排序,但允许有重复对象。 java 集合的 API 中没有提供 bag 接口, hibernate 允许在持久化类中用 list 来模拟 bag 行为。如果 images 集合中允 许存放重复的文件名。可定义为: List images = new ArrayList(); ... Customers 表 ID<<PK>> ... images 表 ID<<PK>> Customer_id<<FK>> FileName(pk)
第十六章 映射值类型集合 映射 List <list name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID” /> <index column=“position”/> <element column=“FILENAME” type=“string” not-null=“true”> </list> Customers 表 ID<<PK>> ... images 表 Customer_id<<FK>><<PK>> position<<PK>> FileName 如果希望 images 集合中的元素允许存放重复的元素,并且按照索引位置排序,首先应 在 images 表中定位一个 position 字段,代表每个元素在集合中的索引位置。
第十六章 映射值类型集合 映射 Map <map name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID” /> <index column=“image_name” type=“string”/> <element column=“FILENAME” type=“string” not-null=“true”> </list> 如果 images 集合中的每一个元素包含一对 key/value 对,那么应该把 images 集合定义 成 map 类型。 Map images = new HashMap(); Customers 表 ID<<PK>> ... images 表 Customer_id<<FK>><<PK>> image_name<<PK>> FileName
第十六章 映射值类型集合 对集合排序 hibernate 对集合中的元素支持两种排序方式 : 1. 在数据库中排序 : 简称为数据库排序 , 当 hibernate 通过 select 语句到数据库中检索集 合对象时 , 利用 order by 子句进行排序。 2. 在内存中排序 , 利用 java 集合的排序功能进行 排序 , 可选择自然排序和客户化排序。 hibernate 用 sort 属性来设置内存排序,用 order- by 属性设置数据库排序。  支持 支持 <map> 不支持 不支持 <list> 支持 不支持 <idbag> 支持 支持 <set> sort order-by 排序属性
第十六章 映射值类型集合 对集合排序 在数据库中对集合排序 <set> <idbag> <map> 元素都有 order-by 属性,若设置了该属性,当 hibernate 通 过 select 语句检索对象时,利用 order by 子句进行排序。 <set name=“images” table=“IMAGES” lazy=“true”  order-by=“FILENAME asc” > <key column=“CUSOTMER_ID” /> <element column=“FILENAME” type=“string” not-null=“true” /> </set> 在 order-by 属性中还可加入 sql 函数,例如: <set name=“images” table=“IMAGES”  order-by=“lower(FILENAME) asc” > ... </set>
第十六章 映射值类型集合 对集合排序 在数据库中对集合排序 ( 续 ) 对键对象排序: <map name=“images” table=“IMAGES” lazy=“true”  order-by=“IMAGE_NAME” > ...... </ map > 对值对象排序: <map name=“images” table=“IMAGES” lazy=“true”  order-by=“FILENAME” > ...... </ map > 按 ID 代理主键排序: <idbag name=“images” table=“IMAGES” lazy=“true”  order-by=“ID” > ...... </idbag>
第十六章 映射值类型集合 对集合排序 在内存中对集合排序 ( 续 ) <set> 和 <map> 都具有 sort 属性,如设置了该属性可对内存中的集合对象进行排序。 <set> 元素在内存中对集合排序 : <set name=“images” table=“images” lazy=“true” sort=“natural”> ....... </set> <set> 元素的 sort 属性为 natural ,表示对 images 集合中的字符串进行自然排序。 <set> 元素也支持客户化排序。需要实现 Comparator 接口。 <set name=“images” table=“images” lazy=“true” sort=“mypack.MyComparator”> ....... </set> 按 ID 代理主键排序: <idbag name=“images” table=“IMAGES” lazy=“true”  order-by=“ID” > ...... </idbag>
第十六章 映射值类型集合 对集合排序 在内存中对集合排序 ( 续 ) <map> 元素在内存中对集合排序 : <map name=“images” table=“images” lazy=“true” sort=“natural”> ....... </map> <map> 元素的 sort 属性为 natural ,表示对 images 集合中的字符串进行自然排序。 <map> 元素也支持客户化排序。需要实现 Comparator 接口。 <map name=“images” table=“images” lazy=“true” sort=“mypack.MyComparator”> ....... </map>
第十六章 映射值类型集合 映射组件类型的集合 Customer ----------- name age images Image ----------- name filename sizeX sizeY Customer 1 0..n Image 类作为一种值类型,没有 OID ,此外,由于 Image 对象会存放在 java 集合 中,为了保证 java 集合类正常工作,应该在 image 类中实现 equals() 和 hashCode() 方法。 <set name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID” /> <composite-element class=“mypack.Image”> <parent name=“customer” /> <property name=“name” column=“IMAGE_NAME” not-null=“true” /> ...... </composite-element> </set>
第十六章 映射值类型集合 映射组件类型的集合 ( 续 ) <idbag name=“images” table=“IMAGES” lazy=“true”> <collection-id type=“long” column=“ID” > <generator class=“increment” /> </collection-id> <key column=“CUSTOMER_ID” /> <composite-element class=“mypack.Image”> <parent name=“customer” /> <property name=“name” column=“IMAGE_NAME” not-null=“true” /> ...... </composite-element> </idbag>
第十六章 映射值类型集合 映射组件类型的集合 ( 续 ) <map name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID” /> <index type=“string” column=“IMAGE_NAME” /> <composite-element class=“mypack.Image”> <parent name=“customer” /> <property name=“name” column=“IMAGE_NAME” not-null=“true” /> ...... </composite-element> </map>
第十七章 映射实体关联关系 映射一对一关联 按照外键映射 CUSTOMERS 表 --------------- ID<<PK>> NAME HOME_ADDRESS<<FK>> COM_ADDRESS<<FK>> ADDRESSS 表 --------------- ID<<PK>> CITY STREET PROVINCE customer.hbm.xml : <many-to-one name=“homeAddress” class=“mypack.Address” column=“HOME_ADDRESS” cascade=“all” unique=“true” /> <many-to-one name=“comAddress” class=“mypack.Address” column=“COM_ADDRESS” cascade=“all” unique=“true” /> address.hbm.xml <one-to-one name=“customer” class=“mypack.Customer” property-ref=“homeAddress” /> one-to-one 元素的 property-ref 属性为 homeAddress, 表明建立了从 homeAddress 对象到 Cusotmer 对象的关联。
第十七章 映射实体关联关系 映射一对一关联 按照主键映射 CUSTOMERS 表 --------------- ID<<PK>> NAME ADDRESSS 表 --------------- ID<<PK>><<FK>> CITY STREET PROVINCE customer.hbm.xml : <one-to-one name=“address” class=“mypack.Address” cascade=“all” /> address.hbm.xml <one-to-one name=“customer” class=“mypack.Customer” constraint=“true” /> one-to-one 元素的 constraint 属性为 true, 表明 Address 表的 ID 主键同时作为外键参照 Customers 表。在 address.hbm.xml 文件中,必须为 OID 使用 foreign 标识符生成策略。 <id name=“id” type=“long” column=“ID”> <generator class=“foreign”> <param name=“property”>customer</param> </generator> </id>
第十七章 映射实体关联关系 映射单向多对多关联 CATEGORIES 表 ---------------- ID<<PK>> NAME CATEGORY_ITEM 表 ---------------- CATEGORY_ID<<PK>><<FK>> ITEM_ID<<FK>><<PK>> ITEMS 表 ---------------- ID<<PK>> NAME BASIC_PRICE
Ad

More Related Content

What's hot (15)

An introduce to n hibernate (part 1) pub
An introduce to n hibernate (part 1) pubAn introduce to n hibernate (part 1) pub
An introduce to n hibernate (part 1) pub
jiangxu
 
Ajax Lucence
Ajax LucenceAjax Lucence
Ajax Lucence
Roger Xia
 
第五章:Struts2标签库
第五章:Struts2标签库第五章:Struts2标签库
第五章:Struts2标签库
shmily7788
 
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 SpringSpring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Justin Lin
 
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit TestingASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
江華 奚
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
appollo0312
 
Spring 2.x 中文
Spring 2.x 中文Spring 2.x 中文
Spring 2.x 中文
Guo Albert
 
Java相关基础知识
Java相关基础知识Java相关基础知识
Java相关基础知识
yiditushe
 
中心教员J2 Ee面试题
中心教员J2 Ee面试题中心教员J2 Ee面试题
中心教员J2 Ee面试题
yiditushe
 
Java SE 7 技術手冊 - 課後練習解答
Java SE 7 技術手冊 - 課後練習解答Java SE 7 技術手冊 - 課後練習解答
Java SE 7 技術手冊 - 課後練習解答
Justin Lin
 
领域驱动设计实践
领域驱动设计实践领域驱动设计实践
领域驱动设计实践
Jacky Chi
 
Java SE 7 技術手冊第六章草稿 - 何謂繼承?
Java SE 7 技術手冊第六章草稿 - 何謂繼承?Java SE 7 技術手冊第六章草稿 - 何謂繼承?
Java SE 7 技術手冊第六章草稿 - 何謂繼承?
Justin Lin
 
An introduce to n hibernate (part 1) pub
An introduce to n hibernate (part 1) pubAn introduce to n hibernate (part 1) pub
An introduce to n hibernate (part 1) pub
jiangxu
 
Ajax Lucence
Ajax LucenceAjax Lucence
Ajax Lucence
Roger Xia
 
第五章:Struts2标签库
第五章:Struts2标签库第五章:Struts2标签库
第五章:Struts2标签库
shmily7788
 
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 SpringSpring 2.0 技術手冊第六章 - Hibernate 與 Spring
Spring 2.0 技術手冊第六章 - Hibernate 與 Spring
Justin Lin
 
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit TestingASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
江華 奚
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
appollo0312
 
Spring 2.x 中文
Spring 2.x 中文Spring 2.x 中文
Spring 2.x 中文
Guo Albert
 
Java相关基础知识
Java相关基础知识Java相关基础知识
Java相关基础知识
yiditushe
 
中心教员J2 Ee面试题
中心教员J2 Ee面试题中心教员J2 Ee面试题
中心教员J2 Ee面试题
yiditushe
 
Java SE 7 技術手冊 - 課後練習解答
Java SE 7 技術手冊 - 課後練習解答Java SE 7 技術手冊 - 課後練習解答
Java SE 7 技術手冊 - 課後練習解答
Justin Lin
 
领域驱动设计实践
领域驱动设计实践领域驱动设计实践
领域驱动设计实践
Jacky Chi
 
Java SE 7 技術手冊第六章草稿 - 何謂繼承?
Java SE 7 技術手冊第六章草稿 - 何謂繼承?Java SE 7 技術手冊第六章草稿 - 何謂繼承?
Java SE 7 技術手冊第六章草稿 - 何謂繼承?
Justin Lin
 

Viewers also liked (16)

Thinking Beyond ORM in JPA
Thinking Beyond ORM in JPAThinking Beyond ORM in JPA
Thinking Beyond ORM in JPA
Patrycja Wegrzynowicz
 
Spring Transaction Management
Spring Transaction ManagementSpring Transaction Management
Spring Transaction Management
Ye Win
 
Effective Spring Transaction Management
Effective Spring Transaction ManagementEffective Spring Transaction Management
Effective Spring Transaction Management
UMA MAHESWARI
 
Spring transaction part4
Spring transaction   part4Spring transaction   part4
Spring transaction part4
Santosh Kumar Kar
 
Spring Transaction
Spring TransactionSpring Transaction
Spring Transaction
patinijava
 
Spring Framework - Data Access
Spring Framework - Data AccessSpring Framework - Data Access
Spring Framework - Data Access
Dzmitry Naskou
 
Spring Data JPA - Repositories done right
Spring Data JPA - Repositories done rightSpring Data JPA - Repositories done right
Spring Data JPA - Repositories done right
Oliver Gierke
 
Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
Cheng Ta Yeh
 
Hibernate ORM: Tips, Tricks, and Performance Techniques
Hibernate ORM: Tips, Tricks, and Performance TechniquesHibernate ORM: Tips, Tricks, and Performance Techniques
Hibernate ORM: Tips, Tricks, and Performance Techniques
Brett Meyer
 
Introduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examplesIntroduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examples
ecosio GmbH
 
JPA and Hibernate
JPA and HibernateJPA and Hibernate
JPA and Hibernate
elliando dias
 
ORM, JPA, & Hibernate Overview
ORM, JPA, & Hibernate OverviewORM, JPA, & Hibernate Overview
ORM, JPA, & Hibernate Overview
Brett Meyer
 
Overview of JPA (Java Persistence API) v2.0
Overview of JPA (Java Persistence API) v2.0Overview of JPA (Java Persistence API) v2.0
Overview of JPA (Java Persistence API) v2.0
Bryan Basham
 
JPA Best Practices
JPA Best PracticesJPA Best Practices
JPA Best Practices
Carol McDonald
 
Intro To Hibernate
Intro To HibernateIntro To Hibernate
Intro To Hibernate
Amit Himani
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By Step
Guo Albert
 
Spring Transaction Management
Spring Transaction ManagementSpring Transaction Management
Spring Transaction Management
Ye Win
 
Effective Spring Transaction Management
Effective Spring Transaction ManagementEffective Spring Transaction Management
Effective Spring Transaction Management
UMA MAHESWARI
 
Spring Transaction
Spring TransactionSpring Transaction
Spring Transaction
patinijava
 
Spring Framework - Data Access
Spring Framework - Data AccessSpring Framework - Data Access
Spring Framework - Data Access
Dzmitry Naskou
 
Spring Data JPA - Repositories done right
Spring Data JPA - Repositories done rightSpring Data JPA - Repositories done right
Spring Data JPA - Repositories done right
Oliver Gierke
 
Hibernate ORM: Tips, Tricks, and Performance Techniques
Hibernate ORM: Tips, Tricks, and Performance TechniquesHibernate ORM: Tips, Tricks, and Performance Techniques
Hibernate ORM: Tips, Tricks, and Performance Techniques
Brett Meyer
 
Introduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examplesIntroduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examples
ecosio GmbH
 
ORM, JPA, & Hibernate Overview
ORM, JPA, & Hibernate OverviewORM, JPA, & Hibernate Overview
ORM, JPA, & Hibernate Overview
Brett Meyer
 
Overview of JPA (Java Persistence API) v2.0
Overview of JPA (Java Persistence API) v2.0Overview of JPA (Java Persistence API) v2.0
Overview of JPA (Java Persistence API) v2.0
Bryan Basham
 
Intro To Hibernate
Intro To HibernateIntro To Hibernate
Intro To Hibernate
Amit Himani
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By Step
Guo Albert
 
Ad

Similar to Hibernate教程 (20)

中远公司 Java培训资料
中远公司  Java培训资料中远公司  Java培训资料
中远公司 Java培训资料
yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
yiditushe
 
NHibernate分享(1) share
NHibernate分享(1) shareNHibernate分享(1) share
NHibernate分享(1) share
Xu Huang
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试
lydiafly
 
Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫
Justin Lin
 
Java Script 引擎技术
Java Script 引擎技术Java Script 引擎技术
Java Script 引擎技术
bigqiang zou
 
Mybatis学习培训
Mybatis学习培训Mybatis学习培训
Mybatis学习培训
flynofry
 
Flex 4.5 action custom component development
Flex 4.5 action custom component developmentFlex 4.5 action custom component development
Flex 4.5 action custom component development
jexchan
 
網站設計100步
網站設計100步網站設計100步
網站設計100步
evercislide
 
Sql Alchemy Story
Sql Alchemy StorySql Alchemy Story
Sql Alchemy Story
Zoom Quiet
 
运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践
Li JianYe
 
Real World ASP.NET MVC
Real World ASP.NET MVCReal World ASP.NET MVC
Real World ASP.NET MVC
jeffz
 
000 北京圣思园教育科技有限公司第一期面授培训大纲
000 北京圣思园教育科技有限公司第一期面授培训大纲000 北京圣思园教育科技有限公司第一期面授培训大纲
000 北京圣思园教育科技有限公司第一期面授培训大纲
ArBing Xie
 
Spring4.x + hibernate4.x_配置详解
Spring4.x + hibernate4.x_配置详解Spring4.x + hibernate4.x_配置详解
Spring4.x + hibernate4.x_配置详解
zany_hui
 
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 -  回歸到最純樸的開發山頂洞人日記 -  回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發
koji lin
 
Kid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese VersionKid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese Version
Frank S.C. Tseng
 
中远公司 Java培训资料
中远公司  Java培训资料中远公司  Java培训资料
中远公司 Java培训资料
yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
yiditushe
 
NHibernate分享(1) share
NHibernate分享(1) shareNHibernate分享(1) share
NHibernate分享(1) share
Xu Huang
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试
lydiafly
 
Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫
Justin Lin
 
Java Script 引擎技术
Java Script 引擎技术Java Script 引擎技术
Java Script 引擎技术
bigqiang zou
 
Mybatis学习培训
Mybatis学习培训Mybatis学习培训
Mybatis学习培训
flynofry
 
Flex 4.5 action custom component development
Flex 4.5 action custom component developmentFlex 4.5 action custom component development
Flex 4.5 action custom component development
jexchan
 
網站設計100步
網站設計100步網站設計100步
網站設計100步
evercislide
 
Sql Alchemy Story
Sql Alchemy StorySql Alchemy Story
Sql Alchemy Story
Zoom Quiet
 
运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践运维系统开发与Rails 3页面开发实践
运维系统开发与Rails 3页面开发实践
Li JianYe
 
Real World ASP.NET MVC
Real World ASP.NET MVCReal World ASP.NET MVC
Real World ASP.NET MVC
jeffz
 
000 北京圣思园教育科技有限公司第一期面授培训大纲
000 北京圣思园教育科技有限公司第一期面授培训大纲000 北京圣思园教育科技有限公司第一期面授培训大纲
000 北京圣思园教育科技有限公司第一期面授培训大纲
ArBing Xie
 
Spring4.x + hibernate4.x_配置详解
Spring4.x + hibernate4.x_配置详解Spring4.x + hibernate4.x_配置详解
Spring4.x + hibernate4.x_配置详解
zany_hui
 
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 -  回歸到最純樸的開發山頂洞人日記 -  回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發
koji lin
 
Kid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese VersionKid171 chap03 traditional Chinese Version
Kid171 chap03 traditional Chinese Version
Frank S.C. Tseng
 
Ad

More from Shilong Sang (16)

C:\Documents And Settings\User\桌面\Installation Guide O Oo3
C:\Documents And Settings\User\桌面\Installation Guide O Oo3C:\Documents And Settings\User\桌面\Installation Guide O Oo3
C:\Documents And Settings\User\桌面\Installation Guide O Oo3
Shilong Sang
 
7月~12月份影片概况 0703更新
7月~12月份影片概况 0703更新7月~12月份影片概况 0703更新
7月~12月份影片概况 0703更新
Shilong Sang
 
Sexix
SexixSexix
Sexix
Shilong Sang
 
groovy经典入门
groovy经典入门groovy经典入门
groovy经典入门
Shilong Sang
 
针对 Java程序员的 U M L概述
针对 Java程序员的 U M L概述针对 Java程序员的 U M L概述
针对 Java程序员的 U M L概述
Shilong Sang
 
《狭义与广义相对论浅说》
《狭义与广义相对论浅说》《狭义与广义相对论浅说》
《狭义与广义相对论浅说》
Shilong Sang
 
自己动手写操作系统
自己动手写操作系统自己动手写操作系统
自己动手写操作系统
Shilong Sang
 
《最后期限》
《最后期限》《最后期限》
《最后期限》
Shilong Sang
 
webwork2guide
webwork2guidewebwork2guide
webwork2guide
Shilong Sang
 
Spring基础教程
Spring基础教程Spring基础教程
Spring基础教程
Shilong Sang
 
spring_jiaocheng
spring_jiaochengspring_jiaocheng
spring_jiaocheng
Shilong Sang
 
oracle
oracleoracle
oracle
Shilong Sang
 
Spring课件
Spring课件Spring课件
Spring课件
Shilong Sang
 
Spring课件
Spring课件Spring课件
Spring课件
Shilong Sang
 
groovy
groovygroovy
groovy
Shilong Sang
 
C:\Documents And Settings\User\桌面\Installation Guide O Oo3
C:\Documents And Settings\User\桌面\Installation Guide O Oo3C:\Documents And Settings\User\桌面\Installation Guide O Oo3
C:\Documents And Settings\User\桌面\Installation Guide O Oo3
Shilong Sang
 
7月~12月份影片概况 0703更新
7月~12月份影片概况 0703更新7月~12月份影片概况 0703更新
7月~12月份影片概况 0703更新
Shilong Sang
 
groovy经典入门
groovy经典入门groovy经典入门
groovy经典入门
Shilong Sang
 
针对 Java程序员的 U M L概述
针对 Java程序员的 U M L概述针对 Java程序员的 U M L概述
针对 Java程序员的 U M L概述
Shilong Sang
 
《狭义与广义相对论浅说》
《狭义与广义相对论浅说》《狭义与广义相对论浅说》
《狭义与广义相对论浅说》
Shilong Sang
 
自己动手写操作系统
自己动手写操作系统自己动手写操作系统
自己动手写操作系统
Shilong Sang
 
《最后期限》
《最后期限》《最后期限》
《最后期限》
Shilong Sang
 
Spring基础教程
Spring基础教程Spring基础教程
Spring基础教程
Shilong Sang
 

Hibernate教程

  • 1. 精通 Hibernate java 对象持久化技术祥解 Hibernate 入门 OR 映射技术 通过 Hibernate API 操纵数据库 检索策略和方式 数据库事务、并发、缓存与性能优化 高级配置。
  • 2. Hibernate 入门 案例 Hibernate 关系数据库 Customer 类 BusinessService 类 对象关系型映射 Hibernate API Hibernate 配置文件 Customers 表
  • 3. Hibernate 入门 创建配置文件 hibernate.dialect=net.sf.hibernate.dialect.OracleDialect hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver hibernate.connection.url=jdbc:oracle:thin:peopres/[email protected]:1521:oracle9 hibernate.connection.username=peopres hibernate.connection.password=peopres hibernate.show_sql=true
  • 4. Hibernate 入门 创建持久化类 public class Customer implements Serializable { private static final long serialVersionUID = 5431991012351413505L; private Long id; private String name; private String email; …… public Customer() { } public Long getId() { return id; } public void setId(Long id) { this .id = id; } public String getName() { return name; }
  • 5. Hibernate 入门 创建数据库 drop database if exists SAMPLEDB; create database SAMPLEDB; use SAMPLEDB; create table CUSTOMERS ( ID bigint not null primary key, NAME varchar(15) not null, EMAIL varchar(128) not null, PASSWORD varchar(8) not null, PHONE int , ADDRESS varchar(255), SEX char(1) , IS_MARRIED bit, DESCRIPTION text, IMAGE blob, BIRTHDAY date, REGISTERED_TIME timestamp );
  • 6. Hibernate 入门 创建对象 - 关系映射文件 <hibernate-mapping> <class name=&quot;mypack.Customer&quot; table=&quot;CUSTOMERS&quot;> <!--id 主键 --> <id name=&quot;id&quot; column=&quot;ID&quot; type=&quot;long&quot;> <generator class=&quot;increment&quot; /> </id> <!-- 名称 --> <property name=&quot;name&quot; column=&quot;NAME&quot; type=&quot;string&quot; not-null=&quot;true&quot; /> …… </class> </hibernate-mapping>
  • 7. Hibernate 入门 把 customer 持久化类映射到 customers 表 <class>: 类和表的映射 <class name=&quot;mypack.Customer“ table=&quot;CUSTOMERS&quot;> <id>: 持久化类的 OID 和表主键映射 <id name=&quot;id&quot; column=&quot;ID&quot; type=&quot;long&quot;> <generator class=&quot;increment&quot; /> </id> <property> <property name=&quot;email&quot; column=&quot;EMAIL&quot; type=&quot;string&quot; not-null=&quot;true&quot; />
  • 8. Hibernate 入门 java 、 hibernate 、 sql 类型对应关系 TIMESTAMP REGISTERED_TIME timestamp java.sql.TimeStamp registeredTime DATE BIRTHDAY date java.sql.Date birthday BLOB CLOB BIT CHAR(1) INT Varchar(15) Sql 类型 IMAGE DESCRIPTION IS_MARRIED SEX PHONE NAME Cutomers 字段名 binary text boolean character int string hibernate byte[] java.lang.String boolean char int java.lang.String java Phone Sex Married Description Name image Customer 类属性
  • 9. Hibernate 入门 通过 API 操作数据库
  • 10. Hibernate 入门 通过 API 操作数据库
  • 11. Hibernate 入门 Hibernate 初始化 1 、创建 configuration 对象,把 hibernate.properties 文件读入内存。 2 、 add (……)把映射文件读入内存 3 、 buildSessionFactory ()数据源。重量级对象。
  • 12. Hibernate 入门 Hibernate 初始化 访问 Session 接口 save() update() delete() load() find()
  • 14. 第一章 Java 对象持久化概述 Hibernate 是什么 连接 java 应用程序和关系型数据库的中间件 对 JDBC API 封装,负责对象持久化 位于持久化层,封装所有的数据访问细节,使业务逻辑层更关注于业务逻辑。 一种 ORM 映射工具。
  • 15. 第一章 Java 对象持久化概述 应用程序的分层体系结构 数据库 应用程序层 数据库 表述层 应用程序层 双层体系结构 三层体系结构 表述层:提供与用户交互的 GUI 。 业务逻辑层:实现各种业务逻辑。 数据库层:负责存放和管理应用的持久性数据。
  • 16. 第一章 Java 对象持久化概述 应用程序的分层体系结构 区分物理层和逻辑层 物理分层:每一层运行在单独的机器上,意味 着创建分布式软件系统。 逻辑分层:在单个的软件模块中完成特定的功 能。 不作特别说明,软件分层指的是逻辑分层。
  • 17. 第一章 Java 对象持久化概述 应用程序的分层体系结构 软件层的特征 1. 每个层由一组相关的类或组件构成,共同完 成特定功能。 2. 层之间存在自上而下的依赖关系。不存在 跨层访问。 3. 每个层对上层公开 API ,但具体的实现细节 对外透明。
  • 18. 第一章 Java 对象持久化概述 应用程序的分层体系结构 软件分层的优点 1. 伸缩性 : 能否支持更多用户。 2. 可维护性 : 需求变化时,影响一部分,不影 响其它部分的代码。 3. 可扩展性 : 增加薪功能的难以程度。 4. 可重用性 : 代码没冗余,满足多种需求。 5. 可管理性 : 管理系统的难易程度。
  • 19. 第一章 Java 对象持久化概述 应用程序的分层体系结构 软件分层缺点 1. 设计人员要求高 2. 体细结构合理划分,耗时大 3. 调试困难 4. 对于规模较小的应用,软件分层会降低开发 效率。
  • 20. 第一章 Java 对象持久化概述 应用程序的分层体系结构 Java 应用的持久化层 表述层 业务逻辑层 数据库层 表述层 业务逻辑层 持久化层 数据库层
  • 21. 第一章 Java 对象持久化概述 Hibernate 中间件特性 应用 1 业务逻辑层 应用 2 业务逻辑层 应用 3 业务逻辑层 持久化层 (hibernate) 数据库 1 数据库 2 数据库 3 持久化层封装了数据访问的细节,为业务逻辑层提供了面向对象的 API 。完善的持久化层应该 达到的目标: 1. 代码重用性高,可完成所有的数据访问操作。 2. 如果需要的话,能够支持多种数据库平台。 3. 具有相对独立性,当持久化层变化时,不会影响上层实现。
  • 22. 第一章 Java 对象持久化概述 软件模型 概念模型:模拟问题域中的真实实体。描述每个实体的概念和属性及实体间关系。不描述实体行为。实体间的关系有一对一、一对多和多对多。 客户 Name age 订单 orderNumber price 1 *
  • 23. 第一章 Java 对象持久化概述 软件模型 关系数据模型:在概念模型的基础上建立起来的,用于描述这些关系数据的静态结构。有以下内容组成: 1. 若干表 2. 表的所有索引 3. 视图 4. 触发器 5. 表与表之间的参照完整性 Customers 表 ID<PK> NAME AGE ORDERS 表 ID<pk> CustomerID<fk> Order_number price
  • 24. 第一章 Java 对象持久化概述 软件模型 域模型:在软件的分析阶段创建概念模型,在软件设计阶段创建域模型。 组成部分: 1. 具有状态和行为的域对象。 2. 域对象之间的关联。
  • 25. 第一章 Java 对象持久化概述 软件模型 域对象 (domain object): 构成域模型的基本元素就是域对象。对真实世界的实体的软件抽象,也叫做业务对象 (Business Object(BO)). 域对象可代表业务领域中的人、地点、事物或概念。 域对象分为以下几种 : 实体域对象:通常是指业务领域中的名词。 (plain old java object) 。 过程域对象:应用中的业务逻辑或流程。依赖 于实体域对象,业务领域中的动词。如 发出订单、登陆等。 事件域对象:应用中的一些事件(警告、异常)。
  • 26. 第一章 Java 对象持久化概述 软件模型 域对象间的关系 1. 关联:类间的引用关系。以属性定义的方式表现。 关联可分为一对一、一对多和多对多。 还可分为单项关联和双向关联。 Order Customer
  • 27. 第一章 Java 对象持久化概述 软件模型 域对象间的关系 2. 依赖:类之间访问关系。无需定义成属性。在 A 中访问 B 中的 方法或属性,或者 A 负责实例化 B 。 BusinessService Customer
  • 28. 第一章 Java 对象持久化概述 软件模型 域对象间的关系 3. 聚集 (Aggregation) :整体与部分的关系。例人与手的关系。部分类的对象不能单独存在,他的生命周期依赖于整体类的对象的生命周期,整体消失时,部分也随之消失。 Person hand:set Hand ……
  • 29. 第一章 Java 对象持久化概述 软件模型 域对象间的关系 4. 一般化( Generalization ):类之间继承关系。 Employee name HourEmployee rate SalaryEmployee salary
  • 30. 第一章 Java 对象持久化概述 软件模型 域对象的持久化概念 实体域对象在内存中创建后,不能永久存在。将实体域对象永久保存起来,就是持久化的过程。通常只有实体域对象需要持久化,过程域对象和事件域对象一般不需要持久化。广义持久化指增、删、改、查。 内存 Customer 对象 order 对象 数据库 持久化 重新加载到内存
  • 31. 第一章 Java 对象持久化概述 直接通过 JDBC API 。
  • 32. 第一章 Java 对象持久化概述 ORM 简介 对象 - 关系映射 (ORM ,即 Object-Relation Mapping). 指单个组件中负责所有实体域对象的持久化,封装数据访问细节。 域模型 (对象、属性、关联、继承和多态) ORM API ORM 实现 关系数据模型 (表、字段、索引、主键和外键) 业务逻辑层 对象 - 关系映射文件 (xml) 持久化层 数据库层 参照 ORM 充当业务逻辑层和数据库层之间的桥梁
  • 33. 第一章 Java 对象持久化概述 ORM 简介 对象 - 关系映射的概念 域模型 Address 类 Province city street zipcode Customer 类 id name homeAddress comAddress 关系数据模型 Customer 类 ID …… HOME_PROVINCE HOME_CITY …… COM_PROVINCE COM_CITY …… 注:域模型中类的数目要比关系数据模型中 表的数目多。 表的列(字段) 表的行(记录) 表 面向关系概念 属性 类 对象 面向对象概念
  • 34. 第一章 Java 对象持久化概述 ORM 简介 ORM 中间件的使用方法 采用元数据来描述对象 - 关系映射细节,元数据通常采用 xml 格式,并存放在专门的对象 - 关系映射文件中。只要配置了持久化类与表的映射关系, orm 中间件在运行时就能够参照映射文件的信息,把域对象持久化到数据库中。 public void deleteCustomer(Customer c){ Session session = getSession(); session.delete(c); } 执行步骤如下: 1. 运用反射机制,获得 Customer 对象的 Customer.class 类。 2. 参照映射文件得到 Customer 类对应的表的信息,以及和 Customer 类关联的类以及 相应的表信息。 3. 根据以上信息生成 SQL 语句。 4. 调用 hibernate API ,执行该语句。
  • 35. 第一章 Java 对象持久化概述 Hibernate API 简介 1. 提供访问数据库操作 (session,transaction,query) 2. 配置 hibernate 接口 (configuratioin) 3. 回调接口 (Interceptor,Lifecycle,Validatable) 4. 用于扩展的功能接口 (UserType,CompositeUserType, IdentifierGenerator) Hibernate 对 JDBC 做了轻量级的封装。所谓轻量级是 指 Hibernate 并没有完全封装 JDBC , java 应用既可以 通过 HibernateAPI 来访问数据库,还可直接通过 JDBC API 访问数据库。
  • 36. 第一章 Java 对象持久化概述 Hibernate API 简介 Hibernate 核心接口 1.Configuration 配置 hibernate ,根启动 hibernate ,创建 sessionFactory 对象。 2.SessionFactory 初始化 hibernate ,充当数据源代理,创建 session 对象。线程安全的,可被多个线程共享。重量级的, 需要一个很大的缓存,用于存放于定义的 sql 语句和映射元数 据等。用户还可为它配置一个缓存插件,称为二级缓存。 3.Session 使用最广泛,也被称为持久化管理器,它提供和持久 化相关的操作。增、删、改、查等。不是线程安全的,避免多 个线程共享。轻量级的,创建和销毁不需要消耗太多资源。 Session 中有一个缓存,称为一级缓存。存放当前工作单元加 载的对象。
  • 37. 第一章 Java 对象持久化概述 Hibernate API 简介 Hibernate 核心接口 ( 续 ) 4.Transaction hibernate 数据库事务接口, 它对底层的事务接口作了封装 . 底层事务接 口包括 : JDBC API JTA(java Transaction API) CORBA(common object request Broker architecture)
  • 38. 第一章 Java 对象持久化概述 Hibernate API 简介 Hibernate 核心接口 ( 续 ) 5.Query 和 Criteria 接口:都是查询接口, query 实例 包装了 HQL 查询语句, hql 是面向对象的,他引用类 名及类的属性名,而不是表名和字段名。 Criteria 接 口完全封装了基于字符串形式的查询语句,比 query 接口更面向对象,他擅长执行动态查询。 sessoin 接口的 find 方法也具有数据查询功能,但他 只是执行一些简单的 hql 查询语句的快捷方式,远没 有 query 接口功能强大。
  • 39. 第一章 Java 对象持久化概述 Hibernate API 简介 回调接口 1.Lifecycle 和 Validatable 接口: lifecycle 接口能使 持久化类响应被加载、保存和删除事件。 Validatable 接口使持久化类的接口被保存之前进行 数据验证。这种方式强迫持久化类实现特定接口, 使 hibernate API 渗透到持久化类中,会影响可移 植性,不值得推荐。 2.Interceptor :不必由持久化类来实现。可定义专门实现该接口的类,负责响应持久化类的实例被加载、保存、更新或删除的事件。
  • 40. 第一章 Java 对象持久化概述 Hibernate API 简介 Hibernate 映射类型接口 1.PrivateType 类:映射 java 基本数据类型,包括 ByteType 、 ShortType 、 IntegerType 、 LongType 、 FloatType 、 DoubleType 、 CharactorType 、 BooleanType 。 2.DateType :映射 java 日期类型。 3.BinaryType :映射 Byte[] 类型。 Query.setParameter(“name”,”name”,Hibernate.STRING)
  • 41. 第一章 Java 对象持久化概述 Hibernate API 简介 可供扩展的接口 hibernate 提供的多数功能是可配置的,允许用户选择适当的内置策略。如可配置如下数据库方言 : hibernate.dialect=net.sf.hibernate.dialect.MySQLDialect hibernate.dialect=net.sf.hibernate.dialect.OracleDialect hibernate.dialect=net.sf.hibernate.dialect.SybaseDialect
  • 42. Java 对象持久化概述 Hibernate API 简介 可供扩展的接口 如果 hibernate 内置的策略不能满足需求时,允许用户自定义实现接口或扩展特定的类。 Hibernate 的扩展点包括: 主键生成策略: IdentifierGenerator sql 方言: Dialect 抽象类 缓存机制: cache 和 cacheprovider 接口 jdbc 连接管理器: connectionprovider 等
  • 43. Java 对象持久化概述 小结 表现层 业务逻辑层 持久化层 (orm 中间件、负责封装数据访问细节 ) 数据库层 实体域对象 ( 业务数据 ) 过程域对象 ( 业务逻辑 )
  • 44. 第四章 对象 - 关系映射基础 本章解决的问题 1. 持久化类没有 getXXX 和 setXXX 方法。 2. 持久化类的属性在库中没有对应的字段,或 字段没有对应的属性 3. 控制 hibernate 的 insert 、 update 语句。 4. 设置从持久化类映射到数据库表,以及持久 化类的属性映射到数据库表的字段的命名策 略。
  • 45. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 Hibernate 中持久化类的访问者有两个: 1.Java 应用程序 2.hibernate( 何时调用 get 、 set 方法 ?) Customer 对象 getXXX() 方法 setXXX() 方法 hibernate Java 应用程序 用户 界面 数据库 Java 应用程序不能访问持久化类的 private 方法,而 hibernate 没有这 个限制,它可以访问各种级别的方法。
  • 46. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 基本数据类型和包装类型 基本数据类型和包装类型对应的 hibernate 映射类型相同。 <property name=“price” type=“double” column=“PRICE” /> 基本类型可直接运算、无法表达 null 、数字类型的默认值为 0 。 包装类默认值是 null 。当对于默认值有业务意义的时候需要使用包装类。
  • 47. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 Hibernate 访问持久化类属性的策略 1.propertye 默认值:表明 hibernate 通过 getXXX 和 setXXX 来访问类属性。推荐使用。提高域模型透明性。 2.field:hibernate 通过 java 反射机制直接访问类属性。对于没有 javabean 方法的属性可设置该访问策略。 <property name=“name” access=“field” /> 除了设置 property 属性的 access 为 field 和 property 之外 还可以自定义访问策略,需要创建实现 net.sf.hibernate. property.PropertyAccessor 接口的类 。
  • 48. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 class Customer{ … .. private String firstname ; private String lastname ; public String getName(){ return firstname + “ ” + lastname ; } public void setName(String name){ StringTokenizer t = new StringTokenizer(name); firstname = t.nextToken(); lastname = t.nextToken(); } }
  • 49. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 在 customer.hbm.xml 文件中无需映射 firstname 和 lastname 属性,而是映射 name 属性 。 <property name =“name” column=“NAME” /> 尽管类中并没有 name 属性,由于 hibernate 不是直接访问 Name 属性,而是调用 get 、 set 方法,因此建立了 Firstname 、 Lastname 和表之间的联系。 Hibernate getName() setName() CUSTOMERS 表 Name 字段 Customer 类 firstname lastname
  • 50. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 不管在类中是否存在 name 属性,只要在 Customer.hbm.xml 文件中映射了 name 属性,在 hql 语句中就能访问他。 Session.find(“from customer as c where c.name=‘tom’”) 如果改成: <property name=“name” column=“NAME” access=“field”> 后过如何?
  • 51. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 在 customer 类的 setOrders ()方法中加入程序逻辑。 Public void setOrders(Set orders){ this.orders = orders ; calprice(); } Public calprice(){ …… setAvgPrice(avgprice); }
  • 52. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 在持久化类的方法中加入程序逻辑 在 setSex ()方法中加入数据验证逻辑 Public void setSex(char sex){ if(sex != ‘M’ && sex != ‘F’){ throw new IllegalArgumentException(“Invalid sex”); } this.sex = sex; }
  • 53. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 设置派生属性 利用 <property> 元素的 formula 属性,用来设置一个 sql 表达式, hibernate 将根据它来计算出派生属性的值。 <property name=“totalprice” formula=“(select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=ID)” /> <property name=“unitprice” formula=“BASE_PRICE*QUANTITY” />
  • 54. 第四章 对象 - 关系映射基础 持久化类的属性及访问方法 控制 insert 、 update 语句 若为 true ,等价于所有的 <property> 元素的 dynamic-update 为 true ,更新一个对象时,动态生成 update 语句,语句中仅包含取值不为 null 的字段。默认 false 。 若为 true ,等价于所有的 <property> 元素的 dynamic-insert 为 true ,保存一个对象时,动态生成 insert 语句,语句中仅包含取值不为 null 的字段。默认 false 。 若为 true ,更新一个对象时,会生成动态 update 语句,只有这个字段取值不为 null 才会把它包含到 update 语句中。默认为 false 。 若为 true ,保存一个对象时,会生成动态 insert 语句,只有这个字段取值不为 null 才会把它包含到 insert 语句中。默认为 false 。 若为 false ,等价于所有的 <property> 元素的 update 属性为 false ,整个实例不能被更新。默认为 true 。 若为 false , update 语句不包含该字段,该字段永远不能被更新。默认值为 true 。 若为 false ,在 insert 语句中不包含该字段,该字段永远不能被插入。默认值 true 。 作用 <property> insert 属性 <property> update 属性 <class> mutable 属性 <property> dynamic-insert 属性 <property> dynamic-update 属性 <class> dynamic-insert 属性 <class> dynamic-update 属性 映射属性
  • 55. 第四章 对象 - 关系映射基础 处理 sql 引用表示符 在 SQL 语法中,表示符是指用于为数据库表、视图、字段或索引等名字的字符串,常规表示符不包括空格,也不包含特殊字符,因此无需使用引用符号。如果数据库表名或列名包含特殊字符,可以使用引用表示符。 <property name=“description” column=“`CUSTOMER DESCRIPTION`” />
  • 56. 第四章 对象 - 关系映射基础 设置类的包名 如果在一个映射文件中包含多个类,并且这些类位于同一个包中,可以设置 <hibernate-mapping> 元素的 package 属性,避免为每个类提供完整的类名。 <hibernate-mapping package=“mypack”> <class name=“customer” table=“cu..” > …… </class> </hibernate-mapping> <hibernate-mapping> <class name=“mypack.customer” table=“cu..” > …… </class> </hibernate-mapping>
  • 57. 第五章 映射对象标识符 Java 按地址区分同一个类的不同对象,关系 数据库用主键区分同一条记录, Hibernate 使用 OID 来建立内存中的对象和数据库中记 录的对应关系。对象的 OID 和数据库的表的 主键对应。为保证 OID 的唯一性,应该让 Hibernate 来为 OID 付值。
  • 58. 第五章 映射对象表示符 关系数据库按主键区分不同记录 主键必备条件: 1. 不允许 null 2. 唯一,不重复 3. 之永远不会改变 自然主键:把具有业务含义的字段作为主键叫做自然主 键。
  • 59. 第五章 映射对象表示符 关系数据库按主键区分不同记录 把主键定义为自动增长类型 在 my SQL 中,把字段设为 auto_increment 类型,数据库会自 动为主键付值。 在 ms SQL server 中,把字段设为 identity 类型,数据库会自 动为主键付值。 从序列 (sequence) 中获取自动增长的描述符 create sequence seq_customer increment by 2 start with 1 insert into customers values(seq_customer.curval,’..’)
  • 60. 第五章 映射对象表示符 Java 语言按内存地址区分不同的对象 == 和 equals() 方法。
  • 61. 第五章 映射对象标识符 Hibernate 中用对象标识符 (OID) 来区分对象 OID 是关系数据库中的主键在 java 对象模型中的等价物。在运行时, hibernate 根据 OID 来维持 java 对象和数据库记录的对应关系。 Customer c1 = (Customer)session.load(Customer.class,new Long(1)); Customer c2 = (Customer)session.load(Customer.class,new Long(1)); Customer c3 = (Customer)session.load(Customer.class,new Long(3)); c1 == c2 ? c1 == c3 ? <id name=“id” type=“long” column=“ID”> <generator class=“increment” /> </id> <generator> 子元素用来设定表示符生成器。 Hibernate 提供了表识符生成器接 口: net.sf.hibernate.id.IdentifierGenerator, 并提供了多种内置的实现。
  • 62. 第五章 映射对象标识符 适用于自然主键。由 java 程序负责生成标识符。不能把 setID() 方法声明为 Private 的。尽量避免使用自然主键。 适用于代理主键。 Hibernate 采用 128 位的 UUID 算法来生成标识符。该算法 能够在网络环境中生成唯一的字符串标识符,这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。 适用于代理主键。根据底层数据库对自动生成表示符的能力来选择 identity 、 sequence 、 hilo 适用于代理主键。 Hibernate 根据 hign/low 算法生成标识符。 Hibernate 把特定表的字段作为“ hign” 值。默认情况下,采用 hibernate_unique_key 表的 next_hi 字段。 适用于代理主键。 Hibernate 根据底层数据库序列生成标识符。条件是数据库支持序列。 适用于代理主键。由底层数据库生成表识符。条件是数据库支持自动增长数据类型。 适用于代理主键。由 hibernate 自动以递增的方式生成表识符,每次增量为 1 描述 Increment Identity Sequence Hilo Uuid.hex Native assigned 表示符生成器
  • 63. 第五章 映射对象表示符 Hibernate 内置标识符用法 increment select max(id) from table; <id name=“id” type=“long” column=“ID”> <generator class=“increment”/> </id> 适用范围: 1 。由于不依赖与底层数据库,适合所有的数据库系统。 2 。单个进程访问同一个数据库的场合,集群环境下不推荐适用。 3 。 OID 必须为 long 、 int 或 short 类型,如果把 OID 定义为 byte 类型,抛异常。
  • 64. 第五章 映射对象表示符 Hibernate 内置标识符用法 Identity 由底层数据库生成标识符 . 需要把字段定义成自增型。 my sql 中为 auto_increment ms sql server 中为 identity <generator class=“identity” />
  • 65. 第五章 映射对象表示符 Hibernate 内置标识符用法 sequence <id name=“id” type=“long” column=“ID”> <generator class=“sequence”> <param name=“sequence”>tester_id_seq</param> </generator> </id> 适用范围: 地层数据库要支持序列。 Oracle DB2 SAP 等。 OID 必须为 long 、 int 或 shot 类型。
  • 66. 第五章 映射对象表示符 Hibernate 内置标识符用法 hilo <id name=“id” type=“long” clomn=“ID”> <generator name=“hilo”> <param name=“table”>hi_value</param> <param name=“column”>next_value</param> <param name=“max_lo”>100</param> </generator> </id> 使用范围: 该机制不依赖于地层数据库,因此适用于所有的数据库系统。 OID 必须为 long 、 int 、 short 类型,如果为 byte 类型的话,会抛出异常。 Net.sf.hibernate.id.IdentifierGeneratorException:this id generator generates Long 、 integer 、 short 。
  • 67. 第五章 映射对象表示符 Hibernate 内置标识符用法 native <id name=“id” type=“native” column=“ID”> <generator class=“native” /> </id> 适用范围: 该类型能根据地层数据库系统的类型,自动选择合适的标识符生成器,因此很适合于跨数据 库的平台,即在同一个应用中需要连接多种数据库系统的场合。 OID 与以上类同。
  • 68. 第五章 映射对象表示符 映射自然主键 映射单个自然主键 <id name=“id” column=“NAME” type=“string”> <generator class=“assigned” /> </id> <version name=“version” column=“VERSION” unsaved-value=“0” />
  • 69. 第五章 映射对象表示符 映射自然主键 映射复合主键 <composite-id> <key-property name=“name” column=“NAME” type=“string”> <key-property name=“companyId” column=“COMPANY_ID” type=“long”> </composite-id> <version name=“version” column=“VERSION” unsaved-value=“0” /> 使用联合主键的持久化类需要实现 serializable 接口和覆盖 equals() 、 hashCode() 方法。 可以使用 customId 属性来设置连联合主键 <composite-id name=“costomerid” class=“mypack.CustomerId”> <key-property name=“name” column=“NAME” type=“string”> <key-property name=“companyId” column=“COMPANY_ID” type=“long”> </composite-id>
  • 70. 第六章 映射一对多关联关系 Order 到 Customer 的多对一单向关联 Customer 到 Order 的一对多单向关联 Customer 到 Order 的一对多双向关联
  • 71. 第六章 映射一对多关联关系 建立多对一的单向关联关系 <many-to-one name=“customer” column=“CUSTOMER_ID” class=“..Customer” not-null=“true”> <property name=“***”> ?
  • 72. 第六章 映射一对多关联关系 建立多对一的单向关联关系 ( 续 ) many-to-one 属性 : name: 设定待映射的持久化类的名字。 column: 设定和持久化类的属性对应的表的外键。 class: 设定持久化类的属性的类型。 not-null: 是否允许为空。
  • 73. 第六章 映射一对多关联关系 tx = session.beginTransaction(); Customer c = new Customer(); c.setName(&quot;TOM&quot;); session.save(c); ? 会有什么后果 Order o1 = new Order(); o1.setOrderNumber(&quot;1&quot;); o1.setCustomer(c); Order o2 = new Order(); o2.setOrderNumber(&quot;1&quot;); o2.setCustomer(c); session.save(o1); session.save(o2); tx.commit();
  • 74. 第六章 映射一对多关联关系 建立多对一的单向关联关系 <many-to-one>not-null 属性 tx = session.beginTransaction(); Customer c = new Customer(); c.setName(&quot;TOM&quot;); //session.save(c); ? 会有什么后果 Order o1 = new Order(); o1.setOrderNumber(&quot;1&quot;); o1.setCustomer(c); Order o2 = new Order(); o2.setOrderNumber(&quot;1&quot;); o2.setCustomer(c); session.save(o1); session.save(o2); tx.commit();
  • 75. 第六章 映射一对多关联关系 建立多对一的单向关联关系 级联保存和更新 当 hibernate 持久化一个临时对象时,在默认情况下,他不会自动持久化所关联的其他临时对象,会抛出 TransientObjectException. 如果设定 many-to-one 元素的 cascade 属性为 save-update 的话,可实现自动持久化所关联的对象。 <many-to-one name=“customer” column=“CUSTOMER_ID” class=“..Customer” cascade=“save-update” not-null=“true” /> <property name=“***”> ?
  • 76. 第六章 映射一对多关联关系 映射一对多双向关联关系 Class Customer{ … public Set orders = new Set(); public Set getOrders(){ return orders; } public void setOrders(Set orders){ this.orders = orders; } … } <set name=“orders” cascade=“save-update”> <key column=“CUSTOMER_ID” /> <one-to-many class=“..Order” /> </set> Customer c = new Customer(“TOM”); Order o1 = new Order(“11”); O1.setCustomer(c); c.getOrders().add(o1); session.save(c); tx.commit();
  • 77. 第六章 映射一对多关联关系 映射一对多双向关联关系 ( 续 ) Hibernate 要求在持久化类中定义集合属性时,必须把属性声明为接口类型,如 Set 、 Map 、 List. 声明为接口类型可提高持久化类的透明性,当 hibernate 调用 setOrders() 方法时,传递的参数是 Hibernate 自定义的实现该接口类的实例。如果定义成类 ( 如 HashSet) 型,强迫 hibernate 把该类型的实例传给他。 通常在定义集合属性时,直接初始化为一个实现类的实例。 private Set orders = new HashSet(); 可避免空指针异常。
  • 78. 第六章 映射一对多关联关系 映射一对多双向关联关系 ( 续 ) <set name=“orders” cascade=“save-update”> <key column=“CUSTOMER_ID” /> <one-to-many class=“..Order” /> </set> name: 设定待映射持久化类的属性名。 cascade: 设定级联操作的程度。 key 子属性 : 设定与所关联的持久化类对应的标 的外键。 one-to-many 子属性 : 设定所关联的持久化类。
  • 79. 第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 Customer c = (Customer)session .load(Customer.class,new Long(2)); Order o = (Order)session.load(Order.class,new Long(2)); o.setCustomer(c); c.getOrders().add(o); tx.commit(); -------------------------------------------------------------- Update orders set …... Update orders set …… hibernate 执行两条更新语句。
  • 80. 第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 ( 续 ) Hibernate 会自动清理缓存中的所有持久化对象,按照持久化对象的改变 来同步更新数据库,因此执行了上述的两条更新语句。 重复执行多余的 sql 语句会影响 java 性能,解决这也问题的办法是把 <set> 元素的 inverse 属性设为 true, 该属性的默认值是 false 。 <set name=“orders” cascade=“save-update” inverse=“true” > <key column=“CUSTOMER_ID” /> <one-to-many class=“mypack.Order” /> </set> Customer 和 order 的双向关联中, customer 端的关联只是 order 端关联 的镜像。当 hibernate 同时探测到持久化对象 customer 和 order 的状态均 发生变化时,仅按照 order 对象状态更新数据库。
  • 81. 第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 ( 续 ) Customer c = (Customer)session.load(…)); Order o = (Order)session.load(…); o.setCustomer(c); //c.getOrders().add(c); tx.commit(); -------------------------------------------------------------------- 以上代码仅设置了 order 对象的 customer 属性, hibernate 仍然会按照 order 对象的状态 的变化来同步更新数据库,执行以下 sql 语句: Update orders set order_number=‘…’,customer_id=2 where id = 2
  • 82. 第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 ( 续 ) Customer c = (Customer)session.load(……); Order o = (Order)session.load(……); //o.setCustomer(c); c.getOrders().add(c); tx.commit(); -------------------------------------------------------------------- 以上代码仅设置了 customer 对象的 orders 属性,由于 <set> 元素的 inverse 属性为 true ,因此, hibernate 不会按照 customer 对象的状态 变化来同步更新数据库。
  • 83. 第六章 映射一对多关联关系 映射一对多双向关联关系 <set> 元素的 inverse 属性 结论: 1. 在映射一对多的双向关联关系时,应该在 one 方把 inverse 属性设为 true ,这可以提高性能。 2. 在建立两个对象的关联时,应该同时修改关联两端的相应 属性: Customer.getOrders().add(order); Order.setCustomer(customer); 这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务 逻辑层的程序代码不受 Hibernate 实现类的影响。同理,当删 除双向关联的关系时,也应该修改关联两端的对象的相应属性: Customer.getOrders().remove(order); Order.setCustomer(null);
  • 84. 第六章 映射一对多关联关系 映射一对多双向关联关系 级联删除 Customer customer = (Customer)session.load(Customer.class,new Long(2)); Session.delete(customer); tx.commit(); -------------------------------------------------------------------------------------- 如果 cascade 属性取默认值 none ,不会自动删除和 customer 关联的其他持久化对象。如 果希望删除 customer 时,自动删除和 customer 关联的 order 对象,可把 cascade 属性设 为 delete 。 <set name=“orders” cascade=“delete” inverse=“true”> <key column=“CUSTOMER_ID” /> <one-to-many class=“mypack.Order” /> </set> 再运行删除方法的时候,会自动删除 order 对象,此时 hibernate 执行如下语句: Delete from customer where customer_id = 1; Delete customer where id = 1;
  • 85. 第六章 映射一对多关联关系 映射一对多双向关联关系 父子关系 Customer customer = (Customer)session.load(……); Order order = (Order)customer.getOrders().iterator().next(); // 删除关联关系 customer.getOrders().remove(order); order.setCustomer(null); tx.commit(); -------------------------------------------------------------------------------------- 如果 cascade 为默认值 none , hibernate 会执行如下语句: Update orders set Customer_id = null where ID = 2; 如果希望程序自动删除不再和 customer 关联的 order 对象,可以把 cascade 属性设为 all-delete-orphan 。 <set name=“orders” cacade=“add-delete-orphan” inverse=“true”> <key column=“CUSTOMER_ID” /> <one-to-many class=“mypack.Order” /> </set> Delete from orders where CUSTOMER_ID = 2 and ID = 2
  • 86. 第六章 映射一对多关联关系 映射一对多双向关联关系 父子关系 当 customer.hbm.xml 的 <set> 元素的 cascade 属性取值为 all-delete-orphan,Hibernate 会按照如下方式处理 customer 对象: 1. 当保存或更新 customer 对象时,级联保存或更新所有关联的 order 对象,相当于 save-update. 2. 当删除 customer 对象时,级联删除所有的 order 对象,相当于 delete 。 3. 删除不再和 customer 对象关联的所有 order 对象。 当关联双方存在父子关系时,就可以把父方的 cascade 属性设为 all-delete-orphan. 所谓父子关系:是指父方来控制子方的持久化生命周期,子方对象必 须和一个父方对象关联。
  • 87. 第七章 操纵持久化对象 Session 接口提供增、删、改、查功能。 Session 中有一个缓存,位于缓存中对象处 于持久化状态,他和数据库中的记录相对 应。 Session 能够在某些时间点,按照缓存 中的持久化对象的属性变化来同步更新数据 库,这一过程被称为清理缓存。除了持久化 状态还有游离态和临时态。
  • 88. 第七章 操纵持久化对象 Java 对象在 JVM 中的生命周期 Customer c = new Customer(“TOM”,new HashSet()); Order o1 = new Order(“Tom_order001”,null); Order o2 = new Order(“Tom_order002”,null); o1.setCustomer(c); c.getOrders().add(o1); o1 = null; o2 = null; c = null;
  • 89. 第七章 操纵持久化对象 理解 session 的缓存 当 session 的 save() 方法持久化一个对象 时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图 load() 对象时,会判断缓存中是否存在该对象,有则返回。
  • 90. 第七章 操纵持久化对象 理解 session 的缓存 ( 续 ) Customer c = new Customer(“TOM”,new HashSet()); session.save(c); Long id = c.getId(); c = null; Customer c2 = (Customer)session.load(Customer.class,id); tx.commit(); session.close(); c2.getName(); C2 = null; --------------------------------------------------------------------------------------------- 缓存的作用: 1 。减少访问数据库的频率。 2 。保证缓存中的对象与数据库中的相关记录保持同步。 3 。当缓存中的持久化对象之间存在循环关联关系时, Session 会保证不出现访问对象图的死循 还,以及由死循环引起的 JVM 堆栈溢出异常。 提示: 当 session 加载了 customer 对象后,会为 customer 对象的值类型的属性复制一份快照。当清理 缓存时,通过比较对象的当前属性和快照,来判断对象的那些属性发生了变化。
  • 91. 第七章 操纵持久化对象 理解 session 的缓存 Session 在清理缓存时,按照以下顺序执行 sql 语句。 1 。按照应用程序调用 save ()方法的先后顺序,执行所有的对实体进行插入的 insert 语句。 2 。所有对实体进行更新的 update 语句。 3 。所有对实体进行删除的 delete 语句。 4 。所有对集合元素进行删除、更新或插入的 sql 语句。 5 。执行所有对集合进行插入的 insert 语句。 6 。按照应用程序调用 delete ()方法的先后执行。 默认情况下: 1 。当应用程序 commit ()方法的时候,先清理缓存,然后在向数据库提交事务。 2 。当调用 find ()或 iterator ()时,如果对象属性发生变化,会先清理缓存,以保证查询结果 能够反映持久化对象的最新状态。 3 。显式调用 flush ()。 --------------------------------------------------------------------------------------------- 提示: Commit ()和 flush ()方法的区别: Flush 进行清理缓存的操作,执行一些列 sql 语句,但不提交事务; commit 方法先调用 flush 方 法,然后提交事务。提交事务意味着对数据库操作永久保存下来。
  • 92. 第七章 操纵持久化对象 理解 session 的缓存 session.setFlushMode(FlushMode.AUTO); 清理 清理 清理 Session 的 flush () 不清理 清理 清理 Session 的 commit () 不清理 不清理 清理 Session 的 查询方法 FlushMode.AUTO FlushMode.COMMIT FLushMode.NEVER 清理缓存的模式
  • 93. 第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 临时状态 (transient) :刚刚用 new 语句创建,没有被持久化,不处于 session 中。该对象 成为临时对象 持久化状态 (persistent) :已经被持久化,加入到 session 的缓存中。该状态的对象为持久 化对象。 游离状态 (detached) :已经被持久化,但不处于 session 中。该状态的对象为游离对象。
  • 94. 第七章 操纵持久化对象 结束生命周期 结束生命周期 c2 = null; 处于游离态 转变为游离态 处于持久化状态 转变为持久化状态 临时状态 状态 处于生命周期中 处于生命周期中 处于生命周期中 处于生命周期中 开始生命周期 生命周期 tx = session.beginTransaction(); Customer c = new Customer(“Tom”,new HashSet); Session.save(c) Long id=c.getId(); c = null; Customer c2 = (Customer)session.load(Customer.class,id); tx.commit(); session.close(); c2,getName(); 程序代码
  • 95. 第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 临时对象特征 不处于 session 中,不被任何 session 关联。 数据库中没有对应的记录。 以下情况,对象进入临时状态: 1.new 语句刚创建了一个对象。 2.session 的 delete 方法使持久化对象或游离 对象转变为临时对象,对于游离对象,该方法从数 据库中删除记录,对于持久化对象,该方法从数据 库中删除记录,还要删除缓存中的对象。
  • 96. 第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 持久化对象特征 1. 位于一个 session 缓存中,总是被一个 session 关联。 2. 持久化对象和数据库记录相对应。 3. 清理缓存时,会根据对象属性变化,同步更新数据库。 4.save 把临时对象转变为持久化对象。 5.load 或 find 或 get 返回的对象总是持久化状态。 6.find 方法返回的 list 存放的都是持久化对象。 7.update 、 save 、 SaveOrUpdate 和 Lock 方法使游离对象装变 为持久化对象。 在实际的应用程序中应该避免一个 java 对象被多个 session 实例关 联,会导致重复执行 sql 语句,并且极容易出现一些并发问题。
  • 97. 第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 游离对象特征 1. 不再位于 session 的缓存中,游离对象不被 session 关联。 2. 游离对象由持久化转变过来的,因此在数据 库中可能还存在与它对应的记录(前提条 件是没有其他程序删除了这条记录)。
  • 98. 第七章 操纵持久化对象 在 hibernate 中 java 对象的状态 游离对象特征 在以下情况下,持久化对象转变为游离对象: 1.close 方法使缓存被清空,缓存中的所有的 对象都变为游离对象。如果没有引用他们 的话,他们就会结束生命周期。 2.evict 方法从缓存中删除一个持久化对象, 使他变为游离态对象。当缓存中保存了大量的持久 化对象时,会消耗许多内存空间,使用该方法删掉 一些对象来节省空间。
  • 99. 第七章 操纵持久化对象 Session 的增、删、改、查方法 save : 1. 对象加入缓存,成为持久化对象。 2.<id name=“id” cloumn=“ID” type=“long”> <generator class=“increment”> </id> session.save(c,new Long(9))
  • 100. 第七章 操纵持久化对象 Session 的增、删、改、查方法 update : 将游离对象转变为持久化对象。不论对象属性 是否发生变化,该方法都会执行 update 操作。如果希望仅当属性变化时才执行 update 语句的话可进行如下配置: <class name=“…” table=“…” select-before-update=“true”>
  • 101. 第七章 操纵持久化对象 Session 的增、删、改、查方法 saveOrUpdate : 该方法同时包含 save 和 update 方法,如果参数是临时对象就用 save 方法,如果是游离对象就用 update 方法,如果是持久化对象就直接返回。 临时对象判断法: 1 。 OID 为 null 2 。具有 version 属性并取值为 null 3 。在映射文件中为 <id> 元素设置了 unsaved-value 属性,并且 OID 属性取值与属 性匹配。 4 。在映射文件中为 <version> 元素设置了 unsaved-value 属性,并且 version 属性取 值与属性匹配。 5 。自定义了 Interceptor 实现类,并且 isUnsaved 方法返回 Boolean.true 如果 id 的类型为 long ,则默认值为 0 ,此时需要在配置文件中设置 id 的 unsaved-value 为 0 。
  • 102. 第七章 操纵持久化对象 Session 的增、删、改、查方法 load 和 get : 从数据库加载指定的 OID 持久化对象。 如果数据库中不存在该记录时, load 方法会 抛出异常,而 get 方法返回 null 。
  • 103. 第七章 操纵持久化对象 Session 的增、删、改、查方法 delete 如果参数是持久化对象,就执行一个 delete 语句,若为游离对象,先使游离对象被 session 关联,使他变为持久化对象,然后计划执行一个 delete 语句。
  • 104. 第七章 操纵持久化对象 Session 的增、删、改、查方法 包含 all 和 delete-orphan 的行为。 all-delete-orphan 删除所有和当前对象解除关联关系的对象。 包含 save-update 和 delete 的行为。 删除对象时,级联删除关联的对象。 保存或更新当前对象时,级联保存关联的临时对象,更新关联的游离对象。 忽略关联对象,默认值 描述 none save-update delete delete-orphan all cascade 属性值
  • 105. 第七章 操纵持久化对象 与触发器协同工作 Session.save(c); Session.flush(); Session.refresh(c); ----------------------------------------------------------------- 触发器的行为导致缓存与数据库中的数据不一致。解决办法是执行完 操作后,立即调用 session 的 flush 方法和 refresh 方法,迫使缓存与 数据库同步。 Session 的 update 操作方法盲目的激活触发器 如果游离状态的对象的属性和数据库一致,则更新操作是多余的。 为避免这种情况: <class name=“” table=“” select-before-update=“true”> …… </class>
  • 106. 第七章 操纵持久化对象 利用拦截器 (interceptor) 生成审计日志 不依赖于具体的数据库平台,可看成持久化层的 拦截器。 当执行 save 、 update 、 saveorupate 、 flush 方法时,会调用拦截器方法。 实现 Inteceptor 接口。
  • 107. 第七章 操纵持久化对象 利用拦截器 (interceptor) 生成审计日志 Inteceptor 1.findDirty(): 查脏对象 2.Instantiate ():构造实例前调用 3.isUnsaved (): saveorupdate 方法调用该方法,判断用 save 还是 update 4.onDelete :删除对象前调用 5.onFlushDirty : flush 方法检查到脏对象时调用此方法。 6.onLoad ():初始化持久化对象时调用此方法。 7.onSave(): 保存对象前调用该方法。 8.postFlush ():执行完 flush 方法之前调用本方法。
  • 108. public class AuditLogInterceptor implements Interceptor, Serializable { private Session session; private Set inserts=new HashSet(); private Set updates=new HashSet(); public void setSession(Session session){ this.session=session; } public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types){ if ( entity instanceof Auditable ) { updates.add(entity); } return false; } public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { return false; } public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { if ( entity instanceof Auditable ) { inserts.add(entity); } return false; } public void postFlush(Iterator entities) { try{ Iterator it=updates.iterator(); while(it.hasNext()){ Auditable entity=(Auditable)it.next(); AuditLog.logEvent(&quot;update&quot;,entity,session); } it=inserts.iterator(); while(it.hasNext()){ Auditable entity=(Auditable)it.next(); AuditLog.logEvent(&quot;insert&quot;,entity,session); } }catch(Exception e){e.printStackTrace();} finally{ inserts.clear(); updates.clear(); } } }
  • 111. 第八章 映射组成关系 Class customer{ …… Address homeAddress ; Address comAddress ; …… } Table customers{ …… home_province home_city home_street com_province com_city com_street …… } <compont name=“homeaddress” class=“mypack.Address”> <parent name=“customer” /> <property name=“street” type=“string” column=“HOME_STREET” /> <property name=“city” type = “string” cloumn=“HOME_CITY” /> <property name=“street” type = “string” cloumn=“HOME_STREET” /> </component> <compont name=“comaddress” class=“mypack.Address”> <parent name=“customer” /> <property name=“street” type=“string” column=“COM_STREET” /> <property name=“city” type = “string” cloumn=“COM_CITY” /> <property name=“street” type = “string” cloumn=“COM_STREET” /> </component>
  • 112. 第八章 映射组成关系 映射组成关系 区分值和实体 持久化类的属性分为两种:值 (value) 类型和实体类型 (entity) 类型。值类型没有 OID ,不能被单独持久化,他的生命周期依赖于所属的持久化类的对象的生命周期,组件类型就是一种值类型;实体类型有 OID ,可单独持久化。
  • 113. 第八章 映射组成关系 映射组成关系 访问由组成关系的持久化类 1.Conf.addClass(Customer.class).addClass(Address.class); 抛映射异常,原因是 Address.hbm.xml 文件没找到。 2. Customer c = new Customer(); c.setHomeAddress(new Address()); c.setComAddress(new Address()); …… Session.save(c); ----------------------------------------------------------------------------------------- Session.save(new Address()); 映射异常: unkown entity class.
  • 114. 第八章 映射组成关系 映射复合组成关系 Computer 类和他的组件类
  • 115. 第八章 映射组成关系 映射复合组成关系 <component name=&quot;cpuBox&quot; class=&quot;mypack.CpuBox&quot;> <parent name=&quot;computer&quot; /> <property name=&quot;type&quot; type=&quot;string&quot; column =&quot;CPUBOX_TYPE&quot; /> <component name=&quot;graphicsCard&quot; class=&quot;mypack.GraphicsCard&quot;> <parent name=&quot;cpuBox&quot; /> <property name=&quot;type&quot; type=&quot;string&quot; column =&quot;GRAPHICSCARD_TYPE&quot; /> </component> <many-to-one name=&quot;vendor&quot; column=&quot;CPUBOX_VENDOR_ID&quot; class=&quot;mypack.Vendor&quot; not-null=&quot;true&quot; /> </component>
  • 116. 第九章 Hibernate 映射类型 内置映射类型 布尔 CHAR(1) boolean Boolean true_false 布尔 BIT boolean Boolean boolean 布尔 CHAR(1) boolean Boolean yes_no 变长串 VARCHAR String string 定长字符 8 位含 2 位小数部分 8 4 1 2 8 4 取值范围 CHAR(1) NUMERIC DOUBLE FLOAT TINYINT SMALLINT BIGINT INTEGER sql char Character String java.math.BigDecinimal double Double float Float byte Byte short Short long Long int Integer java integer int long short byte float double big_decimal character Hibernate
  • 117. 第九章 Hibernate 映射类型 java 时间和日期类性 YYYY-MM-DD YYYYMMDDHHMMSS YYYYMMDDHHMMSS HH:MM:SS YYYY-MM-DD 取值范围 DATE TIMESTAMP TIMESTAMP TIME DATE sql java.util.Calendar java.util.Calendar util.Date sql.timestamp util.Date sql.Time util.Date sql.Date java date time timestamp calendar calendar_date Hibernate
  • 118. 第九章 Hibernate 映射类型 大对象类型的映射 不允许以上类型来定义 OID BLOB sql.Blob blob CLOB BARBINARY(BLOB) CLOB VARBINARY(BLOB) sql sql.Clob 实现类 String byte[] java binary text serializable clob Hibernate
  • 119. 第九章 Hibernate 映射类型 大对象类型的映射 如果持久化类的字段为 blob 或 clob 类型,保存时需要包含两步: ---------------------------------------------------------------------------------------------- Customer c = new Customer(); // 现保存一个空的 clob 实例 c.setDescription(Hibernate.createClob()); session.save(c); session.flush(); // 锁定记录 session.refresh(customer,LockMode.UPGRADE); oracle.sql.CLOB clob = c.getDescription(); // 写入大文本 java.io.Writer pw = clob.getCharacterOutputStream(); pw.write(longtext); pw.close(); tx.commit(); session.close();
  • 120. 第九章 Hibernate 映射类型 JDK 自带的个别 java 类的映射类型 VARCHAR VARCHAR VARCHAR VARCHAR sql java.util.Currency java.util.TimeZone java.util.Locale java.lang.Class java class locale timezone currency Hibernate
  • 121. 第九章 Hibernate 映射类型 使用 hibernate 内置的映射类型 java 应用程序 java.lang.String hibernate hibernate 映射类型: string jdbc Driver 标准 sql 类型: varchar my sql 类型: varchar oracle : varchar2
  • 122. 第九章 Hibernate 映射类型 客户华映射类型 customer 类 -------------------- id:Long email:String phone:Integer hibernate 内置类型 -------------------- long string ? customers 表 -------------------- ID BIGINT EMAIL VARCHAR(50) PHONE VARCHAR(8)
  • 123. 第九章 Hibernate 映射类型 客户华映射类型
  • 124. 第九章 Hibernate 映射类型 客户华映射类型 1 。设置表中的字段类型。 private static final int[] sql_types = {Types.VARCHAR}; public int[] sqltypes(){ return sql_types}; 2. 设置 java 类型。 returnedClass(); 3. 是否是可变类 isMutable(); 4. 深度拷贝,生成快照。 deepCopy(); 5.equals() 方法判断字段属性是否和快照相同。 6. 调用 nullSafeGet() 方法来取得字段的属性值。 public Object nullSafeGet(ResultSet rs,String[] names,Object owner){ if(rs.wasNull()) return null; String phone = rs.getString(name[0]); return new Integer(phone); } 7. 调用 nullSafeSet 方法来把 phone 属性添加到 insert 语句中。 ----------------------------------------------------------------------------------------------- <property name=“phone” type=“mypack.PhoneType” column=“PHONE” />
  • 125. public class Address implements Serializable { private final String province; private final String city; private final String street; private final String zipcode; public boolean equals(Object o) { if ( this == o) return true ; if (!(o instanceof Address)) return false ; final Address address = (Address) o; if (!province.equals(address.province)) return false ; if (!city.equals(address.city)) return false ; if (!street.equals(address.street)) return false ; if (!zipcode.equals(address.zipcode)) return false ; return true ; } public int hashCode() { int result; result = (province == null ? 0 : province.hashCode()); result = 29 * result + (city == null ? 0 : city.hashCode()); result = 29 * result + (street == null ? 0 : street.hashCode()); result = 29 * result + (zipcode == null ? 0 : zipcode.hashCode()); return result; } }
  • 126. public class AddressUserType implements UserType { private static final int [] SQL_TYPES = { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR };// 设置和 Address 类的四个属性对应的字段的 sql 类型。 public int [] sqlTypes() { return SQL_TYPES; } // 设置所映射的 java 类 public Class returnedClass() { return Address. class ; } // 指明 Address 类是不可变类 public boolean isMutable() { return false ; } // 返回 Address 类的快照,由于 Address 类是不可变类,因此直接返回既可。 public Object deepCopy(Object value) { return value; // Address is immutable } // 比较对象是否和快照相等 public boolean equals(Object x, Object y) { if (x == y) return true ; if (x == null || y == null ) return false ; return x.equals(y); }
  • 127. public class AddressUserType implements UserType { // 从结果集中读取四个属性,构造成 Address 对象。 public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { if (resultSet.wasNull()) return null ; String province = resultSet.getString(names[0]); String city = resultSet.getString(names[1]); String street = resultSet.getString(names[2]); String zipcode = resultSet.getString(names[3]); return new Address(province, city, street, zipcode); } // 把 Address 对象中的属性添加到预处理语句中。 public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException { if (value == null ) { statement.setNull(index, Types.VARCHAR); statement.setNull(index + 1, Types.VARCHAR); statement.setNull(index + 2, Types.VARCHAR); statement.setNull(index + 3, Types.VARCHAR); } else { Address address = (Address) value; statement.setString(index, address.getProvince()); statement.setString(index + 1, address.getCity()); statement.setString(index + 2, address.getStreet()); statement.setString(index + 3, address.getZipcode()); } } }
  • 128. <property name=&quot;name&quot; type=&quot;mypack.NameCompositeUserType&quot; > <column name=&quot;FIRSTNAME&quot; length=&quot;15&quot; /> <column name=&quot;LASTNAME&quot; length=&quot;15&quot; /> </property> <property name=&quot;homeAddress&quot; type=&quot;mypack.AddressUserType&quot; > <column name=&quot;HOME_STREET&quot; length=&quot;15&quot; /> <column name=&quot;HOME_CITY&quot; length=&quot;15&quot; /> <column name=&quot;HOME_PROVINCE&quot; length=&quot;15&quot; /> <column name=&quot;HOME_ZIPCODE&quot; length=&quot;6&quot; /> </property> <property name=&quot;comAddress&quot; type=&quot;mypack.AddressUserType&quot; > <column name=&quot;COM_STREET&quot; length=&quot;15&quot; /> <column name=&quot;COM_CITY&quot; length=&quot;15&quot; /> <column name=&quot;COM_PROVINCE&quot; length=&quot;15&quot; /> <column name=&quot;COM_ZIPCODE&quot; length=&quot;6&quot; /> </property>
  • 129. 第十章 Hibernate 的检索策略 hibernate 的检索策略简介 类级别和关联级别可选的检索策略及默认的检索策略 load get find load 运行时行为受影响的 session 的检索方法 一对多和多对多为立即检索 多对一和一对一关联为外连接检索 立即 默认的检索策略 立即 延迟 迫切左外连接检索 立即 延迟 可选的检索策略 类级别 关联级别 检索策略的作用域
  • 130. 第十章 Hibernate 的检索策略 三种检索策略的运行机制 hibernate 的检索策略简介 ( 续 ) 通过左外连接加载与检索方法指定的对象关联的对象。 延迟加载与检索方法指定的对象关联对象。可设定批量检索数量。 立即加载关联的对象、可设定批量检索数量 关联接别 不适用 延迟加载检索方法指定的对象 立即加载检索方法制定的对象 类级别 立即 延迟检索 迫切左外 检索策略的类型
  • 131. 第十章 Hibernate 的检索策略 hibernate 的检索策略简介 ( 续 ) 映射文件中用于设定检索策略的几个属性 合理取值 3~10 之间, class 和 set 存在。 如果为 true ,适用迫切左外连接检索。在 <many-to-one> 和 <one-to-one> <set> 中存在。 如果为 true ,延迟加载, class 和 set 有此属性 描述 1 <many-to-one> 和 <one-to-one> 中为 auto , 在 <set> 元素中为 false 。 false 默认值 正整数 auto true false true false 可选值 lazy out-join batch-size 属性
  • 132. 第十章 Hibernate 的检索策略 类级别的检索策略 立即 <class ...... lazy=“false”> 延迟检索 <class ...... lazy=“true”> if(!Hibernate.isInitialized(c)){ Hibernate.initialize(c); }
  • 133. 第十章 Hibernate 的检索策略 一对多和多对多关联的检索策略( set ) 无意义 延迟检索。 迫切左外联接。 立即检索 策略 true false true false out-join false false true true lazy
  • 134. 第十章 Hibernate 的检索策略 一对多和多对多关联的检索策略 立即检索 延迟检索 批量延迟检索 批量立即检索 迫切左外连接检索
  • 135. 第十章 Hibernate 的检索策略 多对一和一对一的检索策略 立即 延迟 迫切左外连接 迫切左外连接 迫切左外连接 延迟 检索 order 时对 customer 对象的检索策略 false true false true false true customer 类的 lazy 属性 auto auto true true false false order 类 <many-to-one> 的 outer-join 属性
  • 136. 第十章 Hibernate 的检索策略 比较三种检索策略 (1) 对应用程序完全透明,不管对象处于持久化状态还是游离状态,都可从一个对象导航到另一个对象。 (2) 使用了外连接, select 语句少 由应用程序决定需要加载哪些对象,可以避免执行多余的 select 语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间。 对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象 优点 (1) 多对一或一对一关联 (2) 需要立即访问的对象 (3) 数据库有良好的表连接性能。 (1) 一对多或者多对多关联 (2) 应用程序不需要立即访问或者根本不会访问的对象 (1) 类级别 (2) 应用程序需要立即访问的对象 (3) 使用了二级缓存 优先考虑使用的场合 (1) 可能会加载应用程序不需要访问的对象,浪费内存。 (2) 复杂的数据库表连接也会影响检索性能。 应用程序如果希望访问游离状态的代理类实例,必须保证她在持久化状态时已经被初始化。 (1)select 语句多 (2) 可能会加载应用程序不需要访问的对象,浪费许多内存空间。 缺点 立即检索 延迟检索 迫切左外连接检索 检索策略
  • 137. 第十一章 hibernate 检索方式 1 。对象导航图 2 。 OID 检索 3 。 HQL 检索 4 。 QBC 检索 5 。本地 SQL 检索
  • 138. 第十一章 hibernate 检索方式 检索方式简介 HQL 检索方式 1 。在查询语句中设定各种查询条件 2 。支持投影,仅检索出对象的部分属性 3 。支持分页 4 。连接查询 5 。分组查询 6 。内置聚集函数 7 。调用用户自定义的函数 8 。嵌入式查询 9 。动态绑定参数 Query query = session.createQuery(“from Customer as c where c.name=:custoerNa me and c.age = :customerAge”); query.setString(“customerName”,”Tom”); query.setInteger(“customerAge,21); query.list();
  • 139. 第十一章 hibernate 检索方式 检索方式简介 QBC 检索方式 主要由 Criteria 、 Criterion 接口和 Expression 类组成,他支持在运行时动态生成查询语句。 ------------------------------------------------------------------------------------------ Criteria criteria = session.createCriteria(Customer.class); Criterion c1 = Expression.like(“name”,”T%”); Criterion c2 = Expression.eq(“age”,new Integer(21)); criteria.add(c1) criteria.add(c2); criteria.list(); ------------------------------------------------------------------------------------------ 方法链编程: session.createCriteria(Customer.class).add(Expression.like(“name”,”%T”)) .add(Expression.eq(“age”,new Integer(21))) .list();
  • 140. 第十一章 hibernate 检索方式 检索方式简介 SQL 检索方式 Query query = session.createSQLQuery(“select {c.*} from CUSTOMERS c where c.NAME like :customerName and c.AGE=:customerAge”,”c”, Customer.class); // 动态绑定参数 query.setString(“customerName”,”T%”); query.setInteger(“customerAge”,new Integer()21); // 执行 sql select 语句,返回查询结果。 List list = query.list();
  • 141. 第十一章 hibernate 检索方式 检索方式简介 使用别名 from Customer as c where c.name = :customerName as 可省略。
  • 142. 第十一章 hibernate 检索方式 检索方式简介 多态查询 session.createQuery(“from Employee”); 查询出所有的实体 from java.lang.serializable (支持接口) from java.lang.Object
  • 143. 第十一章 hibernate 检索方式 检索方式简介 对查询结果排序 hql 查询: session.createQuery(“from Employee c order by c.name”); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”)); 检索方式简介 分页查询 hql 查询: session.createQuery(“from Employee c order by c.name”).setFirstResult(97) .setMaxResults(10); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”)) .setFirstResult(97).setMaxResult(10).list();
  • 144. 第十一章 hibernate 检索方式 检索方式简介 检索单个对象 hql 查询: session.createQuery(“from Employee c order by c.name”) .setMaxResults(1).uniqueResult(); qbc 查询: session.createCriteria(Customer.class) .addOrder(Order.asc(“name”)) .setMaxResult(1).uniqueResult();
  • 145. 第十一章 hibernate 检索方式 检索方式简介 绑定参数 hql 查询: session.createQuery(“from Employee c where c.name =:customerName”); query.setString(“customer”,”Tom”); ---------------------------------------------------- ............................c.name=? query.setString(0,”Tom”);
  • 146. 第十一章 hibernate 检索方式 检索方式简介 在影射文件中定义命名查询语句 <class> ....... </class> <query name=“findCustomersByName”> <![CDATA[from Cusomter c where c.name like:name]]> </query> ------------------------------------------------------------------ query = session.getNamedQuery(“findCustomersByName”); query.setString(“name”,”Tom”); query.list();
  • 147. 第十一章 hibernate 检索方式 设定查询条件 Express.not(Express.in()) not in Express.between() between Express.not(Express.between()) not between 含义 Express.in() Express.isNotNull() Express.isNull() Express.le() Express.lt() Express.ge() Express.not(Express.eq()) Express.eq() QBC 运算方法 in is not null is null <= < >= <> = HQL 运算符 比较运算 范围运算符 运算类型
  • 148. 第十一章 hibernate 检索方式 设定查询条件 ( 续 ) Expression.or()| Expression.disjunction() or Expression.not() not 含义 Expression.and()| Expression.conjunction() Expression.like() QBC 运算方法 and like HQL 运算符 字符串模式匹配 逻辑 运算类型
  • 149. 第十一章 hibernate 检索方式 连接查询 适用于不存在关联关系的持久化类 不支持 ClassA,ClassB 交叉连接 不支持 right out join | out join 右外连接 迫切左外连接 左外连接 隐式内连接 不支持 不支持 left out join out join FetchMode.EAGER left out join fetch out join fetch 适用于由关联关系的持久化类 适用范围 不支持 Criteria.createAlias() QBC 语法 inner join fetch | join fetch inner join | join HQL 语法 内连接 迫切内连接 程序中指定的连接查询类型
  • 150. 第十一章 hibernate 检索方式 连接查询 迫切左外连接 HQL: createQuery(“from Customer c left outer join fetch c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class).setFetchMode(“orders”,FetchMode.EAGER) .add(Expression.like(“name”,”T”,MatchMode.START))
  • 151. 第十一章 hibernate 检索方式 连接查询 左外连接 HQL: createQuery(“from Customer c left join c.orders o where c.name like ‘T%’”);
  • 152. 第十一章 hibernate 检索方式 连接查询 内连接 HQL: createQuery(“from Customer c inner join c.orders o where c.name like ‘T%’”); HQL: createQuery(“from Customer c join c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class). .add(Expression.like(“name”,”T”,MatchMode.START)) .createCriteria(“orders”) .add(Expression.like(“orderNumber”,”T”,MatchMode.START));
  • 153. 第十一章 hibernate 检索方式 连接查询 迫切内连接 HQL: createQuery(“from Customer c inner join fetch c.orders o where c.name like ‘T%’”); QBC: createCriteria(Customer.class). .setFetchMode(“orders”,FetchMode.EAGER) .createAlias(“orders”,”o”) .add(Expression.like(“this.name”,”T”,MatchMode.START)) .add(Expression.like(“o.orderNumber”,”T”,MatchMode.START))
  • 154. 第十一章 hibernate 检索方式 连接查询 隐式内连接 HQL: createQuery(“from Order o where o.customer.name like ‘T%’“); 等价于 : from Order o join o.customer c where c.name like ‘T%’ QBC: 不支持
  • 155. 第十一章 hibernate 检索方式 连接查询 右外连接 HQL: from Customer c right outer join c.orders o where o.name like ‘T%’ 等价于 : from Customer c right join c.orders o where o.name like ‘T%’
  • 156. 第十一章 hibernate 检索方式 连接查询 使用 SQL 风格的交叉连接和隐式内连接 HQL: 交叉连接查询 :from Customer,Order 标准 SQL 风格的内连接 :from Customer c inner join c.orders SQL 风格的隐式内连接查询 :from Customer c,Order o where c.id = o.customer_id
  • 157. 第十一章 hibernate 检索方式 连接查询 关联级别运行时的检索策略 1. 若在 HQL 、 QBC 代码中没有显式指定检索策 略,使用映射文件中的检索策略。但 HQL 总是忽略 映射文件中设置的迫切左外连接检索策略。 2. 若代码中显示指定了检索策略,则覆盖映射文件中 的检索策略。 3. 目前的 hibernate 版本只允许在一个查询语句中迫切 左外连接检索一个集合。 4.HQL 支持各种各样的连接查询。
  • 158. 第十一章 hibernate 检索方式 报表查询 投影查询 指查询结果仅包括部分实体或实体的部分属 性。通过 select 来实现。 from Customer c join c.orders o where o.orderNumber like ‘T%’ 如果希望查询结果中只包含 Customer 对象,可使用以下形式: select c from Customer c join c.orders o where o.orderNumber like T%’ session.createQuery(“select c.id,c.name,o.orderNumber from Customer c join c.orders o where o.orderNumber like ‘T%’”) ----------------------------------------------------------------------------------- 对应的 sql 语句为: select c.ID,c.NAME,o.ORDER_NUMBER from CUSTOMERS c inner join ORDERS o on c.ID-=o.CUSTOMER_ID where o.ORDER_NUMBER like’T%’ ------------------------------------------------------------------------------------ 过滤重复元素 createQuery(“select distinct c.name from customer c”);
  • 159. 第十一章 hibernate 检索方式 报表查询 使用聚集函数 createQuery(“select count(*) from Customer c”).uniqueResult(); createQuery(“select avg(c.age) from Customer c”).uniqueResult(); createQuery(“select max(c.age),min(c.age) from Customer c”).uniqueResult(); 分组查询 : createQuery(“select c.name,count(c) from Customer group by c.name”);
  • 160. 第十一章 hibernate 检索方式 高级查询技巧 动态查询: session.createCriteria(Customer.class) .add(Expression.like(“name”,name.toLowerCase()),MatchMode.ANYWHERE) .add(Expression.eq(“age”,new Integer(11))); 集合过滤: hql : createQuery(“from Order o where o.customer=:customer and o.price>100 order by o.price”).setEntity(“customer”,customer).list(); 使用集合过滤: session.createFilter(customer.getOrders(),”where this.price > 100 order by this.price”).list(); 子查询: from Customer c where 1 < (select count(o) from c.orders o); 本地 SQL 查询: String sql=“select cs.ID as {c.id},cs.NAME as {c.name},cs.AGE as {c.age} from CUSTOMERS cs where cs.ID = 1”; Query query = session.createSQLQuery(sql,”c”,Customer.class); 第二个参数是类的别名,在 SQL 语句中,每个字段的别名必须位于打括号内。
  • 161. 第十一章 hibernate 检索方式 查询性能优化 iterate 方法 query1=session.createQuery(“from Customer c”); List result1 = query1.list(); Query query2 = session.createQuery(“from Customer c where c.age < 30”); Iterator it = query2.iterator(); query 接口的 iterate 方法首先检索 ID 字段,然后根据 ID 字段到一级缓存、二级缓存中查 找,有则返回,否则查库。
  • 162. 第十一章 hibernate 检索方式 查询性能优化 查询缓存 在 hibernate.properties 中的 hibernate.cache.use_query_cache=true query = session.createQuery(“from Cusotmer c where c.age>:age”); query.setInteger(“age”,new Integer(1)); query.setCacheable(true); ------ 如果想更加细粒度的控制查询缓存,可设置缓存区域 query.setCacheRegion(“customer”)
  • 163. 第十一章 hibernate 检索方式 小结 适合动态生成查询语句 支持动态查询,编程麻烦 对动态查询语句的支持 用户可扩展 criteria 接口 编译时被解析,更易排错 更加面向对象 不支持报表查询和子查询。有限的连接查询 将语句肢解成一组 criteria ,较差 QBC 检索 不具扩展性 运行时被解析 基于字符串形式的 sql 支持各种查询 优点:和 sql 相近,易读 HQL 检索 可读性 功能 查询语句形式 何时被解析 可扩展性 比较方面
  • 164. 数据库事务与并发 在应用中采用悲观锁和乐观锁 当 hibernate 向库中 save 或 update 一个对象时,会自动使用这种锁模式。该模式仅供 hibernate 使用,在应用程序中不该使用它。 同 LockMode.UPGRADE. 对于 oracle ,执行 select ... for update no wait 语句, nowait 表明如果执行该语句的事务不能立即获得悲观锁,不会等待其他事务解锁,而是立即抛出一个异常。 不管缓存有无,都查库,同上,如果数据库系统支持悲观锁,执行 select ... for update 操作,否则执行普通的 sql 语句。 不管缓存中是否存在,都查库,如果映射文件中设置了版本元素,就执行版本检查,比较缓存中的对象和库中的版本是否一致。 如果缓存中存在该对象则返回,否则查库,默认值。 LockMode.NONE LockMode.READ LockMode.UPGRADE LockMode.UPGRADE_NOWAIT LockMode.WRITE session.get(Accout.class,new Long(1),LockMode.UPGRADE)
  • 165. 数据库事务与并发 在应用中采用悲观锁和乐观锁 由应用程序实现悲观锁 如果数据库不支持 select ... for update 语句时,可由应用程序来实现悲观锁。这需要在 表中建个锁字段,可以是布尔值。 true 表示锁定态, false 表示空闲态。 步骤: 1 。根据 lock 字段判段记录的状态 2 。若锁定了,一直等待。直到空闲。 3 。如果空闲,改成锁定态。 4 。更新记录,改称空闲态,解除锁定。
  • 166. 数据库事务与并发 在应用中采用悲观锁和乐观锁 利用 hibernate 的版本控制实现乐观锁 <version> 和 <timestamp> 都具有版本控 制的功能, <verion> 利用一个递增的整数 来跟踪记录的版本, <timestamp> 用时间 戳来跟踪记录的版本。 使用版本: create table a( ... VERSION intger ... ) 使用版本: <id name=“*” column=“”> <generator ..> </id> <version name=“version” column=“VERSION”> 使用版本: class Account{ ... private int version; ... } 在影射文件中, <verion> 元素必须跟在 <id> 之后。
  • 167. 数据库事务与并发 在应用中采用悲观锁和乐观锁 利用 hibernate 的版本控制实现乐观锁 使用 <timestamp> 除了 <version> 元素外, <timestamp> 元素也同样的版本控制功能。使用 <timestamp> 元素步骤如下: 使用版本: create table a( ... timestamp timestamp; ... ) 使用版本: <id name=“*” column=“”> <generator ..> </id> <timestamp name=“timestamp” column=“TIMESTAMP”> 使用版本: class Account{ ... private Date timestamp; ... } 在影射文件中, <timestamp> 元素必须跟在 <id> 之后。
  • 168. 数据库事务与并发 比较 Session 的 lock() 方法与 update() 方法 会计划执行一个 update 语句 update .. where id=1 and VERSION=0; 当清理缓存时才会执行这个 update 语句,并进行版本检查,如果库中没有匹配的记录,抛出 StaleObjectStateException 异常 不会计划执行一个 update 语句。 执行 update 方法时不会立即进行版本检查,只有当 session 在清理缓存时,真正执行 update 语句时才进行版本检查。 udate() 都能使一个游离对象与当前会话关联 如果设定了 LockMode.READ 模式,则立即进行版本检查,执行类似以下形式的 select 语句: select ID from ACCOUNTS where ID=1 and VERSION=0; 如果数据库中没有匹配的记录,就抛出 StaleObjectStateException. lock() 相似之处 不同之处 比较两个方法
  • 169. 影射继承关系 关系树的每个具体类对应一个表 companys 表 -------------- ID NAME HE 表 -------------- ID<pk> Custome_ID<fk> NAME SE 表 -------------- ID<pk> company_id<fk> NAME
  • 170. 影射继承关系 company 类 SE 类 HE 类 Employee 类 company.hbm.xml SE.hbm.xml HE.hbm.xml company 表 SE 表 HE 表
  • 171. 影射继承关系 关系树的每个具体类对应一个表 <class name=“HE”...> ... <propery name=“rate” type=“string” column=“RATE”> ... </class> <class name=“SE”...> ... <propery name=“salary” type=“string” column=“RATE”> ... </class>
  • 172. 影射继承关系 关系树的根类对应一个表 company 类 SE 类 HE 类 Employee 类 company.hbm.xml Employee.hbm.xml company 表 Employee 表
  • 173. 影射继承关系 <class name=“employee” table=“employee”> <id ...></id> <discriminator column=“EMPLOYEE_TYPE” type=“string”/> ... <subclass name=“HE” discriminator-value=“HE”> <propery name=“rate” column=“RATE” type=“double”/> </subclass> <subclass name=“SE” discriminator-value=“SE”> <propery name=“salary” column=“SALARY” type=“double”/> </subclass> </class>
  • 174. 映射继承关系 每个类对应一个表 <class name=“employee” table=“employee”> <id ...> </id> ... <joined-subclass name=“HE” table=“HE”> <key column=“employee_id”/> <property name=“salary” column=“salary” type=“string”> </joined-subclass> <joined-subclass name=“SE” table=“SE”> <key column=“employee_id”/> <property name=“rate” column=“rate” type=“string”> </joined-subclass> </class>
  • 176. 映射继承关系 映射多对一多态关联 表 D ----------- ID(PK) A_TYPE A_ID D1 表 B --------- A1 B1 表 C --------- A1 B1
  • 177. 映射继承关系 映射多对一多态关联 <any name=“a” meta-type=“string” id-type=“long” cascade=“save-update”> <meta-value value=“B” class=“ClassB” /> <meta-value value=“C” class=“ClassC” /> <column name=“A_TYPE” /> <column name=“A_ID” /> </any>
  • 178. 第十六章 映射值类型集合 set: 集合中的对象不按特定的方式排序,每 又重复对象。 TreeSet 能按照特定方式 排序。 list: 集合中的对象按索引位置排序,可有重 复对象,允许按照对象在集合中的索引 位置检索对象。 map: 集合中的每个元素包含一个键值对, 没有重复的 key 对象, value 对象可重复。 TreeMap 按特定方式排序。
  • 179. 第十六章 映射值类型集合 映射 set <set name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID”> <element column=“FILENAME” type=“string” not-null> </set> name: 指定 customer 类的 images 属性名 table: 指定和 images 属性对应的表为 images 。 lazy: 如果为 true ,表示延迟检索。 Customer 中有一个集合类型的属性 images ,用来存放所有的图片名,则在 Customer 中的定义如下: Set images = new HashSet(); Customers 表 ID<<pk>> ... images 表 Customer_id(fk) FileName(pk)
  • 180. 第十六章 映射值类型集合 映射 Bag <idbag name=“images” table=“IMAGES” lazy=“true”> <colllection-id type=“long” column=“ID”> <generator class=“increment”/> </collection-id> <key column=“CUSTOMER_ID” /> <element column=“FILENAME” type=“string” not-null=“true”> </idbag> bag 集合中的对象不按特定方式排序,但允许有重复对象。 java 集合的 API 中没有提供 bag 接口, hibernate 允许在持久化类中用 list 来模拟 bag 行为。如果 images 集合中允 许存放重复的文件名。可定义为: List images = new ArrayList(); ... Customers 表 ID<<PK>> ... images 表 ID<<PK>> Customer_id<<FK>> FileName(pk)
  • 181. 第十六章 映射值类型集合 映射 List <list name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID” /> <index column=“position”/> <element column=“FILENAME” type=“string” not-null=“true”> </list> Customers 表 ID<<PK>> ... images 表 Customer_id<<FK>><<PK>> position<<PK>> FileName 如果希望 images 集合中的元素允许存放重复的元素,并且按照索引位置排序,首先应 在 images 表中定位一个 position 字段,代表每个元素在集合中的索引位置。
  • 182. 第十六章 映射值类型集合 映射 Map <map name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID” /> <index column=“image_name” type=“string”/> <element column=“FILENAME” type=“string” not-null=“true”> </list> 如果 images 集合中的每一个元素包含一对 key/value 对,那么应该把 images 集合定义 成 map 类型。 Map images = new HashMap(); Customers 表 ID<<PK>> ... images 表 Customer_id<<FK>><<PK>> image_name<<PK>> FileName
  • 183. 第十六章 映射值类型集合 对集合排序 hibernate 对集合中的元素支持两种排序方式 : 1. 在数据库中排序 : 简称为数据库排序 , 当 hibernate 通过 select 语句到数据库中检索集 合对象时 , 利用 order by 子句进行排序。 2. 在内存中排序 , 利用 java 集合的排序功能进行 排序 , 可选择自然排序和客户化排序。 hibernate 用 sort 属性来设置内存排序,用 order- by 属性设置数据库排序。 支持 支持 <map> 不支持 不支持 <list> 支持 不支持 <idbag> 支持 支持 <set> sort order-by 排序属性
  • 184. 第十六章 映射值类型集合 对集合排序 在数据库中对集合排序 <set> <idbag> <map> 元素都有 order-by 属性,若设置了该属性,当 hibernate 通 过 select 语句检索对象时,利用 order by 子句进行排序。 <set name=“images” table=“IMAGES” lazy=“true” order-by=“FILENAME asc” > <key column=“CUSOTMER_ID” /> <element column=“FILENAME” type=“string” not-null=“true” /> </set> 在 order-by 属性中还可加入 sql 函数,例如: <set name=“images” table=“IMAGES” order-by=“lower(FILENAME) asc” > ... </set>
  • 185. 第十六章 映射值类型集合 对集合排序 在数据库中对集合排序 ( 续 ) 对键对象排序: <map name=“images” table=“IMAGES” lazy=“true” order-by=“IMAGE_NAME” > ...... </ map > 对值对象排序: <map name=“images” table=“IMAGES” lazy=“true” order-by=“FILENAME” > ...... </ map > 按 ID 代理主键排序: <idbag name=“images” table=“IMAGES” lazy=“true” order-by=“ID” > ...... </idbag>
  • 186. 第十六章 映射值类型集合 对集合排序 在内存中对集合排序 ( 续 ) <set> 和 <map> 都具有 sort 属性,如设置了该属性可对内存中的集合对象进行排序。 <set> 元素在内存中对集合排序 : <set name=“images” table=“images” lazy=“true” sort=“natural”> ....... </set> <set> 元素的 sort 属性为 natural ,表示对 images 集合中的字符串进行自然排序。 <set> 元素也支持客户化排序。需要实现 Comparator 接口。 <set name=“images” table=“images” lazy=“true” sort=“mypack.MyComparator”> ....... </set> 按 ID 代理主键排序: <idbag name=“images” table=“IMAGES” lazy=“true” order-by=“ID” > ...... </idbag>
  • 187. 第十六章 映射值类型集合 对集合排序 在内存中对集合排序 ( 续 ) <map> 元素在内存中对集合排序 : <map name=“images” table=“images” lazy=“true” sort=“natural”> ....... </map> <map> 元素的 sort 属性为 natural ,表示对 images 集合中的字符串进行自然排序。 <map> 元素也支持客户化排序。需要实现 Comparator 接口。 <map name=“images” table=“images” lazy=“true” sort=“mypack.MyComparator”> ....... </map>
  • 188. 第十六章 映射值类型集合 映射组件类型的集合 Customer ----------- name age images Image ----------- name filename sizeX sizeY Customer 1 0..n Image 类作为一种值类型,没有 OID ,此外,由于 Image 对象会存放在 java 集合 中,为了保证 java 集合类正常工作,应该在 image 类中实现 equals() 和 hashCode() 方法。 <set name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID” /> <composite-element class=“mypack.Image”> <parent name=“customer” /> <property name=“name” column=“IMAGE_NAME” not-null=“true” /> ...... </composite-element> </set>
  • 189. 第十六章 映射值类型集合 映射组件类型的集合 ( 续 ) <idbag name=“images” table=“IMAGES” lazy=“true”> <collection-id type=“long” column=“ID” > <generator class=“increment” /> </collection-id> <key column=“CUSTOMER_ID” /> <composite-element class=“mypack.Image”> <parent name=“customer” /> <property name=“name” column=“IMAGE_NAME” not-null=“true” /> ...... </composite-element> </idbag>
  • 190. 第十六章 映射值类型集合 映射组件类型的集合 ( 续 ) <map name=“images” table=“IMAGES” lazy=“true”> <key column=“CUSTOMER_ID” /> <index type=“string” column=“IMAGE_NAME” /> <composite-element class=“mypack.Image”> <parent name=“customer” /> <property name=“name” column=“IMAGE_NAME” not-null=“true” /> ...... </composite-element> </map>
  • 191. 第十七章 映射实体关联关系 映射一对一关联 按照外键映射 CUSTOMERS 表 --------------- ID<<PK>> NAME HOME_ADDRESS<<FK>> COM_ADDRESS<<FK>> ADDRESSS 表 --------------- ID<<PK>> CITY STREET PROVINCE customer.hbm.xml : <many-to-one name=“homeAddress” class=“mypack.Address” column=“HOME_ADDRESS” cascade=“all” unique=“true” /> <many-to-one name=“comAddress” class=“mypack.Address” column=“COM_ADDRESS” cascade=“all” unique=“true” /> address.hbm.xml <one-to-one name=“customer” class=“mypack.Customer” property-ref=“homeAddress” /> one-to-one 元素的 property-ref 属性为 homeAddress, 表明建立了从 homeAddress 对象到 Cusotmer 对象的关联。
  • 192. 第十七章 映射实体关联关系 映射一对一关联 按照主键映射 CUSTOMERS 表 --------------- ID<<PK>> NAME ADDRESSS 表 --------------- ID<<PK>><<FK>> CITY STREET PROVINCE customer.hbm.xml : <one-to-one name=“address” class=“mypack.Address” cascade=“all” /> address.hbm.xml <one-to-one name=“customer” class=“mypack.Customer” constraint=“true” /> one-to-one 元素的 constraint 属性为 true, 表明 Address 表的 ID 主键同时作为外键参照 Customers 表。在 address.hbm.xml 文件中,必须为 OID 使用 foreign 标识符生成策略。 <id name=“id” type=“long” column=“ID”> <generator class=“foreign”> <param name=“property”>customer</param> </generator> </id>
  • 193. 第十七章 映射实体关联关系 映射单向多对多关联 CATEGORIES 表 ---------------- ID<<PK>> NAME CATEGORY_ITEM 表 ---------------- CATEGORY_ID<<PK>><<FK>> ITEM_ID<<FK>><<PK>> ITEMS 表 ---------------- ID<<PK>> NAME BASIC_PRICE