- 浏览: 1509570 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (798)
- struts2 (42)
- servlet (20)
- quartz (4)
- jquery & ajax (24)
- tomcat (5)
- javascript (15)
- struts1 (8)
- 搜索关键字及链接 (3)
- fckeditor (3)
- Apache (5)
- spring (22)
- linux (3)
- 企业应用 (8)
- 综合应用 (13)
- 服务器 (2)
- 数据库 (85)
- 性能调优 (21)
- 网络应用 (15)
- 缓存技术 (8)
- 设计模式 (39)
- 面试题 (7)
- 程序人生&前辈程序员 (29)
- java基础 (59)
- hibernate (75)
- log4j (4)
- http (11)
- 架构设计 (28)
- 网页设计 (12)
- java邮件 (4)
- 相关工具 (11)
- ognl (7)
- 工作笔记 (18)
- 知识面扩展 (12)
- oracle异常 (1)
- 正则表达式 (2)
- java异常 (5)
- 项目实践&管理 (1)
- 专业术语 (11)
- 网站参考 (1)
- 论坛话题 (2)
- web应用 (11)
- cxf&webservice (22)
- freemarker (3)
- 开源项目 (9)
- eos (1)
- ibatis (6)
- 自定义标签 (3)
- jsp (3)
- 内部非公开文档(注意:保存为草稿) (0)
- 国内外知名企业 (2)
- 网店 (3)
- 分页 (1)
- 消费者习惯 (2)
- 每日关注 (1)
- 商业信息 (18)
- 关注商业网站 (1)
- 生活常识 (3)
- 新闻 (2)
- xml&JSON (5)
- solaris (1)
- apache.common (3)
- BLOB/CLOB (1)
- lucene (2)
- JMS (14)
- 社会进程 (8)
- SSH扩展 (2)
- 消费心理 (1)
- 珠三角 (1)
- 设计文档 (1)
- XWork&webwork (1)
- 软件工程 (3)
- 数据库及链接 (1)
- RMI (2)
- 国内外知名企业&人物 (1)
最新评论
-
司c马:
简介易懂、
OutputStream和InputStream的区别 -
在世界的中心呼喚愛:
解决我的问题
Java获取客户端的真实IP地址 -
bo_hai:
都是些基本的概念呀!
SSO -
tian_4238:
哥们,你也是搞水利这块的吧。
巧用SQLQuery中的addScalar -
loveEVERYday:
java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp小结
http://www.kuqin.com/docs/hibernate/mapping.html
对象和关系数据库之间的映射是用一个XML文档(XML document)来定义的。这个映射文档被设计为易读的,并且可以手工修改。映射语言是以Java为中心的,意味着映射是按照持久化类的定义来创建的,而非表的定义。
请注意,虽然很多Hibernate用户选择手工定义XML映射文档,也有一些工具来生成映射文档,包括XDoclet,Middlegen和AndroMDA.
让我们从一个映射的例子开始:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping package="eg"> <class name="Cat" table="CATS" discriminator-value="C"> <id name="id" column="uid" type="long"> <generator class="hilo"/> </id> <discriminator column="subclass" type="character"/> <property name="birthdate" type="date"/> <property name="color" not-null="true"/> <property name="sex" not-null="true" update="false"/> <property name="weight"/> <many-to-one name="mate" column="mate_id"/> <set name="kittens"> <key column="mother_id"/> <one-to-many class="Cat"/> </set> <subclass name="DomesticCat" discriminator-value="D"> <property name="name" type="string"/> </subclass> </class> <class name="Dog"> <!-- mapping for Dog could go here --> </class> </hibernate-mapping>
我们现在开始讨论映射文档的内容。我们只描述Hibernate在运行时用到的文档元素和属性。映射文档还包括一些额外的可选属性和元素,它们在使用schema导出工具的时候会影响导出的数据库schema结果。(比如, not-null 属性。)
所有的XML映射都需要定义如上所示的doctype。DTD可以从上述URL中获取,或者在hibernate-x.x.x/src/net/sf/hibernate目录中,或hibernate.jar文件中找到。Hibernate总是会在它的classptah中首先搜索DTD文件。
这个元素包括三个可选的属性。schema属性,指明了这个映射所引用的表所在的schema名称。假若指定了这个属性,表名会加上所指定的schema的名字扩展为全限定名。假若没有指定,表名就不会使用全限定名。default-cascade指定了未明确注明cascade属性的Java属性和集合类Java会采取什么样的默认级联风格。auto-import属性默认让我们在查询语言中可以使用非全限定名的类名。
<hibernate-mapping schema="schemaName" (1) default-cascade="none|save-update" (2) auto-import="true|false" (3) package="package.name" (4) />
(1) |
schema (可选): 数据库schema名称。 |
(2) |
default-cascade (可选 - 默认为 none): 默认的级联风格。 |
(3) |
auto-import (可选 - 默认为 true): 指定是否我们可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。 |
(4) |
package (可选): 指定一个包前缀,如果在映射文档中没有指定全限定名,就使用这个包名。 |
假若你有两个持久化类,它们的非全限定名是一样的(就是在不同的包里面--译者注),你应该设置auto-import="false"。假若说你把一个“import过”的名字同时对应两个类, Hibernate会抛出一个异常。
你可以使用class元素来定义一个持久化类:
<class name="ClassName" (1) table="tableName" (2) discriminator-value="discriminator_value" (3) mutable="true|false" (4) schema="owner" (5) proxy="ProxyInterface" (6) dynamic-update="true|false" (7) dynamic-insert="true|false" (8) select-before-update="true|false" (9) polymorphism="implicit|explicit" (10) where="arbitrary sql where condition" (11) persister="PersisterClass" (12) batch-size="N" (13) optimistic-lock="none|version|dirty|all" (14) lazy="true|false" (15) />
(1) |
name: 持久化类(或者接口)的Java全限定名。 |
(2) |
table: 对应的数据库表名。 |
(3) |
discriminator-value(辨别值) (可选 - 默认和类名一样):一个用于区分不同的子类的值,在多态行为时使用。 |
(4) |
mutable(可变) (可选, 默认值为 true): 表明该类的实例可变(不可变)。 |
(5) |
schema (可选): 覆盖在根<hibernate-mapping>元素中指定的schema名字。 |
(6) |
proxy (可选): 指定一个接口,在延迟装载时作为代理使用。你可以在这里使用该类自己的名字。 |
(7) |
dynamic-update(动态更新) (可选,默认为false): 指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。 |
(8) |
dynamic-insert(动态插入) (可选, 默认为false): 指定用于INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。 |
(9) |
select-before-update (可选,默认值为false): 指定Hibernate除非确定对象的确被修改了,不会执行SQL UPDATE操作。在特定场合(实际上,只会发生在一个临时对象关联到一个新的session中去,执行update()的时候),这说明Hibernate会在UPDATE之前执行一次额外的SQL SELECT操作,来决定是否应该进行UPDATE。 |
(10) |
polymorphism(多形,多态) (可选, 默认值为 implicit (隐式)): 界定是隐式还是显式的使用查询多态。 |
(11) |
where (可选) 指定一个附加的SQLWHERE 条件,在抓取这个类的对象时会一直增加这个条件。 |
(12) |
persister (可选): 指定一个定制的ClassPersister。 |
(13) |
batch-size (可选,默认是1) 指定一个用于根据标识符抓取实例时使用的"batch size"(批次抓取数量)。 |
(14) |
optimistic-lock(乐观锁定) (可选,默认是version): 决定乐观锁定的策略。 |
(15) |
lazy(延迟) (可选): 假若设置 lazy="true",就是设置这个类自己的名字作为proxy接口的一种等价快捷形式。 |
若指明的持久化类实际上是一个接口,也可以被完美地接受。其后你可以用<subclass>来指定该接口的实际实现类名。你可以持久化任何static(静态的)内部类。记得应该使用标准的类名格式,就是说比如:Foo$Bar。
不可变类,mutable="false"不可以被应用程序更新或者删除。这可以让Hibernate做一些小小的性能优化。
可选的proxy属性可以允许延迟加载类的持久化实例。Hibernate开始会返回实现了这个命名接口的CGLIB代理。当代理的某个方法被实际调用的时候,真实的持久化对象才会被装载。参见下面的“用于延迟装载的代理”。
Implicit (隐式)的多态是指,如果查询中给出的是任何超类、该类实现的接口或者该类的名字,都会返回这个类的实例;如果查询中给出的是子类的名字,则会返回子类的实例。 Explicit (显式)的多态是指,只有在查询中给出的明确是该类的名字时才会返回这个类的实例;同时只有当在这个<class>的定义中作为<subclass>或者<joined-subclass>出现的子类,才会可能返回。 大多数情况下,默认的polymorphism="implicit"都是合适的。 显式的多态在有两个不同的类映射到同一个表的时候很有用。(允许一个“轻型”的类,只包含部分表字段)。
persister属性可以让你定制这个类使用的持久化策略。你可以指定你自己实现的net.sf.hibernate.persister.EntityPersister的子类,你甚至可以完全从头开始编写一个net.sf.hibernate.persister.ClassPersister接口的实现,可能是用储存过程调用、序列化到文件或者LDAP数据库来实现的。参阅net.sf.hibernate.test.CustomPersister,这是一个简单的例子(“持久化”到一个Hashtable)。
请注意dynamic-update和dynamic-insert的设置并不会继承到子类,所以在<subclass>或者<joined-subclass>元素中可能需要再次设置。这些设置是否能够提高效率要视情形而定。请用你的智慧决定是否使用。
使用select-before-update通常会降低性能.当是在防止数据库不必要的触发update触发器,这就很有用了。
如果你打开了dynamic-update,你可以选择几种乐观锁定的策略:
-
version(版本检查) 检查version/timestamp字段
-
all(全部) 检查全部字段
-
dirty(脏检查)只检察修改过的字段
-
none(不检查)不使用乐观锁定
我们非常强烈建议你在Hibernate中使用version/timestamp字段来进行乐观锁定。对性能来说,这是最好的选择,并且这也是唯一能够处理在session外进行操作的策略(就是说,当使用Session.update()的时候)。 记住version或timestamp属性永远不能使null,不管何种unsaved-value策略,否则实例会被认为是尚未被持久化的。
被映射的类必须声明对应数据库表主键字段。大多数类有一个JavaBeans风格的属性,为每一个实例包含唯一的标识。<id> 元素定义了该属性到数据库表主键字段的映射。
<id name="propertyName" (1) type="typename" (2) column="column_name" (3) unsaved-value="any|none|null|id_value" (4) access="field|property|ClassName"> (5) <generator class="generatorClass"/> </id>
(1) |
name (可选): 标识属性的名字。 |
(2) |
type (可选): 标识Hibernate类型的名字。 |
(3) |
column (可选 - 默认为属性名): 主键字段的名字。 |
(4) |
unsaved-value (可选 - 默认为null): 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。这可以把这种实例和从以前的session中装载过(可能又做过修改--译者注)但未再次持久化的实例区分开来。 |
(5) |
access (可选 - 默认为property): Hibernate用来访问属性值的策略。 |
如果 name属性不存在,会认为这个类没有标识属性。
unsaved-value 属性很重要!如果你的类的标识属性不是默认为null的,你应该指定正确的默认值。
还有一个另外的<composite-id>声明可以访问旧式的多主键数据。我们强烈不鼓励使用这种方式。
必须声明的<generator>子元素是一个Java类的名字,用来为该持久化类的实例生成唯一的标识。如果这个生成器实例需要某些配置值或者初始化参数,用<param>元素来传递。
<id name="id" type="long" column="uid" unsaved-value="0"> <generator class="net.sf.hibernate.id.TableHiLoGenerator"> <param name="table">uid_table</param> <param name="column">next_hi_value_column</param> </generator> </id>
所有的生成器都实现net.sf.hibernate.id.IdentifierGenerator接口。这是一个非常简单的接口;某些应用程序可以选择提供他们自己特定的实现。当然,Hibernate提供了很多内置的实现。下面是一些内置生成器的快捷名字:
用于为long, short或者int类型生成唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。 在集群下不要使用。
对DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的内置标识字段提供支持。返回的标识符是long, short 或者int类型的。
在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence),而在Interbase中使用生成器(generator)。返回的标识符是long, short或者 int类型的。
使用一个高/低位算法来高效的生成long, short或者 int类型的标识符。给定一个表和字段(默认分别是是hibernate_unique_key 和next_hi)作为高位值得来源。高/低位算法生成的标识符只在一个特定的数据库中是唯一的。在使用JTA获得的连接或者用户自行提供的连接中,不要使用这种生成器。
使用一个高/低位算法来高效的生成long, short或者 int类型的标识符,给定一个数据库序列(sequence)的名字。
用一个128-bit的UUID算法生成字符串类型的标识符。在一个网络中唯一(使用了IP地址)。UUID被编码为一个32位16进制数字的字符串。
使用同样的UUID算法。UUID被编码为一个16个字符长的任意ASCII字符组成的字符串。不能使用在PostgreSQL数据库中
根据底层数据库的能力选择identity, sequence 或者hilo中的一个。
让应用程序在save()之前为对象分配一个标示符。
使用另外一个相关联的对象的标识符。和<one-to-one>联合一起使用。
hilo 和 seqhilo生成器给出了两种hi/lo算法的实现,这是一种很令人满意的标识符生成算法。第一种实现需要一个“特殊”的数据库表来保存下一个可用的“hi”值。第二种实现使用一个Oracle风格的序列(在被支持的情况下)。
<id name="id" type="long" column="cat_id"> <generator class="hilo"> <param name="table">hi_value</param> <param name="column">next_value</param> <param name="max_lo">100</param> </generator> </id>
<id name="id" type="long" column="cat_id"> <generator class="seqhilo"> <param name="sequence">hi_value</param> <param name="max_lo">100</param> </generator> </id>
很不幸,你在为Hibernate自行提供Connection,或者Hibernate使用JTA获取应用服务器的数据源连接的时候无法使用hilo 。Hibernate必须能够在一个新的事务中得到一个"hi"值。在EJB环境中实现hi/lo算法的标准方法是使用一个无状态的session bean。
UUID包含:IP地址,JVM的启动时间(精确到1/4秒),系统时间和一个计数器值(在JVM中唯一)。在Java代码中不可能获得MAC地址或者内存地址,所以这已经是我们在不使用JNI的前提下的能做的最好实现了。
不要试图在PostgreSQL中使用uuid.string。
对于内部支持标识字段的数据库(DB2,MySQL,Sybase,MS SQL),你可以使用identity关键字生成。对于内部支持序列的数据库(DB2,Oracle, PostgreSQL, Interbase, McKoi,SAP DB),你可以使用sequence风格的关键字生成。这两种方式对于插入一个新的对象都需要两次SQL查询。
<id name="id" type="long" column="uid"> <generator class="sequence"> <param name="sequence">uid_sequence</param> </generator> </id>
<id name="id" type="long" column="uid" unsaved-value="0"> <generator class="identity"/> </id>
对于跨平台开发,native策略会从identity, sequence 和hilo中进行选择,取决于底层数据库的支持能力。
<composite-id name="propertyName" class="ClassName" unsaved-value="any|none" access="field|property|ClassName"> <key-property name="propertyName" type="typename" column="column_name"/> <key-many-to-one name="propertyName class="ClassName" column="column_name"/> ...... </composite-id>
如果表使用联合主键,你可以把类的多个属性组合成为标识符属性。<composite-id>元素接受<key-property>属性映射和<key-many-to-one>属性映射作为子元素。
<composite-id> <key-property name="medicareNumber"/> <key-property name="dependent"/> </composite-id>
你的持久化类必须重载equals()和hashCode()方法,来实现组合的标识符判断等价.也必须实现Serializable接口。
不幸的是,这种组合关键字的方法意味着一个持久化类是它自己的标识。除了对象自己之外,没有什么方便的“把手”可用。你必须自己初始化持久化类的实例,在使用组合关键字load()持久化状态之前,必须填充他的联合属性。我们会在第 7.4 节 “组件作为联合标识符(Components as composite identifiers)”章中说明一种更加方便的方法,把联合标识实现为一个独立的类,下面描述的属性只对这种备用方法有效:
-
name (可选):一个组件类型,持有联合标识(参见下一节)。
-
class (可选 - 默认为通过反射(reflection)得到的属性类型) : 作为联合标识的组件类名(参见下一节)。
-
unsaved-value (可选 - 默认为 none): 假如被设置为非none的值,就表示新创建,尚未被持久化的实例将持有的值。
在"一棵对象继承树对应一个表"的策略中,<discriminator>元素是必需的,它声明了表的识别器字段。识别器字段包含标志值,用于告知持久化层应该为某个特定的行创建哪一个子类的实例。只能使用如下受到限制的一些类型: string, character, integer, byte, short, boolean, yes_no, true_false.
<discriminator column="discriminator_column" (1) type="discriminator_type" (2) force="true|false" (3) />
(1) |
column (可选 - 默认为 class) 识别器字段的名字 |
(2) |
type (可选 - 默认为 string) 一个Hibernate字段类型的名字 |
(3) |
force(强制) (可选 - 默认为 false) "强制"Hibernate指定允许的识别器值,就算取得的所有实例都是根类的。 |
标识器字段的实际值是根据<class> 和<subclass>元素的discriminator-value得来的.
force属性仅仅是在表包含一些未指定应该映射到哪个持久化类的时候才是有用的。这种情况不是经常会遇到。
<version>元素是可选的,表明表中包含附带版本信息的数据。这在你准备使用 长事务(long transactions)的时候特别有用。(见后)
<version column="version_column" (1) name="propertyName" (2) type="typename" (3) access="field|property|ClassName" (4) unsaved-value="null|negative|undefined" (5) />
(1) |
column (可选 - 默认为属性名): 指定持有版本号的字段名。 |
(2) |
name: 持久化类的属性名。 |
(3) |
type (可选 - 默认是 integer): 版本号的类型。 |
(4) |
access (可选 - 默认是 property): Hibernate用于访问属性值的策略。 |
(5) |
unsaved-value (可选 - 默认是undefined): 用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况和已经在先前的session中保存或装载的实例区分开来。(undefined指明使用标识属性值进行这种判断。) |
版本号必须是以下类型:long, integer, short, timestamp或者calendar。
可选的<timestamp>元素指明了表中包含时间戳数据。这用来作为版本的替代。时间戳本质上是一种对乐观锁定的一种不是特别安全的实现。当然,有时候应用程序可能在其他方面使用时间戳。
<timestamp column="timestamp_column" (1) name="propertyName" (2) access="field|property|ClassName" (3) unsaved-value="null|undefined" (4) />
(1) |
column (可选 - 默认为属性名): 持有时间戳的字段名。 |
(2) |
name: 在持久化类中的JavaBeans风格的属性名,其Java类型是 Date 或者 Timestamp的。 |
(3) |
access (可选 - 默认是 property): Hibernate用于访问属性值的策略。 |
(4) |
unsaved-value (可选 - 默认是null): 用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况和已经在先前的session中保存或装载的实例区分开来。(undefined指明使用标识属性值进行这种判断。) |
注意,<timestamp> 和<version type="timestamp">是等价的。
<property>元素为类声明了一个持久化的,JavaBean风格的属性。
<property name="propertyName" (1) column="column_name" (2) type="typename" (3) update="true|false" (4) insert="true|false" (4) formula="arbitrary SQL expression" (5) access="field|property|ClassName" (6) />
(1) |
name: 属性的名字,以小写字母开头。 |
(2) |
column (可选 - 默认为属性名字): 对应的数据库字段名。 |
(3) |
type (可选): 一个Hibernate类型的名字。 |
(4) |
update, insert (可选 - 默认为 true) :表明在用于UPDATE 和/或 INSERT的SQL语句中是否包含这个字段。这二者如果都设置为false则表明这是一个“外源性(derived)”的属性,它的值来源于映射到同一个(或多个)字段的某些其他属性,或者通过一个trigger(触发器),或者其他程序。 |
(5) |
formula (可选): 一个SQL表达式,定义了这个计算(computed) 属性的值。计算属性没有和它对应的数据库字段。 |
(6) |
access (可选 - 默认值为 property): Hibernate用来访问属性值的策略。 |
typename可以是如下几种:
-
Hibernate基础类型之一(比如:integer, string, character,date, timestamp, float, binary, serializable, object, blob)。
-
一个Java类的名字,这个类属于一种默认基础类型 (比如: int, float,char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob)。
-
一个PersistentEnum的子类的名字。(比如:. eg.Color)。
-
一个可以序列化的Java类的名字。
-
一个自定义类型的类的名字。(比如: com.illflow.type.MyCustomType)。
如果你没有指定类型,Hibernarte会使用反射来得到这个名字的属性,以此来猜测正确的Hibernate类型。Hibernate会对属性读取器(getter方法)的返回类进行解释,按照规则2,3,4的顺序。然而,这并不足够。 在某些情况下你仍然需要type属性。(比如,为了区别Hibernate.DATE和Hibernate.TIMESTAMP,或者为了指定一个自定义类型。)
access属性用来让你控制Hibernate如何在运行时访问属性。在默认情况下,Hibernate会使用属性的get/set方法对。如果你指明access="field",Hibernate会忽略get/set方法对,直接使用反射来访问成员变量。你也可以指定你自己的策略,这就需要你自己实现net.sf.hibernate.property.PropertyAccessor接口,再在access中设置你自定义策略类的名字。
通过many-to-one元素,可以定义一种常见的与另一个持久化类的关联。这种关系模型是多对一关联。(实际上是一个对象引用。)
<many-to-one name="propertyName" (1) column="column_name" (2) class="ClassName" (3) cascade="all|none|save-update|delete" (4) outer-join="true|false|auto" (5) update="true|false" (6) insert="true|false" (6) property-ref="propertyNameFromAssociatedClass" (7) access="field|property|ClassName" (8) />
(1) |
name: 属性名。 |
(2) |
column (可选): 字段名。 |
(3) |
class (可选 - 默认是通过反射得到属性类型): 关联的类的名字。 |
(4) |
cascade(级联) (可选): 指明哪些操作会从父对象级联到关联的对象。 |
(5) |
outer-join(外连接) (可选 - 默认为 自动): 当设置hibernate.use_outer_join的时候,对这个关联允许外连接抓取。 |
(6) |
update, insert (可选 - defaults to true) 指定对应的字段是否在用于UPDATE 和/或 INSERT的SQL语句中包含。如果二者都是false,则这是一个纯粹的“外源性(derived)”关联,它的值是通过映射到同一个(或多个)字段的某些其他属性得到的,或者通过trigger(除法器),或者是其他程序。 |
(7) |
property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。 |
(8) |
access (可选 - 默认是 property): Hibernate用来访问属性的策略。 |
cascade 属性允许下列值: all, save-update, delete, none。设置除了none以外的其它值会传播特定的操作到关联的(子)对象中。参见后面的“Lifecycle Objects(自动管理生命周期的对象)”。
outer-join参数允许下列三个不同值:
-
auto (默认) 使用外连接抓取关联(对象),如果被关联的对象没有代理(proxy)
-
true 一直使用外连接来抓取关联
-
false 永远不使用外连接来抓取关联
一个典型的简单many-to-one声明例子:
<many-to-one name="product" class="Product" column="PRODUCT_ID"/>
property-ref属性只应该用来对付老旧的数据库系统,可能出现外键指向对方关联表的是个非主键字段(但是应该是一个惟一关键字)的情况。这是一种十分丑陋的关系模型。比如说,假设Product类有一个惟一的序列号,它并不是主键。(unique属性控制Hibernate通过SchemaExport工具生成DDL的过程。)
<property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>
那么关于OrderItem 的映射可能是:
<many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>
当然,我们决不鼓励这种用法。
持久化对象之间一对一的关联关系是通过one-to-one元素定义的。
<one-to-one name="propertyName" (1) class="ClassName" (2) cascade="all|none|save-update|delete" (3) constrained="true|false" (4) outer-join="true|false|auto" (5) property-ref="propertyNameFromAssociatedClass" (6) access="field|property|ClassName" (7) />
(1) |
name: 属性的名字。 |
(2) |
class (可选 - 默认是通过反射得到的属性类型):被关联的类的名字。 |
(3) |
cascade(级联) (可选) 表明操作是否从父对象级联到被关联的对象。 |
(4) |
constrained(约束) (可选) 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。这个选项影响save()和delete()在级联执行时的先后顺序(也在schema export tool中被使用)。 |
(5) |
outer-join(外连接) (可选 - 默认为 自动): 当设置hibernate.use_outer_join的时候,对这个关联允许外连接抓取。 |
(6) |
property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。 |
(7) |
access (可选 - 默认是 property): Hibernate用来访问属性的策略。 |
有两种不同的一对一关联:
-
主键关联
-
惟一外键关联
主键关联不需要额外的表字段;两行是通过这种一对一关系相关联的,那么这两行就共享同样的主关键字值。所以如果你希望两个对象通过主键一对一关联,你必须确认它们被赋予同样的标识值!
比如说,对下面的Employee和Person进行主键一对一关联:
<one-to-one name="person" class="Person"/>
<one-to-one name="employee" class="Employee" constrained="true"/>
现在我们必须确保PERSON和EMPLOYEE中相关的字段是相等的。我们使用一个特别的称为foreign的Hibernate标识符生成器策略:
<class name="person" table="PERSON"> <id name="id" column="PERSON_ID"> <generator class="foreign"> <param name="property">employee</param> </generator> </id> ... <one-to-one name="employee" class="Employee" constrained="true"/> </class>
一个刚刚保存的Person实例被赋予和该Person的employee属性所指向的Employee实例同样的关键字值。
另一种方式是一个外键和一个惟一关键字对应,上面的Employee和Person的例子,如果使这种关联方式,应该表达成:
<many-to-one name="person" class="Person" column="PERSON_ID" unique="true"/>
如果在Person的映射加入下面几句,这种关联就是双向的:
<one-to-one name"employee" class="Employee" property-ref="person"/>
<component>元素把子对象的一些元素与父类对应的表的一些字段映射起来。 然后组件可以声明它们自己的属性、组件或者集合。参见后面的“Components”一章。
<component name="propertyName" (1) class="className" (2) insert="true|false" (3) upate="true|false" (4) access="field|property|ClassName"> (5) <property ...../> <many-to-one .... /> ........ </component>
(1) |
name: 属性名 |
(2) |
class (可选 - 默认为通过反射得到的属性类型):组件(子)类的名字。 |
(3) |
insert: 被映射的字段是否出现在SQL的INSERT语句中? |
(4) |
update: 被映射的字段是否出现在SQL的UPDATE语句中? |
(5) |
access (可选 - 默认是 property): Hibernate用来访问属性的策略。 |
其<property>子标签为子类的一些属性和表字段建立映射。
<component>元素允许加入一个<parent>子元素,在组件类内部就可以有一个指向其容器的实体的反向引用。
<dynamic-component>元素允许把一个Map映射为组件,其属性名对应map的键值。
最后,多态持久化需要为父类的每个子类都进行声明。对于我们建议的“每一棵类继承树对应一个表”的策略来说,就需要使用<subclass>声明。
<subclass name="ClassName" (1) discriminator-value="discriminator_value" (2) proxy="ProxyInterface" (3) lazy="true|false" (4) dynamic-update="true|false" dynamic-insert="true|false"> <property .... /> ..... </subclass>
(1) |
name: 子类的全限定名。 |
(2) |
discriminator-value(辨别标志) (可选 - 默认为类名):一个用于区分每个独立的子类的值。 |
(3) |
proxy(代理) (可选): 指定一个类或者接口,在延迟装载时作为代理使用。 |
(4) |
lazy(延迟装载) (可选): 设置lazy="true"是把自己的名字作为proxy接口的一种等价快捷方式。 |
每个子类都应该声明它自己的持久化属性和子类。 <version> 和<id> 属性可以从根父类继承下来。在一棵继承树上的每个子类都必须声明一个唯一的discriminator-value。如果没有指定,就会使用Java类的全限定名。
另外一种情况,如果子类是持久化到一个属于它自己的表(每一个子类对应一个表的映射策略),那么就需要使用<joined-subclass>元素。
<joined-subclass name="ClassName" (1) proxy="ProxyInterface" (2) lazy="true|false" (3) dynamic-update="true|false" dynamic-insert="true|false"> <key .... > <property .... /> ..... </joined-subclass>
(1) |
name: 子类的全限定名。 |
(2) |
proxy (可选): 指定一个类或者接口,在延迟装载时作为代理使用。 |
(3) |
lazy(延迟装载) (可选): 设置lazy="true"是把自己的名字作为proxy接口的一种等价快捷方式。 |
这种映射策略不需要指定辨别标志(discriminator)字段。但是,每一个都必须使用<key>元素指定一个表字段包含对象的标识符。本章开始的映射可以被用如下方式重写:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping package="eg"> <class name="Cat" table="CATS"> <id name="id" column="uid" type="long"> <generator class="hilo"/> </id> <property name="birthdate" type="date"/> <property name="color" not-null="true"/> <property name="sex" not-null="true"/> <property name="weight"/> <many-to-one name="mate"/> <set name="kittens"> <key column="MOTHER"/> <one-to-many class="Cat"/> </set> <joined-subclass name="DomesticCat" table="DOMESTIC_CATS"> <key column="CAT"/> <property name="name" type="string"/> </joined-subclass> </class> <class name="eg.Dog"> <!-- mapping for Dog could go here --> </class> </hibernate-mapping>
假设你的应用程序有两个同样名字的持久化类,但是你不想在Hibernate查询中使用他们的全限定名。除了依赖auto-import="true"以外,类也可以被显式地“import(引用)”。你甚至可以引用没有明确被映射的类和接口。
<import class="java.lang.Object" rename="Universe"/>
<import class="ClassName" (1) rename="ShortName" (2) />
(1) |
class: 任何Java类的全限定名。 |
(2) |
rename (可选 - 默认为类的全限定名): 在查询语句中可以使用的名字。 |
为了理解很多与持久化服务相关的Java语言级对象的行为,我们需要把它们分为两类:
实体entity 独立于任何持有实体引用的对象。与通常的Java模型相比,不再被引用的对象会被当作垃圾收集掉。实体必须被显式的保存和删除(除非保存和删除是从父实体向子实体引发的级联)。这和ODMG模型中关于对象通过可触及保持持久性有一些不同——比较起来更加接近应用程序对象通常在一个大系统中的使用方法。实体支持循环引用和交叉引用,它们也可以加上版本信息。
实体的持久化状态包含有指向其他实体的连接和一些值 类型的实例。值是原始类型、集合、组件或者特定的不可变对象。与实体不同,值(特别是集合和组件)是通过可触及性来进行持久化和删除的。因为值对象(和原始类型数据)是随着包含它们的实体而被持久化和删除的,它们不能够被独立的加上版本信息。值没有独立的标识,所以它们不能被两个实体或者集合共享。
所有的Hibernate对象,除了集合,都支持null语义。
直到现在,我们都一直使用"持久化对象"来代表实体。我们仍然会这么做。然而严格的来说,并不是所有用户定义的,带有持久化状态的类都是实体。组件(component)就是一个用户定义的类,仅仅由值语义构成。
发表评论
-
自定义用户类(UserType)的使用
2011-08-04 10:46 1882学习hibernate有段时间了,最近复习这门技术时看到了自定 ... -
技巧:利于ThreadLocal模式管理Session
2011-08-02 10:31 1271在利用Hibernate开发DAO模块时,我们和Session ... -
Hibernate中的回调与拦截机制
2011-07-27 17:31 1466在某些情况下,我们需要对实体的CURD操作进行捕获并执行一些操 ... -
HibernateTemplate中HibernateCallback的事务
2011-07-04 14:41 1455目的:使用HibernateTemplate执行execute ... -
Hibernate的复杂用法HibernateCallback
2011-07-04 14:40 1346HibernateTemplate还提供一种更加灵活的方式来操 ... -
Hibernate session FlushMode有五种属性
2011-07-04 13:59 17381、NEVER:已经废弃了,被MANUAL取代了2 MANUA ... -
数据库持久层——浅谈hibernate中的Session
2011-07-01 22:49 1680大多数情况下,Session 管理的目标聚焦于通过合理的设 ... -
详解Hibernate Session
2011-07-01 22:42 1503这里介绍Hibernate Session,Ses ... -
HttpSession与Hibernate中Session的区别
2011-07-01 22:41 1305一、javax.servlet.http.HttpSess ... -
巧用SQLQuery中的addScalar
2011-06-02 17:16 5756当我们用HQL进行子查询的时候,如select * from ... -
hibernate中SQLQuery的addEntity();方法
2011-04-13 14:48 2898如果使用原生sql语句进行query查询时,hibernate ... -
Hibernate的clear(),flush(),evict()方法详解
2011-03-24 11:18 17781.Clear 方法 无论是Load 还是 G ... -
hibernate模糊查询-Restrictions.ilike & Expression.like
2011-03-11 10:32 16369Criteria criteria = session.c ... -
Hibernate分页查询小结
2011-03-10 11:14 1834通常使用的Hibernate通常是三种:hql查询,QBC查询 ... -
current_session_context_class
2011-03-07 15:31 1300此设置的作用如下: What does sessionFac ... -
Hibernate的拦截器和监听器
2010-12-14 15:06 1393核心提示:最近项目需要,用到了Hibernate的拦截器和 ... -
孙卫琴.精通Hibernate:Java对象持久化技术详解_触发器使缓存与数据库不一致
2010-12-14 08:46 1405p198 -
孙卫琴.精通Hibernate:Java对象持久化技术详解_优化报表查询的性能
2010-12-13 17:51 1282p332 -
孙卫琴.精通Hibernate:Java对象持久化技术详解_查询结果类型
2010-12-13 17:34 1310p329 -
孙卫琴.精通Hibernate:Java对象持久化技术详解_投影查询
2010-12-13 17:31 1431p325
相关推荐
2. **O/R Mapping**:对象关系映射,是ORM的核心概念。它通过定义规则将数据库表映射为类,表中的字段映射为类的属性,从而实现对象与数据库记录的对应。这样,开发者可以直接操作对象,而无需关心底层SQL语句的编写...
一、O/R Mapping简介与优点 1. O/R Mapping(对象关系映射)是为了解决面向对象编程与关系型数据库之间的差异,通过在对象和关系表之间建立关联,使得开发者可以以面向对象的方式处理数据,降低了数据库操作的复杂性...
Hibernate的底层实现是基于O/R Mapping(对象关系映射)的原理。O/R Mapping是将Java对象映射到关系型数据库表的中间层。它的目的是简化Java开发者对数据库的操作,让开发者以面向对象的方式进行数据库编程,而非...
【HIBERNATE入门】是针对Java开发者的培训资料,主要介绍了如何入门并掌握Hibernate这一流行的O/R Mapping框架。Hibernate是一种用于简化Java应用程序与数据库交互的开源库,它通过对象关系映射(O/R Mapping)技术...
【一、O/R Mapping】 O/R Mapping,即对象关系映射,是将对象模型与关系数据库之间进行映射的技术。在Hibernate中,O/R Mapping允许开发者以面向对象的方式来操作数据库,而无需关心底层的SQL语句。这极大地提高了...
总结,这份hibernate培训ppt提供了一个基础的Hibernate学习框架,帮助开发者理解O/R Mapping的核心概念,并学会如何利用Hibernate进行实际的数据库操作。虽然可能在深度上有所欠缺,但对于初学者而言,它是一个良好...
AutoJava根据O/R Mapping规则生成表对应的Java对象,并且生成了所有的添加、删除、修改、查询等底层数据库操作代码。借助于AutoJava我们基本上不用再写与数据库相关的操作代码,只需要在此基础上实现相关的业务逻辑...
【Hibernate快速学习PPT】是针对Java开发人员的一份教程资料,主要讲解了对象关系映射(Object/Relationship Mapping,简称O/R Mapping)框架Hibernate的核心概念和应用。这份PPT由加拿大嘉木华公司(JetGuo)提供,...
《Hibernate培训》是针对Java开发者的教程,旨在深入理解对象关系映射(O/R Mapping)原理,特别是通过Hibernate框架实现这一映射。本教程适合熟悉Java、SQL和JDBC,有面向对象开发经验的学员。课程的目标是使学员...
1. **O/R Mapping**:Object-Relational Mapping,对象关系映射,是将数据库中的关系数据模型映射到面向对象的编程语言中的一种技术。通过O/R Mapping,开发者可以避免直接编写SQL语句,而是以对象的形式处理数据,...
SQL2JAVA作为一个O/R Mapping(对象关系映射)工具,旨在简化数据库与Java应用程序之间的交互,使得开发者能够更专注于业务逻辑而不是繁琐的SQL代码。本文将详细介绍SQL2JAVA及其工作原理,以及如何利用它来提高开发...
Hibernate是一种强大的Object-Relational Mapping(O/R Mapping)工具,它允许开发者将Java对象与关系数据库中的表进行映射,从而简化数据库操作。 **一、持久化层—O/R Mapping** 在基于B/S的三层架构中,业务...
Hibernate是一个开源的Java库,实现了对象-关系映射(O/R Mapping)机制,允许开发者用面向对象的方式来操作数据库,降低了Java应用程序和关系数据库之间的耦合度。它的主要功能包括: 1. **对象关系映射**:...
综上所述,"汤阳光Hibernate3.6(基础).doc"文档详细讲解了Hibernate 3.6的基础知识,包括对象持久化的概念、分层架构的运用以及Hibernate在数据访问层中的实现方式,是学习Hibernate和O/R Mapping的宝贵资源。...
Hibernate 是一个流行的开源 Object-Relational Mapping (O/R Mapping)框架,它在Java Web开发中广泛应用于数据访问层,极大地简化了数据库操作。O/R Mapping 是一种技术,旨在消除对象世界和关系数据库之间的差异,...
1. **O/R Mapping基础** O/R Mapping是将对象模型与关系数据模型进行映射的技术,它允许程序员以面向对象的方式处理数据库。Hibernate通过XML或注解方式定义映射规则,实现了对象与数据库表之间的透明交互。 2. **...
本培训材料主要针对Hibernate这一流行的Java对象关系映射(ORM)框架,旨在帮助已经熟悉Java、SQL和JDBC的开发者深入理解O/R Mapping原理,掌握Hibernate的使用,以便在实际项目开发中有效地利用Hibernate进行持久化...
ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案,早期被称为 ObjectSpace,现已经包含在 Visual Studio 2008 Service Pack 1 以及 .NET Framework 3.5 Service ...