Hibernate学习笔记 第二章 基本对象关系映射

来源:互联网 发布:数据猿创始人 编辑:程序博客网 时间:2024/06/05 21:58
【POJO类和数据库的映射文件:*.hbm.xml】
*POJO类和关系数据库之间的映射可以用一个XML文档来定义。
*通过POJO类的数据库映射文件,Hibernate可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据库表列之间的对应关系。
*在运行时Hibernate将根据这个映射文件来生成各种SQL语句。
*映射文件的扩展名为:.hbm.xml
【映射文件说明】
*hibernate-mapping
  - 类层次:class
     * 主键:id
     * 基本类型:property
     * 实体引用类:many-to-one | one-to-one
     * 集合:set | list | map | array
       - one-to-many
       - many-to-many
     * 子类:subclass | joined-subclass
     * 其他:component | any等
  - 查询语句:query(用来放置查询语句,便于对数据库查询的同意管理和优化)
*每个Hibernate-mapping中可以同时定义多个类。但更推荐为每个类都创建一个单独的映射文件。
<hibernate-mapping package="net.lasolmi.app">
【Hibernate-mapping】
*Hibernating-mapping是Hibernating映射文件的根元素
  - schema:指定所映射的数据库schema的名称。若指定该属性,则表明会自动添加带schema前缀
  - catalog:指定所映射的数据库catalog的名称。
  - default-cascade(默认为none):设置hibernate默认的级联风格。若配置java属性,集合映射时没有指定cascade属性,则Hibernate将采用此处指定的级联风格。
  - default-access(默认为property):指定Hibernate的默认的属性访问策略。默认值为property,即使用getter,setter方法来访问属性。若指定access,则Hibernate会忽略getter/setter方法,而通过反射访问成员变量。
  - default-lazy(默认为true):设置Hibernate morning的延迟加载策略。该属性的默认值为true,即启用延迟加载策略。若配置Java属性映射,集合映射时没有指定lazy属性,则Hibernate将采用此处指定的延迟加载策略。
  - auto-import(默认为true):指定是否可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。
  - package(可选):制定一个包前缀,如果在映射文档中没有指定全限定的类名,就是用这个作为包名。
【class】
*class元素用于指定类和表的映射
  - name:制定该持久化类映射的持久化类的类名
  - table:指定该持久化类映射的表名,Hibernate默认以持久化类的类名作为表名
  - dynamic-insert:若设置为true,表示当保存一个对象时,会动态生成insert语句,insert语句中仅包含所有取值不为null的字段。默认值为false
  - dynamic-update:若设置为true,表示当更新一个对象时,对动态生成update语句,update语句中仅包含所有取值需要更新的字段。默认值为false
  - select-before-update:设置Hibernate在更新某个持久化对象之前是否需要先执行一次查询。默认值为false
  - batch-size:指定根据OID来抓取实例时每批抓取的实例数。
  - lazy:指定是否使用延迟加载。
  - mutable:若设置为true,等价于所有的<property>元素的update属性为false,表示整个实例不能被更新。默认为true。
  - discriminator-value:指定区分不同子类的值。当使用<subclass/>元素来定义持久化类的继承关系时需要使用该属性
【映射对象标识符】
*Hibernate使用对象标识符(OID)来建立内存中的随想和数据库表中记录的对应关系。对象的OID和数据表的主键对应。Hibernate通过标识符生成器莱维逐渐赋值。
*Hibernate推荐在数据表中使用代理主键,即不具备业务含义的字段。代理主键通常为整数类型,因为整数类型比字符串类型要节省很多的数据库空间。
*在对象-关系映射文件中,<id>元素用来设置对象标识符。<generator>子元素用来设定标识符生成器。
*Hibernate提供了标识符生成器接口:IdentifierGenerator,并提供了各种内置实现。
【id】
*id:设定持久化类的OID和表的主键的映射
 - name:标识持久化类OID的属性名
 - column:设置标识属性所映射的数据表的列名(主键字段的名字).
 - unsaved-value:若设定了该属性,Hibernate会通过比较持久化类的OID值和该属性值来区分当前持久化类的对象是否为临时对象。
 - type:指定Hibernate映射类型。Hibernate映射类型是Java类型与SQL类型的桥梁。如果没有为某个属性显示设定映射类型,Hibernate会运用反射机制先识别出持久化类的特定属性的Java类型,然后自动使用与之对应的默认的Hibernate映射类型
 - Java的基本数据类型和包装类型对应相同的Hibernate映射类型。基本数据类型无法表达null,所以对于持久化类的OID推荐使用包装类型。
【generator】
*generator:设定持久化类设定标识符生成器
 - class:指定使用的标识符生成器权限定类名或其缩写名
