Hibernate的持久化对象配置

摘要:
#7native:根据底层数据库对自动生成主键的支持能力选择identity|sequence|hilo#8uuid:根据当前机器的mac地址和time生成UUID作为主键。指定Dao类属性的访问方式和的属性access可以控制类属性的访问方式,缺省为property:#1access=”field”:表示让hibernate通过反射的方式直

定义Pojo对象和**.hbm.xml文件

-1 对于每一个需要持久化的对象都需要创建一个Pojo类定义,Hibernate要求POJO类定义中必须有一个no-argument的构造方法,便于Hibernate通过java reflection机制创建实例:[java.lang.reflect.Constructor.newInstance()];

-2 对于Pojo类定义中的类属性而言,不管访问符是否为public,也不管是否提供了对应的setter/getter方法,Hibernate都可以通过java reflection进行访问,类属性类型最好使用装箱类型,便于业务隔离;
-3 Hibernate也不要求每一个POJO必须实现Serializable接口,但如果对采用RMI和J2EE分布式结构的应用,POJO在不同进程节点之间传输时,或者在HttpSession内,则一定需要实现此接口;

1 <hibernate-mapping package="com.leo.chen.dao.hibernate">
2     <class name="User"table="user"dynamic-insert="true"dynamic-update="true"> 
3         <id name="id"column="id"access="property">
4             <generator class="native"></generator>
5         </id>
6         <property name="name"column="name access="field"></property>
7         <property name="password"column="password"access="field"></property>
8     </class>
9  </hibernate-mapping>

指定插入行的primary key生成策略

设计数据库表的时候主键ID一般使用非业务相关的独立字段,从而保证主键在任何时候都不受业务变动的影响,对于<generator>而言hibernate提供了多种实现方式:
#1 代理主键:increment
由hibernate负责生成,每次增量为1,插入一条数据会执行两个sql语句,先从表中查找出最大的id,执行加1,然后插入当前数据;适用于所有数据库,但是如果多个SessionFactory同时连接一个DB,则increment的自增操作失效;仅适合DB被单个Hibernate App访问的场景;OID必须为Long、INT或者Short;

#2 代理主键:identity
由底层数据库负责生成,依赖数据库的主键自增功能;由DB设置,根据不同DB配置不同的DB dialect,从而映射成不同的类型,MySQL为auto_increment,SQL Server为identity;底层数据库必须支持自动增长字段的类型;OID必须为Long、INT或者Short;

#3 代理主键:sequence
由Hibernate设置,但序列来自于底层数据库;底层数据库必须支持序列,MySQL不支持序列,Oracle,DB2和PostgreSQL支持;OID必须为Long、INT或者Short;

#4 单自然主键:assigned
表示由应用程序为当前赋值,并且该属性为自然主键,业务相关,永远不会为null;一般而言saveOrUpdate()方法通过判断主键ID是否为null来确定对象的状态,当主键的生成属性generator为assigned的时候则不能判断;只能通过额外的属性<version>来控制;如果unsaved-value为null就表示为临时对象,非null就表示游离对象;

1 <hibernate-mapping>
2   <class name="org.hibernate.tutorial.domain.Cart" 
3 table="CARTS"dynamic-update="true">
4     <id name="name"type="string"access="field">
5       <column name="CART_NAME" />
6       <generator class="assigned" />
7     </id> 
8     <version name="version"column="VERSION" 
9 unsaved-value="null"/>
10   </class>
11 </hibernate-mapping>

#5 复合自然主键:composite-id
Customer对象由CustomerId对象确定,CustomerId由name和company组成; 凡是由自然键担任主键的class都需要定义version属性以区分状态;<many-to-one>标签表示company与customer为多对一的关系;Insert和update属性为false表示当customer对象被保存的时候,会忽略company属性;

1 <hibernate-mapping>
2   <class name="mypack.Customer"table="CUSTOMERS">
3     <composite-id name="customerId"class="mypack.CustomerId">
4       <key-property name="name"column="NAME"type="string" />
5       <key-property name="company"column ="COMPANY_ID"type="long" />
6     </composite-id>
7     <version name="version"column="VERSION"unsaved-value="null" />
8     <many-to-one name="company"column="CLIENT_ID" 
9 insert="false” update="false”
10 class="org.hibernate.tutorial.domain.Company" />
11   </class>
12 </hibernate-mapping> 

#6 hilo:由hibernate根据hilo算法自己生成主键。
#7 native:根据底层数据库对自动生成主键的支持能力选择 identity|sequence|hilo
#8 uuid :根据当前机器的mac地址和time生成UUID作为主键。
#9 customized class:可以通过实现org.hibernate.id.IdentifierGenerator接口自定义id。

指定Dao类属性的访问方式
<id>和<property>的属性access可以控制类属性的访问方式,缺省为property:
#1 access=”field”:表示让hibernate通过反射的方式直接访问field,丢失封装性;
#2 access=”property”:表示让hibernate通过类对外暴露的getter/setter访问field,推荐;

指定Dao类和关联对象的数据加载策略和SQL生成方式
加载Dao对象<class>元素可以使用属性lazy控制类数据的加载时机,缺省为true;
#1 lazy=”true”:当使用load()加载对象时会先生成一个代理对象,其中只有primary key被赋值,其他属性只有等对象实际被使用时才会生成SQL语句到DB进行查询。
#2 lazy=”false”:立即加载,也就是使用load方法会立即生成SQL到DB进行查询。

级联查询<set>元素使用lazy来控制关联对象的加载时机,缺省值为true;
#1 lazy=”true”:跟<class>级别同理;
#2 lazy=”false”:跟<class>级别同理;
#3 lazy=”extra”:采用精细化的延迟加载,比如关联对象调用size/contains/isEmpty等非访问整个集合的元素方法时,不会加载整个集合元素,仅生成返回特定信息的SQL;

