《Hibernate对象关系映射课件》由会员分享,可在线阅读,更多相关《Hibernate对象关系映射课件(67页珍藏版)》请在金锄头文库上搜索。
1、Prepared by TongGang对象关系映射对象关系映射Hibernate对象关系映射Prepared by TongGangHibernate 配置文件Hibernate对象关系映射Prepared by TongGangHibernateHibernate配置文件配置文件 Hibernate 配置文件主要用于配置数据库连接和 Hibernate 运行时所需的各种属性每个 Hibernate 配置文件对应一个 Configuration 对象Hibernate配置文件可以有两种格式:hibernate.propertieshibernate.cfg.xmlhibernate.cfg.
2、xml Hibernate对象关系映射Prepared by TongGanghibernate.cfg.xml的常用属性JDBC 连接属性connection.url:数据库URL connection.username:数据库用户名connection.password:数据库用户密码 connection.driver_class:数据库JDBC驱动 dialectdialect:配置数据库的方言,根据底层的数据库不同产生不同的sql语句,Hibernate 会针对数据库的特性在访问时进行优化Hibernate对象关系映射Prepared by TongGanghibernate.cfg
3、.xml的常用属性C3P0 数据库连接池属性hibernate.connection.provider_class: 该类用来向 Hibernate 提供JDBC连接hibernate.c3p0.max_size: 数据库连接池的最大连接数hibernate.c3p0.min_size: 数据库连接池的最小连接数hibernate.c3p0.timeout: 数据库连接池中连接对象在多长时间没有使用过后,就应该被销毁hibernate.c3p0.max_statements: 缓存 Statement 对象的数量hibernate.c3p0.idle_test_period: 表示连接池检测线
4、程检测线程多长时间检测一次池内的所有链接对象是否超时. 连接池本身不会把自己从连接池中移除,而是专门有一个线程按照一定的时间间隔来做这件事,这个线程通过比较连接对象最后一次被使用时间和当前时间的时间差来和 timeout 做对比,进而决定是否销毁这个连接对象。 hibernate.c3p0.acquire_increment: 当数据库连接池中的连接耗尽时, 同一时刻获取多少个数据库连接hibernate.c3p0.validate: 是否每次连接都验证连接是否可用Hibernate对象关系映射Prepared by TongGanghibernate.cfg.xml的常用属性其他show_s
5、ql:是否将运行期生成的SQL输出到日志以供调试。取值 true | false format_sql:是否将 SQL 转化为格式良好的 SQL . 取值 true | falseuse_sql_comments:是否在 Hibernate 生成的 SQL 语句中添加有助于调试的注释hbm2ddl.auto:在启动和停止时自动地创建,更新或删除数据库模式。取值 create | update | create-drop | validate*hibernate.jdbc.fetch_sizehibernate.jdbc.batch_sizeHibernate对象关系映射Prepared by
6、TongGangjdbc.fetch_size jdbc.fetch_size 和和 jdbc.batch_size jdbc.batch_sizehibernate.jdbc.fetch_size:实质是调用 Statement.setFetchSize() 方法设定设定 JDBC JDBC 的的 Statement Statement 读取数据读取数据的时候每次从数据库中取出的记录条数的时候每次从数据库中取出的记录条数。例如一次查询1万条记录,对于Oracle的JDBC驱动来说,是不会 1 次性把1万条取出来的,而只会取出 fetchSize 条数,当记录集遍历完了这些记录以后,再去数据库
7、取 fetchSize 条数据。因此大大节省了无谓的内存消耗。Fetch Size设的越大,读数据库的次数越少,速度越快;Fetch Size越小,读数据库的次数越多,速度越慢。Oracle数据库的JDBC驱动默认的Fetch Size = 10,是一个保守的设定,根据测试,当Fetch Size=50时,性能会提升1倍之多,当 fetchSize=100etchSize=100,性能还能继续提升20%,Fetch Size继续增大,性能提升的就不显著了。并不是所有的数据库都支持Fetch Size特性,例如MySQL就不支hibernate.jdbc.batch_size:设定对数据库进行批
8、量删除,批量更设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小新和批量插入的时候的批次大小,类似于设置缓冲区大小的意思。batchSize 越大,批量操作的向数据库发送sql的次数越少,速度就越快。测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删除1万条记录需要25秒,Batch Size = 50的时候,删除仅仅需要5秒!Oracle数据库 batchSize=30atchSize=30 的时候比较合适。Hibernate对象关系映射Prepared by TongGang对象关系映射文件Hibernate对象关系映射Prepared by
9、 TongGang实体类和数据库的映射文件*.hbm.xml实体类和关系数据库之间的映射可以用一个XML文档来定义。通过实体类的数据库映射文件,Hibernate可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据库表列之间的对应关系在运行时 Hibernate 将根据这个映射文件来生成各种 SQL 语句映射文件的扩展名为 .hbm.xmlHibernate对象关系映射Prepared by TongGang映射文件说明hibernate-mapping类层次:class主键。id基本类型:property实体引用类: many-to-one | one-to-one集合:se
10、t | list | map | arrayone-to-manymany-to-many子类:subclass | joined-subclass其它:component | any 等查询语句:query(用来放置查询语句,便于对数据库查询的统一管理和优化)一个 hibernate-mapping 中可以同时定义多个类. 但更推荐推荐为每个类都创建一个单独的映射文件为每个类都创建一个单独的映射文件Hibernate对象关系映射Prepared by TongGanghibernate-mappinghibernate-mapping hibernate-mapping 是是 hiberna
11、te hibernate 映射文件的根映射文件的根元素元素schema: schema: 指定所映射的数据库指定所映射的数据库schemaschema的名称。若指定该属的名称。若指定该属性性, , 则表明会自动添加该则表明会自动添加该 schema schema 前缀前缀catalog:catalog:指定所映射的数据库指定所映射的数据库catalogcatalog的名称。的名称。 default-cascadedefault-cascade( (默认为默认为 none): none): 设置设置hibernatehibernate默认的默认的级联风格级联风格. . 若配置若配置 Java J
12、ava 属性属性, , 集合映射时没有指定集合映射时没有指定 cascade cascade 属性属性, , 则则 Hibernate Hibernate 将采用此处指定的级联风将采用此处指定的级联风格格. . default-accessdefault-access ( (默认为默认为 property): property): 指定指定 Hibernate Hibernate 的默认的属性访问策略。默认值为的默认的属性访问策略。默认值为 property, property, 即使用即使用 getter, setter getter, setter 方法来访问属性方法来访问属性. . 若指
13、定若指定 access, access, 则则 Hibernate Hibernate 会忽略会忽略 getter/setter getter/setter 方法方法, , 而通过反射访而通过反射访问成员变量问成员变量. .default-lazydefault-lazy( (默认为默认为 true): true): 设置设置 Hibernat morning Hibernat morning的的延迟加载策略延迟加载策略. . 该属性的默认值为该属性的默认值为 true, true, 即启用延迟加即启用延迟加载策略载策略. . 若配置若配置 Java Java 属性映射属性映射, , 集合映射
14、时没有指定集合映射时没有指定 lazy lazy 属性属性, , 则则 Hibernate Hibernate 将采用此处指定的延迟加载策将采用此处指定的延迟加载策略略 auto-import (auto-import (默认为默认为 true): true): 指定是否可以在查询语言指定是否可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。中使用非全限定的类名(仅限于本映射文件中的类)。 package (package (可选可选): ): 指定一个包前缀,如果在映射文档中没指定一个包前缀,如果在映射文档中没有指定全限定的类名,有指定全限定的类名, 就使用这个作为包名。就使用这
15、个作为包名。 Hibernate对象关系映射Prepared by TongGangclassclass class 元素用于指定类和表的映射元素用于指定类和表的映射namename: :指定该持久化类映射的持久化类的类名指定该持久化类映射的持久化类的类名tabletable: :指定该持久化类映射的表名指定该持久化类映射的表名, Hibernate , Hibernate 默认默认以持久化类的类名作为表名以持久化类的类名作为表名dynamic-insertdynamic-insert: : 若设置为若设置为 true, true, 表示当保存一个对表示当保存一个对象时象时, , 会动态生成会
16、动态生成 insert insert 语句语句, insert , insert 语句中仅包语句中仅包含所有取值不为含所有取值不为 null null 的字段的字段. . 默认值为默认值为 false falsedynamic-updatedynamic-update: : 若设置为若设置为 true, true, 表示当更新一个对表示当更新一个对象时象时, , 会动态生成会动态生成 update update 语句语句, update , update 语句中仅包语句中仅包含所有取值需要更新的字段含所有取值需要更新的字段. . 默认值为默认值为 false falseselect-befor
17、e-updateselect-before-update: :设置设置 Hibernate Hibernate 在更新某个在更新某个持久化对象之前是否需要先执行一次查询持久化对象之前是否需要先执行一次查询. . 默认值为默认值为 falsefalsebatch-sizebatch-size: :在关联对象图时在关联对象图时, , 指定根据指定根据 OID OID 来抓取来抓取实例时每批抓取的实例数实例时每批抓取的实例数. .lazylazy: : 指定是否使用延迟加载指定是否使用延迟加载. . mutablemutable: : 若设置为若设置为 true, true, 等价于所有的等价于所有
18、的 元素的元素的 update update 属性为属性为 false, false, 表示整个实例不能被表示整个实例不能被更新更新. . 默认为默认为 true. true. discriminator-valuediscriminator-value: : 指定区分不同子类的值指定区分不同子类的值. . 当使当使用用 元素来定义持久化类的继承关系时需元素来定义持久化类的继承关系时需要使用该属性要使用该属性Hibernate对象关系映射Prepared by TongGang映射对象标识符Hibernate 使用对象标识符使用对象标识符(OID) (OID) 来建立内存中的对象和数据来建立内
19、存中的对象和数据库表中记录的对应关系库表中记录的对应关系. 对象的 OID 和数据表的主键对应. Hibernate 通过标识符生成器来为 OID 赋值Hibernate Hibernate 推荐在数据表中使用代理主键推荐在数据表中使用代理主键, , 即不具备业务含即不具备业务含义的字段义的字段. 代理主键通常为整数类型, 因为整数类型比字符串类型要节省更多的数据库空间.在对象-关系映射文件中, 元素用来设置对象标识符. 子元素用来设定标识符生成器.Hibernate 提供了标识符生成器接口: IdentifierGenerator, 并提供了各种内置实现Hibernate对象关系映射Prep
20、ared by TongGangididid:设定持久化类的:设定持久化类的 OID OID 和表的主键的映射和表的主键的映射namename: : 标识持久化类标识持久化类 OID OID 的属性名的属性名 columncolumn: : 设置标识属性所映射的数据列的列名设置标识属性所映射的数据列的列名( (主键字段的主键字段的名字名字). ). unsaved-valueunsaved-value: :若设定了该属性若设定了该属性, Hibernate , Hibernate 会通过比较持会通过比较持久化类的久化类的 OID OID 值和该属性值来区分当前持久化类的对象是值和该属性值来区分
21、当前持久化类的对象是否为临时对象否为临时对象typetype: :指定指定 Hibernate Hibernate 映射类型映射类型. Hibernate . Hibernate 映射类型是映射类型是 Java Java 类型与类型与 SQL SQL 类型的桥梁类型的桥梁. . 如果没有为某个属性显式设如果没有为某个属性显式设定映射类型定映射类型, Hibernate , Hibernate 会运用反射机制先识别出持久化类会运用反射机制先识别出持久化类的特定属性的的特定属性的 Java Java 类型类型, , 然后自动使用与之对应的默认的然后自动使用与之对应的默认的 Hibernate Hi
22、bernate 映射类型映射类型Java Java 的基本数据类型和包装类型对应相同的的基本数据类型和包装类型对应相同的 Hibernate Hibernate 映映射类型射类型. . 基本数据类型无法表达基本数据类型无法表达 null, null, 所以对于所以对于持久化类持久化类的的 OID OID 推荐使用包装类型推荐使用包装类型Hibernate对象关系映射Prepared by TongGanggeneratorgenerator generatorgenerator:设定持久化类设定标识符生成器:设定持久化类设定标识符生成器class: class: 指定使用的标识符生成器全限定类
23、名或其缩写名指定使用的标识符生成器全限定类名或其缩写名Hibernate对象关系映射Prepared by TongGang主键生成策略主键生成策略generatorgeneratorHibernate提供的内置标识符生成器: Hibernate对象关系映射Prepared by TongGangincrement 标识符生成器increment 标识符生成器由由 Hibernate Hibernate 以递增的方式为代理主键赋值Hibernate 会先读取 NEWS 表中的主键的最大值, 而接下来向 NEWS 表中插入记录时, 就在 max(id) 的基础上递增, 增量为 1.适用范围:由于
24、 increment 生存标识符机制不依赖于底层数据库系统, 因此它适合所有的数据库系统适用于只有单个 Hibernate 应用进程应用进程访问同一个数据库的场合, 在集群环境下不推荐使用它不推荐使用它OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常Hibernate对象关系映射Prepared by TongGangidentity 标识符生成器identity 标识符生成器由底层数据库来负责生成标识符, 它要求底层数据库把主键定义为自动增长字段类型把主键定义为自动增长字段类型适用范围:由于 identity 生成标识符
25、的机制依赖于底层数据库系统, 因此, 要求底层数据库系统必须支持自动增长字段类型要求底层数据库系统必须支持自动增长字段类型. 支持自动增长字段类型的数据库包括: DB2, Mysql, MSSQLServer, Sybase 等OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常Hibernate对象关系映射Prepared by TongGangsequence 标识符生成器sequence 标识符生成器利用底层数据库提供的序列序列来生成标识符. Hibernate 在持久化一个 News 对象时, 先从底层数据库的 new
26、s_seq 序列中获得一个唯一的标识号, 再把它作为主键值适用范围:由于 sequence 生成标识符的机制依赖于底层数据库系统的序列, 因此, 要求底层数据库系统必须支持序列底层数据库系统必须支持序列. 支持序列的数据库包括: DB2 Oracle 等OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常Hibernate对象关系映射Prepared by TongGanghilo 标识符生成器hilo 标识符生成器由 Hibernate 按照一种 high/low 算法算法*生成标识符, 它从数据库的特定表的字段中获取 hi
27、gh 值.Hibernate 在持久化一个 News 对象时, 由 Hibernate 负责生成主键值. hilo hilo 标识符生成器在生成标识符时标识符生成器在生成标识符时, , 需要需要读取并修改读取并修改 HI_TABLE HI_TABLE 表中的表中的 NEXT_VALUE NEXT_VALUE 值值.适用范围:由于 hilo 生存标识符机制不依赖于底层数据库系统, 因此它适合所有的数据库系统OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常Hibernate对象关系映射Prepared by TongGangn
28、ative 标识符生成器native 标识符生成器依据底层数据库对自动生成标识符的支持能力, 来选择使用 identity, sequence 或 hilo 标识符生成器. 适用范围:由于 native 能根据底层数据库系统的类型, 自动选择合适的标识符生成器, 因此很适合于跨数据库平台开发OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常Hibernate对象关系映射Prepared by TongGangPropertyproperty property 元素用于指定类的属性和表的字段的元素用于指定类的属性和表的字段的映
29、射映射namename: :指定该持久化类的属性的名字指定该持久化类的属性的名字columncolumn: :指定与类的属性映射的表的字段名指定与类的属性映射的表的字段名. . 如果没有如果没有设置该属性设置该属性, Hibernate , Hibernate 将直接使用类的属性名作为将直接使用类的属性名作为字段名字段名. . typetype: :指定指定 Hibernate Hibernate 映射类型映射类型. Hibernate . Hibernate 映射类映射类型是型是 Java Java 类型与类型与 SQL SQL 类型的桥梁类型的桥梁. . 如果没有为某个如果没有为某个属性显
30、式设定映射类型属性显式设定映射类型, Hibernate , Hibernate 会运用反射机制会运用反射机制先识别出持久化类的特定属性的先识别出持久化类的特定属性的 Java Java 类型类型, , 然后自然后自动使用与之对应的默认的动使用与之对应的默认的 Hibernate Hibernate 映射类型映射类型. .not-nullnot-null: :若该属性值为若该属性值为 true, true, 表明不允许为表明不允许为 null, null, 默认为默认为 false falseinsertinsert: : 如果为如果为 false, false, 在在 insert inse
31、rt 语句中不包含该语句中不包含该字段字段, , 表明该字段永远不能被插入表明该字段永远不能被插入. . 默认值为默认值为 true trueupdateupdate: :如果为如果为 false, false, 在在 update update 语句中不包含该字语句中不包含该字段段, , 表明该字段永远不能被更新表明该字段永远不能被更新. . 默认值为默认值为 true trueaccessaccess: :指定指定 Hibernate Hibernate 的默认的属性访问策略。默的默认的属性访问策略。默认值为认值为 property, property, 即使用即使用 getter, se
32、tter getter, setter 方法来访方法来访问属性问属性. . 若指定若指定 access, access, 则则 Hibernate Hibernate 会忽略会忽略 getter/setter getter/setter 方法方法, , 而通过反射访问成员变量而通过反射访问成员变量Hibernate对象关系映射Prepared by TongGangproperty property 元素用于指定类的属性和表的字段的元素用于指定类的属性和表的字段的映射映射uniqueunique: : 设置是否为该属性所映射的数据列添加唯一设置是否为该属性所映射的数据列添加唯一约束约束. .
33、若设置为若设置为 true, true, 就允许该字段作为就允许该字段作为 property- property-ref ref 引用的目标引用的目标indexindex: : 指定一个字符串的索引名称指定一个字符串的索引名称. . 当系统需要当系统需要 Hibernate Hibernate 自动建表时自动建表时, , 用于为该属性所映射的数据用于为该属性所映射的数据列创建索引列创建索引, , 从而加快给予该数据列的查询从而加快给予该数据列的查询. .lengthlength: : 指定该属性所映射数据列的字段的长度指定该属性所映射数据列的字段的长度scalescale: : 指定该属性所映
34、射数据列的小数位数指定该属性所映射数据列的小数位数, , 对对 double, float, decimal double, float, decimal 等类型的数据列有效等类型的数据列有效. .formulaformula:设置一个:设置一个 SQL SQL 表达式表达式, Hibernate , Hibernate 将根据将根据它来计算出派生属性的值它来计算出派生属性的值. . 派生属性派生属性: : 并不是持久化类的所有属性都直接和表的并不是持久化类的所有属性都直接和表的字段匹配字段匹配, , 持久化类的有些属性的值必须在运行时通持久化类的有些属性的值必须在运行时通过计算才能得出来过计
35、算才能得出来, , 这种属性称为派生属性这种属性称为派生属性使用使用 formula formula 属性时属性时formula=“(sql)” formula=“(sql)” 的英文括号不能少的英文括号不能少Sql Sql 表达式中的列名和表名都应该和数据库对应表达式中的列名和表名都应该和数据库对应, , 而而不是和持久化对象的属性对应不是和持久化对象的属性对应如果需要在如果需要在 formula formula 属性中使用参数属性中使用参数, , 这直接使用这直接使用 where cur.id=id where cur.id=id 形式形式, , 其中其中 id id 就是参数就是参数,
36、, 和当前和当前持久化对象的持久化对象的 id id 属性对应的列的属性对应的列的 id id 值将作为参数值将作为参数传入传入. . Property*Hibernate对象关系映射Prepared by TongGangJava Java 类型类型, Hibernate , Hibernate 映射类型及映射类型及 SQL SQL 类型之间的对应关系类型之间的对应关系 Hibernate对象关系映射Prepared by TongGangJava Java 类型类型, Hibernate , Hibernate 映射类型及映射类型及 SQL SQL 类型之间的对应关系类型之间的对应关系Hi
37、bernate对象关系映射Prepared by TongGangJava 时间和日期类型的 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 类型对应在标准 SQL 中, DATE 类型表示日期, TIME 类型表
38、示时间, TIMESTAMP 类型表示时间戳, 同时包含日期和时间信息. Hibernate对象关系映射Prepared by TongGangJava 大对象类型的 Hiberante 映射类型在 Java 中, java.lang.String 可用于表示长字符串(长度超过 255), 字符数组 byte 可用于存放图片或文件的二进制数据. 此外, 在 JDBC API 中还提供了 java.sql.Clob 和 java.sql.Blob 类型, 它们分别和标准 SQL 中的 CLOB 和 BLOB 类型对应. CLOB 表示字符串大对象(Character Large Object),
39、 BLOB表示二进制大对象(Binary Large Object)Mysql 不支持标准 SQL 的 CLOB 类型, 在 Mysql 中, 用 TEXT, MEDIUMTEXT 及 LONGTEXT 类型来表示长度操作 255 的长文本数据在持久化类中, 二进制大对象可以声明为 byte 或 java.sql.Blob 类型; 字符串可以声明为 java.lang.String 或 java.sql.Blob实际上在 Java 应用程序中处理长度超过 255 的字符串, 使用 java.lang.String 比 java.sql.Clob 更方便; 使用 byte 比 java.sql.
40、Blob 更方便. Hibernate对象关系映射Prepared by TongGang使用 Hibernate 内置映射类型以下情况下必须显式指定必须显式指定 Hibernate Hibernate 映射类型映射类型一个 Java 类型对应多个 Hibernate 映射类型时. 例如: 如果持久化类的属性为 java.util.Date 类型, 对应的 Hibernate 映射类型可以是 date, time 或 timestamp. 此时必须根据对应的数据表的字段的 SQL 类型, 来确定 Hibernate 映射类型. 如果字段为 DATE 类型, 那么 Hibernate 映射类型为
41、 date; 如果字段为 TIME 类型, 那么 Hibernate 映射类型为 time; 如果字段为 TIMESTATMP 类型, 那么 Hibernate 映射类型为 timestamp.Hibernate对象关系映射Prepared by TongGang练习1根据给定的 Java 类写出相对应的 hbm.xml 文件, 由 Hibernate 生成 对应的数据表,并完成对 Customer 记录在数据表中增删改查操作Hibernate对象关系映射Prepared by TongGang映射组成关系*建立域模型和关系数据模型有着不同的出发点:域模型: 由程序代码组成由程序代码组成, ,
42、 通过细化持久化类的的粒度可提高代码的可通过细化持久化类的的粒度可提高代码的可重用性重用性, , 简化编程简化编程关系数据模型: 由关系数据组成由关系数据组成, 在存在数据冗余的情况下, 需要把粗粒度的表拆分成具有外键参照关系的几个细粒度的表, 从而节省存储空间; 另一方面, 在没有数据冗余的情况下在没有数据冗余的情况下, , 应该尽可能减少表的数目应该尽可能减少表的数目, , 简化表之间的参照关系简化表之间的参照关系, , 以便提高数据的访问速度以便提高数据的访问速度Hibernate对象关系映射Prepared by TongGang映射组成关系Hibernate 把持久化类的属性分为两种
43、: 值值(value)(value)类型类型: 没有没有 OID OID, 不能被单独持久化不能被单独持久化, 生命周期依赖于所属生命周期依赖于所属的持久化类的对象的生命周期的持久化类的对象的生命周期实体(entity)类型: 有 OID, 可以被单独持久化, 有独立的生命周期显然无法直接用 property 映射 name 属性Hibernate 使用 元素来映射组成关系, 该元素表明 pay 属性是 Worker 类一个组成部分, 在 Hibernate 中称之为组件组件Hibernate对象关系映射Prepared by TongGangcomponent 元素来映射组成关系元素来映射组
44、成关系class:class:设定组成关系属性的类型设定组成关系属性的类型, , 此处表明此处表明 pay pay 属属性为性为 Pay Pay 类型类型 元素指定组件属性所属的整体类元素指定组件属性所属的整体类name: name: 整体类在组件类中的属性名整体类在组件类中的属性名Hibernate对象关系映射Prepared by TongGang映射一对多关联关系Hibernate对象关系映射Prepared by TongGang一对多关联关系在域模型中, 类与类之间最普遍的关系就是关联关系. 在 UML 中, 关联是有方向的. 以 Customer 和 Order 为例: 一个用户能
45、发出多个订单, 而一个订单只能属于一个客户. 从 Order 到 Customer 的关联使多对一关联; 而从 Customer 到 Order 是一对多关联单向关联双向关联Hibernate对象关系映射Prepared by TongGang单向 n-1单向 n-1 关联只需从 n 的一端可以访问 1 的一端域模型: 从 Order 到 Customer 的多对一单向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中无需定义存放 Order 对象的集合属性关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键ORD
46、ERS 表CUSTOMERS 表Hibernate对象关系映射Prepared by TongGang单向 n-1显然无法直接用 property 映射 customer 属性因为 Customer 有主键, 所以也不能使用 component 进行映射Hibernate 使用 元素来映射多对一关联关系Hibernate对象关系映射Prepared by TongGangmany-to-one 元素来映射多对一的关联关系元素来映射多对一的关联关系name: name: 设定待映射的持久化类的属性的名字设定待映射的持久化类的属性的名字column: column: 设定和持久化类的属性对应的表的
47、外键设定和持久化类的属性对应的表的外键classclass:设定待映射的持久化类的属性的类型:设定待映射的持久化类的属性的类型Hibernate对象关系映射Prepared by TongGang双向 1-n双向 1-n 与 双向 n-1 是完全相同的两种情形双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然.域模型:从 Order 到 Customer 的多对一单向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中需定义存放 Order 对象的集合属性关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的
48、主键ORDERS 表CUSTOMERS 表Hibernate对象关系映射Prepared by TongGang双向 1-n当 Session 从数据库中加载 Java 集合时, 创建的是 Hibernate 内置集合类的实例, 因此在持久化类中定义集合属在持久化类中定义集合属性时必须把属性声明为性时必须把属性声明为 Java Java 接口类型接口类型Hibernate 的内置集合类具有集合代理功能, 支持延迟检索策略Hibernate 的内置集合类都封装了 JDK 中的集合类, 这使得 Hibernate 能够对缓存中的集合对象进行脏检查, 按照集合对象的状态来同步更新数据库。在定义集合属
49、性时在定义集合属性时, , 通常把它初始化为集合实现类的一个实例通常把它初始化为集合实现类的一个实例. 这样可以提高程序的健壮性, 避免应用程序访问取值为 null 的集合的方法而抛出 NullPointerExceptionHibernate对象关系映射Prepared by TongGang双向 1-nHibernate 使用 元素来映射 set 类型的属性Hibernate对象关系映射Prepared by TongGangset 元素来映射持久化类的元素来映射持久化类的 set set 类型的属性类型的属性name: name: 设定待映射的持久化类的属性名设定待映射的持久化类的属性名
50、Hibernate对象关系映射Prepared by TongGangkey 元素设定与所关联的持久化类对应的表的外键元素设定与所关联的持久化类对应的表的外键column: column: 指定关联表的外键名指定关联表的外键名Hibernate对象关系映射Prepared by TongGangone-to-many 元素设定集合属性中所关联的持久化元素设定集合属性中所关联的持久化类类class: class: 指定关联的持久化类的类名指定关联的持久化类的类名Hibernate对象关系映射Prepared by TongGangcascade 属性在对象 关系映射文件中, 用于映射持久化类之间
51、关联关系的元素, , 和 都有一个 cascade 属性, 它用于指定指定如何操纵与当前对象关联的其他对象如何操纵与当前对象关联的其他对象. Hibernate对象关系映射Prepared by TongGang 元素的 inverse 属性在在hibernatehibernate中通过对中通过对 inverse inverse 属性的来决定是由双向关联属性的来决定是由双向关联的哪一方来维护表和表之间的关系的哪一方来维护表和表之间的关系. inverse=false . inverse=false 的为主的为主动方,动方,inverse=true inverse=true 的为被动方的为被动方
52、, , 由主动方负责维护关联由主动方负责维护关联关系关系在没有设置在没有设置 inverse=true inverse=true 的情况下,父子两边都维护父子的情况下,父子两边都维护父子 关系关系 在 1-n 关系中,将 n 方设为主控方将有助于性能改善(如果要国家元首记住全国人民的名字,不是太可能,但要让全国人民知道国家元首,就容易的多)在 1-N 关系中,若将 1 方设为主控方会额外多出 update 语句。插入数据时无法同时插入外键列,因而无法为外键列添加非空约束Hibernate对象关系映射Prepared by TongGang在数据库中对集合排序 元素有一个 order-by 属性
53、, 如果设置了该属性, 当 Hibernate 通过 select 语句到数据库中检索集合对象时, 利用 order by 子句进行排序order-by 属性中还可以加入 SQL 函数Hibernate对象关系映射Prepared by TongGang映射一对一关联关系Hibernate对象关系映射Prepared by TongGang1 - 1域模型关系数据模型:按照外键映射:按照主键映射:DEPARTMENTS 表MANAGERS 表DEPARTMENTS 表MANAGERS 表Hibernate对象关系映射Prepared by TongGang基于外键映射的 1-1对于基于外键的1
54、-1关联,其外键可以存放在任意一边,在需在需要存放外键一端,增加要存放外键一端,增加 many-to-one many-to-one 元素元素。为 many-to-one元素增加 unique=“true” 属性来表示为1-1关联,并用name属性来指定关联属性的属性名另一端需要使用one-to-one元素,该元素使用 property-refproperty-ref 属性指定使用被关联实体主键以外的字段作为关联字段不使用 property-ref 属性的 sql使用 property-ref 属性的 sqlHibernate对象关系映射Prepared by TongGang基于主键映射的
55、1-1基于主键的映射策略:指一端的主键生成器使用 foreign 策略,表明根据”对方对方”的主键来生成自己的主键,自己并不能独立生成主键. 子元素指定使用当前持久化类的哪个属性作为 “对方对方”采用foreign主键生成器策略的一端增加 one-to-one 元素映射关联属性,其 one-to-one 属性还应增加 constrained=“true”constrained=“true” 属性;另一端增加one-to-one元素映射关联属性。constrained(约束):指定为当前持久化类对应的数据库表的主键添加一个外键约束,引用被关联的对象(“对方对方”)所对应的数据库表主键Hibern
56、ate对象关系映射Prepared by TongGang映射多对多关联关系Hibernate对象关系映射Prepared by TongGang单向 n-n域模型: 关系数据模型CATEGORIES 表CATEGORIES_ITEMS 表ITEMS 表Hibernate对象关系映射Prepared by TongGang单向 n-nn-n 的关联必须使用连接表的关联必须使用连接表与 1-n 映射类似,必须为 set 集合元素添加 key 子元素,指定 CATEGORIES_ITEMS 表中参照 CATEGORIES 表的外键为 CATEGORIY_ID. 与 1-n 关联映射不同的是,建立
57、n-n 关联时, 集合中的元素使用 many-to-many. many-to-many 子元素的 class 属性指定 items 集合中存放的是 Item 对象, column 属性指定 CATEGORIES_ITEMS 表中参照 ITEMS 表的外键为 ITEM_IDHibernate对象关系映射Prepared by TongGangHibernate对象关系映射Prepared by TongGang双向 n-n域模型: 关系数据模型CATEGORIES 表CATEGORIES_ITEMS 表ITEMS 表Hibernate对象关系映射Prepared by TongGang双向n-
58、n关联 双向 n-n 关联需要两端都使用集合属性两端都使用集合属性双向n-n关联必须使用连接表必须使用连接表集合属性应增加 key 子元素用以映射外键列, 集合元素里还应增加many-to-many子元素关联实体类在双向在双向 n-n 关联的两边都需指定连接表的表名及外键列的列关联的两边都需指定连接表的表名及外键列的列名名. 两个集合元素两个集合元素 set 的的 table 元素的值必须指定,而且必元素的值必须指定,而且必须相同。须相同。set元素的两个子元素:元素的两个子元素:key 和和 many-to-many 都都必须指定必须指定 column 属性,其中,属性,其中,key 和和
59、many-to-many 分分别指定本持久化类和关联类在连接表中的外键列名,因此两别指定本持久化类和关联类在连接表中的外键列名,因此两边的边的 key 与与 many-to-many 的的column属性交叉相同属性交叉相同。也就是说,一边的set元素的key的 cloumn值为a,many-to-many 的 column 为b;则另一边的 set 元素的 key 的 column 值 b,many-to-many的 column 值为 a. 对于双向对于双向 n-n 关联关联, 须把其中一端的须把其中一端的 inverse 设置为设置为 true, 否则可能会造成主键冲突.Hibernat
60、e对象关系映射Prepared by TongGang映射继承关系Hibernate对象关系映射Prepared by TongGang继承映射对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念。Hibernate 的继承映射可以理解持久化类之间的继承关系。例如:人和学生之间的关系。学生继承了人,可以认为学生是一个特殊的人,如果对人进行查询,学生的实例也将被得到。Hibernate对象关系映射Prepared by TongGang继承映射Hibernate支持三种继承映射策略:每个具体类一张表(table per concrete class) 将域模型中的每一个实体对象映射到一个
61、独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态。 每个类分层结构一张表(table per class hierarchy) 对于继承关系中的子类使用同一个表,这就需要在数据库表中增加额外的区分子类类型的字段。 每个子类一张表(table per subclass) 域模型中的每个类映射到一个表,通过关系数据模型中的外键来描述表之间的继承关系。这也就相当于按照域模型的结构来建立数据库中的表,并通过外键来建立表之间的继承关系。Hibernate对象关系映射Prepared by TongGang采用 subclass 元素的继承映射采用 subclass 的继承映射可以实现
62、对于继承关系中父类和子父类和子类使用同一张表类使用同一张表因为父类和子类的实例全部保存在同一个表中,因此需要在需要在该表内增加一列该表内增加一列,使用该列来区分每行记录到低是哪个类的实例-这个列被称为辨别者列(discriminatordiscriminator).在这种映射策略下,使用使用 subclass subclass 来映射子类来映射子类,使用使用 class class 或或 subclass subclass 的的 discriminator-value discriminator-value 属性指定辨属性指定辨别者列的值别者列的值所有子类定义的字段都不能有非空约束所有子类定义
63、的字段都不能有非空约束。如果为那些字段添加非空约束,那么父类的实例在那些列其实并没有值,这将引起数据库完整性冲突,导致父类的实例无法保存到数据库中Hibernate对象关系映射Prepared by TongGang采用 subclass 元素的继承映射Hibernate对象关系映射Prepared by TongGang采用 joined-subclass 元素的继承映射采用 joined-subclass 元素的继承映射可以实现每个子类一张表每个子类一张表采用这种映射策略时,父类实例保存在父类表中,子类实例由子类实例由父类表和子类表共同存储父类表和子类表共同存储。因为子类实例也是一个特殊的
64、父类实例,因此必然也包含了父类实例的属性。于是将子类和父类共有的属性保存在父类表中,子类增加的属性,则保存在子类表中。在这种映射策略下,无须使用鉴别者列,但需要为每个子类使个子类使用用 key 元素映射共有主键元素映射共有主键,该主键必须与父类标识属性的列名主键必须与父类标识属性的列名相同相同。但如果继承树的深度很深,可能查询一个子类实例时,需要跨越多个表,因为子类的数据一次保存在多个父类中。子类增加的属性可以添加非空约束子类增加的属性可以添加非空约束。因为子类的属性和父类的属性没有保存在同一个表中Hibernate对象关系映射Prepared by TongGang采用 joined-sub
65、class 元素的继承映射Hibernate对象关系映射Prepared by TongGang采用 union-subclass 元素的继承映射采用 union-subclass 元素可以实现将将每一个实体对象映射到一个独立每一个实体对象映射到一个独立的表中的表中。子类增加的属性可以有非空约束子类增加的属性可以有非空约束 - 即父类实例的数据保存在父表中,而子类实例的数据保存在子类表中。子类实例的数据仅保存在子类表中, 而在父类表中没有任何记录在这种映射策略下,子类表的字段会比父类表的映射字段要多,因为子类表的字段等于父类表的字段、加子类增加属性的总和在这种映射策略下,既不需要使用鉴别者列,
66、也无须使用 key 元素来映射共有主键.使用使用 union-subclass union-subclass 映射策略是不可使用映射策略是不可使用 identity identity 的主键生成的主键生成策略策略, 因为同一类继承层次中所有实体类都需要使用同一个主键种子, 即多个持久化实体对应的记录的主键应该是连续的个持久化实体对应的记录的主键应该是连续的. 受此影响, 也不该使用 native 主键生成策略, 因为 native 会根据数据库来选择使用 identity 或 sequence.Hibernate对象关系映射Prepared by TongGang采用 union-subclass 元素的继承映射Hibernate对象关系映射Prepared by TongGang三种继承映射方式的比较 union-subclasssubclassjoined-subclassHibernate对象关系映射Prepared by TongGang练习3Hibernate对象关系映射