【主键生成策略generator】
*Hibernate提供的内置标识符生成器:
标识符生成器
increment  :用于代理主键。由Hibernate自动以递增方式生成。
identity   :适用于代理主键。由底层数据库生成标识符。
sequence   :适用于代理主键。Hibernate根据底层数据库的序列生成标识符,这要求底层数据库支持序列。
hilo       :适用于代理主键。Hibernate分局high/low算法生成标识符。
seqhilo    :适用于代理主键。使用一个高/低位算法来高效的生成long,short或者int类型的标识符。
native     :适用于代理主键。根据地岑数据库对自动生成标识符的方式,自动选择identity、sequence或hilo。
uuid.hex   :适用于代理主键。Hibernate采用128位的UUID算法生成标识符。
uuid.string:适用于代理主键。UUID被编码成16字符长的字符串。
assigned   :适用于自然主键。由Java应用程序负责生成标识符。
foreign    :适用于代理主键。使用另外一个相关联的对象的标识符。
【increment标识符生成器】
*increment标识符生成器由Hibernate以递增的方式为代理主键赋值
*Hibernate会先读取NEWS表中的逐渐的最大值,而接下来想NEWS表中插入记录时,就在max(id)的基础上递增,增量为1.
*适用范围:
 - 由于increment生存标识符机制不依赖于底层数据库系统,因此它适合于所有的数据库系统
 - 适用于只有单个Hibernate应用进程访问同一个数据库的场合,在集群环境下不推荐使用它
 - OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出异常
【sequence标识符生成器】
*sequence标识符生成器利用底层数据库提供的序列来生成标识符。<id name="id"><generator class="Sequence"><param name="Sequence">news_seq</param></generator></id>

*Hibernate在持久化一个News对象时,先从底层数据库的news_seq序列中获得一个唯一的标识符,再把它作为主键值
*适用范围:
  - 由于sequence生成标识符的机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列。支持序列的数据库包括:DB@,Oracle等
  - OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出异常
【hilo标识符生成器】
*hilo标识符生成器由Hibernate按照一种high/low算法*生成标识符,它从数据库的特定表的字段中获取high值。
<id name="id"><generator class="hilo"><param name="table"></param><param name="column"></param><param name="max_lo"></param></generator></id>

*Hibernate在持久化一个News对象时,由Hibernate负责生成主键值。hilo标识符生成器在生成标识符时,需要读取并修改HI_TABLE表中的NEXT_VALUE值。
*适用范围:
  - 由于hilo生存系统标识符机制不依赖于底层数据库系统,因此它适合所有的数据库系统
  - OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出异常。
【native标识符生成器】
*native标识符生成器依据底层数据库对自动生成标识符的生成能力,来选择使用identity,sequence或hilo标识符生成器.
*适用范围:
  - 由于native能根据底层数据库系统的类型,自动选择合适的标识符生成器,因此很适合于跨数据库平台开发
  - OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出异常
【映射组成关系*】
*建立域模型和关系数据模型有着不同的出发点:
  - 域模型:由程序代码组成,通过细化持久化类的粒度可提高代码的可重用性,简化编程
  - 关系数据模型:由关系数据组成,在存在数据冗余的情况下,需要把粗粒度的表拆分成具有外键参照关系的几个细粒度的表,从而节省存储空间;另一方面,在没有数据冗余的情况下,应该尽可能减少表的数目,简化表之间的参照关系,以便提高数据的访问速度
*Hibernate把持久化类的属性分为两种:
  - 值(value)类型:没有OID,不能被单独持久化,生命周期依赖于所属的持久化类的对象的生命周期
  - 实体(entity)类型:有OID,可以被单独持久化,有独立的生命周期
*显然无法直接用property映射name属性
*Hibernate使用<component>元素来影射组成关系,该元素表名pay属性时Worker类一个组成部分,在Hibernate中称之为组件
<component name="pay" class="Pay"><parent name="worker"><property name="monthlyPay" column="MONTHLY_PAY" type="integer"/><property name="vocationWithPay" column="VOCATION_WITH_PAY" type="integer"/><property name="yearPay" column="YEAR_PAY" type="integer"/></component>

【Property】
*property元素用于指定类的属性和表的字段的映射
  - name:制定该持久化类的属性的名字
  - column:指定与类的属性映射的表的字段名。如果没有设置该属性,Hibernate将直接使用类的属性名作为字段名。
  - type:指定Hibernate映射类型。Hibernate映射类型是Java类型与SQL类型的桥梁。如果没有为摸个属性显示设定映射类型,Hibernate会运用反射机制先识别出持久化类的特定属性的Java类型,然后自动使用与之对应的默认的Hibernate映射类型。
  - not-null:若该属性值为true,表名不允许为null,默认为false
  - access:指定Hibernate的默认的属性访问策略。默认值为property,即使用getter,setter方法来访问属性。若指定field,则Hibernate会忽略getter/setter方法,而通过反射访问成员变量
  - unique:设置是否为该属性所映射的数据列添加唯一约束。