级联查询<set>元素使用fetch来控制查询关联对象时的SQL生成策略
#1 fetch=”select”:缺省值,额外生成一条SQL进行独立查询。
#2 fetch=”subselect”:额外生成一条SQL查询集合数据,比如当查询多个用户,每个用户上有多个订单,这样可以通过一条独立的SQL 将所有用户的所有订单一次性查询出来,在内存中将不同的订单分配到不同用户上。
#3 fetch=”join”:采用LEFT JOIN table的方式生成唯一SQL,减少执行SELECT的次数,同时会忽略lazy属性,立即加载所有数据,但由于关联多张表,可以造成性能下降;

级联查询<many-to-one>/<one-to-many>也有lazy和fetch属性,功能也类似。另外<class>和<set>元素上设置batch-size=”10”可以生成批量加载数据的SQL将数据放入缓存,从而减少SQL语句的执行条数。

通过sql语句获取复杂查询的字段值
Hibernate将根据formula的sql语句动态为totalPrice设置值,formula可以操作各表字段,所以并不需要orders表中有total_price的字段;如果formula查询的结果为空则totalPrice的值返回null,因此Java类中totalPrice的属性需要设置为Double包装类型。

1 <property name=”totalPrice” 
2   formula=”SELECT SUM(o.price) FROM orders o WHERE o.customer_id=id” />

强制动态生成insert和update的SQL语句
缺省情况下Hibernate会预先生成并编译针对所有column的insert和update子句;但预编译好的sql语句不管待写入DB的字段是否为空,也不管待写入DB的字段是否有更新,都全部进行操作,当column比较多的时候缺省设置会耗费比较多的DB资源;因此Hibernate提供关键字用于控制<class>上各个column的插入和更新:
#1 insert属性:缺省为true;如果为false,表示Hibernate不再为insert生成price字段,也就是该DB column不能被插入;
<property name=”price” insert=”false” />

#2 update属性:缺省为true;如果为false,表示Hibernate不再为update生成price字段,也就是该DB column不能被更新;
<property name=”price” update=”false” />

#3 mutable属性:缺省为true;如果为false,表示所有该class的property的update属性为false,该实例不能被更新;
<class name=”org.hibernate.totorial.domain.User” table=”USER” mutable=”false” />

#4 dynamic-insert属性:缺省为false;如果为true,表示插入一个对象时动态生成insert语句,insert的字段仅包含取值不为null的字段;
<class name=”org.hibernate.totorial.domain.User” table=”USER” dynamic-insert=”true” />

#5 dynamic-update属性:缺省为false;如果为true,表示更新一个对象时动态生成update语句,update的字段仅包含取值有更新的字段;
<class name=”org.hibernate.totorial.domain.User” table=”USER” dynamic-update=”true” />

#6 select-before-update属性:缺省为false,表示只要使用Session.update(),则不管目标对象的属性是否有更新都会执行UPDATE操作;如果为true,则会先执行一条SELECT语句查询DB的状态并对比是否有更新,表示仅当目标对象的属性被修改时才执行UPDATE操作;
<class name=”org.hibernate.totorial.domain.User” table=”USER” select-before-update=”true” />

免责声明:文章转载自《Hibernate的持久化对象配置》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇js 数组去重的三种方法(unique)POJ 3281 Dining (网络流之最大流)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SQL Server:触发器详解

SQL Server:触发器详解  1. 概述 2. 触发器的分类 3. Inserted和Deleted表 4. 触发器的执行过程 5. 创建触发器 6. 修改触发器: 7. 删除触发器: 8. 查看数据库中已有触发器: 9. “Instead of”相关示例: 10. “After”触发器 11. 参考资源 1. 概述 触发器是一种特殊的存储过程...

Java高并发,如何解决,什么方式解决

  对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了。而并发问题是绝大部分的程序员头疼的问题,但话又说回来了,既然逃避不掉, 那我们就坦然面对吧~今天就让我们一起来研究一下常见的并发和同步吧。   为了更好的理解并发和同步,我们需要先明白两个重要的概念:同步和异步    1、同步和异步的区别和联系    所谓同步,可以...

MySQL中update修改数据与原数据相同

mysql默认的binlog_format是statement 1.在binlog_format=row和binlog_row_image=FULL时,由于MySQL 需要在 binlog 里面记录所有的字段,所以在读数据的时候就会把所有数据都读出来,那么重复数据的update不会执行。即MySQL 调用了 InnoDB 引擎提供的“修改为 (1,55)”...

Spring-Data-JPA尝鲜:快速搭建CRUD+分页后台实例

前言:由于之前没有接触过Hibernate框架,但是最近看一些博客深深被它的“效率”所吸引,所以这就来跟大家一起就着一个简单的例子来尝尝Spring全家桶里自带的JPA的鲜 Spring-DATA-JPA 简介 JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理J...

mysql 有就更新 没有就插入

数据持久化的过程中,有时会遇到这样的需求: 当数据库表中存在符合某种条件的数据时,需要去更新它,不存在时,则需要新增,也就是insertOrUpdate操作,本文主要讲解MySQL中的INSERT ... ON DUPLICATE KEY UPDATE语句,该语句是基于唯一索引或主键使用,比如一张表中含有a,b,c三个字段,字段a被加上了unique in...

在SQLSERVER企业管理器中如何创建触发器

下面将分别介绍在MS SQLServer 中如何用SQL Server 管理工具Enterprise Manager 和Transaction_SQL 来创建触发器。在创建触发器以前必须考虑到以下几个方面: CREATE TRIGGER 语句必须是批处理的第一个语句; 表的所有者具有创建触发器的缺省权限,表的所有者不能把该权限传给其它用户; 触发器...