【Java时间和日期类型的Hibernate映射】
*在Java中,代表时间和日期的类型包括:java.util.Date和java.util.Calendar,此外,在JDBC API中还提供了3个扩展了java.util.Date类的子类:java.sql.Date,java.sql.Time,java.sql.Timestamp,则三个类分别和标准SQL类型中的DATE,TIME和TIMESTAMP类型对应。
|------------------------------------------------------------------------------------------||映射类型     |Java类型                          |标准SQL类型|描述                         ||-------------|----------------------------------|-----------|-----------------------------||date         |java.util.Date或java.sql.Date     |DATE       |代表日期:yyyy-MM-dd          ||-------------|----------------------------------|-----------|-----------------------------||time         |java.util.Date或java.sql.Time     |TIME       |代表时间:hh:mi:ss            ||-------------|----------------------------------|-----------|-----------------------------||timestamp    |java.util.Date或java.sql.timestamp|TIMESTAMP  |代表时间和日期:yyyymmddhhmiss||-------------|----------------------------------|-----------|-----------------------------||calendar     |java.util.Calendar                |TIMESTAMP  |同上                         ||-------------|----------------------------------|-----------|-----------------------------||calendar_date|java.util.Calendar                |DATE       |代表日期:yyyy-MM-dd          ||------------------------------------------------------------------------------------------|

*在标准SQL中,DATE类型表示日期,TIME类型表示时间,TIMESTAMP类型表示时间戳,同时包含日期和时间信息。
【使用Hibernate内置映射类型】
*以下情况下必须显示指定Hibernate映射类型
  - 一个Java类型可能对应多个Hibernate映射类型。例如:如果持久化类的属性为java.util.Date类型,对应的Hibernate映射类型可以是date,time或timestamp.此时必须根据对应的数据表的字段的SQL类型,来确定Hibernate映射类型。如果字段为DATE类型,那么Hibernate映射类型为date;如果字段为TIME类型,那么Hibernate映射类型为time;如果字段为TIMESTAMP类型,那么Hibernate映射类型为timestamp。
【一对多关联关系】
*在域模型中,类与类之间最普遍的关系就是关联关系。
*在UML中,关联是有方向的。
  - 以Customer和Order为例:一个用户能发出多个订单,而一个订单只能属于一个客户。从Order到Customer的关联式多对一关联;而从Customer到Order是一对多关联
  - 单向关联
  - 双向关联
【单项n-1】
*单项n-1关联只需从n的一端可以访问1的一端
*域模型:从Order到Customer的多对一单向关联需要在Order类中定义一个Customer属性,而在Customer类中无需定义存放Order对象的集合属性
*关系数据模型:ORDERS表中的CUSTOMER_ID参照CUSTOMER表的主键
【双向1-n】
*双向1-n与双向n-1是完全相同的两种情形
*双向1-n需要在1的一端可以访问n的一端,反之亦然。
*域模型:从Order到Customer的多对一双向关联需要在Order类中定义一个Customer属性,而在Custome类中需定义存放Order对象的集合属性
*关系数据模型:ORDERS表中的CUSTOMER_ID参照CUSTOMER表的主键
*当Session从数据库中加载Java集合时,创建的是Hibernate内置集合类的实例,因此在持久化类中定义集合属性时必须把属性声明为Java接口类型
  - Hibernate的内置集合类具有集合代理功能,支持延迟检索策略
  - 事实上,Hibernate的内置集合类封装了JDK中的集合类,这使得Hibernate能够对缓存中的集合对象进行脏检查,按照集合对象的状态来同步更新数据库。
*在定义集合属性时,通常把它初始化为集合实现类的一个实例。这样可以提高程序的健壮性,避免应用程序访问取值为null的集合的方法抛出NullPointerException
private Set<Order> orders = new HashSet<Order>();public Set<Order> getOrders() {return orders;}public void setOrders(Set<Order> orders) {this.orders = orders;}

【set】
*<set>元素用来映射持久化类的set类型的属性
  - name:设定带映射的持久化类的属性
【key】
*<key>元素设定与所关联的持久化类对应的表的外键
  - column:指定关联表的外键名
【one-to-many】
*<one-to-many>元素设定集合属性中所关联的持久化类
  - class:指定关联的持久化类的类名
【<set>元素的inverse属性】
*在Hibernate中通过对inverse属性来据定是由双向关联的哪一方面来维护表和表之间的关系。inverse=false的为主动方,inverse=true的为被动方,由主动方负责维护关联关系
*在没有设置inverse=true的情况下,父子两边都维护父子关系
*在1-n关系中,将n方设为主控方将有足浴性能改善(如果要国家元首记住全国人民的名字,不是太可能,但要让全国人民知道国家元首,就容易得多)
*在1-n关系中,若将1方设为主控方
  - 会额外多出update语句。
  - 插入数据时无法同时插入外键列,因而无法为外键列添加非空约束
0 0