NHibernate官⽅⽂档中⽂版--基础ORM(BasicORMapping)
映射声明
对象/关系映射在XML⽂件中配置。mapping⽂件这样设计是为了使它可读性强并且可修改。mapping语⾔是以对象为中⼼,意味着mapping是围绕着持久化类声明来建⽴的,⽽不是围绕数据表。
要注意的是,尽管很多NHibernate使⽤者选择⼿动定义XML⽂件,但是仍然有很多⼯具可以⽤来⽣成mapping⽂件,包括NHibernate.Mapping.Attributes 库和各种各样基于模板的代码⽣成⼯具(CodeSmith, MyGeneration)。
让我们⽤⼀个mapping的例⼦作为开始:
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Eg"
namespace="Eg">
<class name="Cat" table="CATS" discriminator-value="C">
<id name="Id" column="uid" type="Int64">
<generator class="hilo"/>
</id>
<discriminator column="subclass" type="Char"/>
<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"/>mysql操作官方文档
<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>
我们现在讨论mapping⽂件中的内容。我们将只会描述NHibernate在运⾏时使⽤的⽂档中的标签和特
性。mapping⽂件也包含⼀些额外的可选的特性和标签,这些特性和标签会影响表结构导出⼯具(schema export tool)导出的数据库的表结构(database schemas)。(例如not-null特性)。
XML名称空间
所有的XMLmapping应该声明XML名称空间。规定的XML结构定义(schema definition)可以在NHibernate发⾏版中的src\nhibernate-mapping.xsd中到。
⼩建议:想要启⽤mapping和配置⽂件的智能感知功能,需要将相应的.xsd⽂件作为你解决⽅案中所有项⽬的⼀部分(⽣成操作可以是‘none’)或者作为“solution files”,或者放在你的“lib”⽂件夹中,然后将它添加到你的XML⽂件的schemas属性中。你可以在<VS installation directory>\Xml\Schemas中复制它,要注意你可能得将不同版本的xsd对应不同版本的NHibernate。
hibernate-mapping
这个标签有很多可选的特性。schema特性定义了对应表的数据库表空间。如果指定了相应的表空间,那么数据表名称就会被限定在给定的表空间。如果这个置空,就不会限定表空间。default-cascade 特性定义了没有详细指定级联⽅式的属性和集合的级联⽅式。默认情况下,auto-import 特性让我们在查询语句中使⽤不限定表空间的类名。assembly 和namespace特性定义了持久化类位于哪个程序集中,在哪个名称空间中声明。
<hibernate-mapping                        (1)
schema="schemaName"                          (2)
default-cascade="none|save-update"          (3)
auto-import="true|false"                    (4)
assembly="Eg"                                (5)
namespace="Eg"                              (6)
default-access="field|property|field.camecase(7)..."
default-lazy="true|false"
/>
(1) schema (可选): 数据库表空间的名称。
(2) default-cascade (可选 - 默认none):  默认的级联⽅式。
(3) auto-import (可选 - 默认true):  定义是否可以在查询语句中使⽤⾮限定表空间的类名(在mapping⽂件中定义的类)。
(4)(5) assembly and namespace(可选):  指定⾮限定表空间的类所在的程序集和名称空间。
(6) default-access (可选- 默认 property): NHibernate获得属性值的⽅式
(7) default-lazy (可选- 默认true):如果设置成false,懒加载就会被禁⽤
如果你不使⽤assembly和namespace特性,你就得使⽤完整的类名,包括程序集和名称空间的名称。
如果你有两个持久化类使⽤了相同的(未限定表空间的)名字,你应该将auto-import设置成false。如果你试图将两个类设置成相同的名称,那么NHibernate会抛出异常。
你可以使⽤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)
abstract="true|false"                        (16)
/>
(1) name: 持久化类(或者接⼝)的全限定名。
(2) table(optional - 默认是⾮限定的类名): 对应的数据库表名。
(3) discriminator-value (optional - 默认是类名):  ⼀个⽤于区分不同的⼦类的值,在多态⾏为时使⽤。可以设置为null和not null。
(4) mutable (optional, 默认是true): 指定该类的实例可变(不可变)。
(5) schema (optional): 覆盖在根<hibernate-mapping> 标签中指定的表空间名字
(6) proxy (optional): Specifies an interface to use for lazy initializing proxies. You may specify the name of the class itself. 指定⼀个接⼝,在延迟装载时作为代理使⽤。你可以在这⾥使⽤该类⾃⼰的名字。
(7) dynamic-update (optional, defaults to false): 指定⽤于UPDATE 的SQL将会在运⾏时动态⽣成,并且只更新那些改变过的字段。
(8) dynamic-insert (optional, defaults to false): 指定⽤于INSERT的SQL将会在运⾏时动态⽣成,并且只包含那些⾮空字段。
(9) select-before-update (optional, defaults to false): 指定NHibernate是否需要执⾏UPDATE操作,除⾮它确定对象真的被修改了,不然就不会执⾏。在⼀些特定的情况下(实际上仅仅当瞬时态对象要执⾏update()⽽被关联到⼀个新的session的时候),这意味着NHibernate在执⾏UPDATE之前会执⾏⼀个额外的SELECT的SQL语句操作来判断是不是真的需要进⾏UPDATE。
(10) polymorphism (optional, defaults to implicit):  指定是隐式还是显式的使⽤查询多态。
(11) where (optional)  指定⼀个附加的SQL WHERE 条件,在抓取这个类的对象时会⼀直增加这个条件。
(12) persister (optional):  指定⼀个⾃定义的IClassPersister.
(13) batch-size (optional, defaults to 1) 指定通过主键获得实体⽅式的批量插⼊量
(14) optimistic-lock (optional, defaults to version): 指定乐观锁策略。
(15) lazy (optional): 如果设置成lazy="false"懒加载会被完全关闭。
(16) abstract (optional):  ⽤来在<union-subclass>继承中标记抽象⽗类
若指明的持久化类实际上是⼀个接⼝,也可以被完美地接受。其后你可以⽤ <subclass> 来指定该接⼝的实际实现类名。你可以持久化任何static(静态的)内部类。记得应该使⽤标准的类名格式,就是说⽐如:Eg.Foo+Bar 。这是因为HQL解析器的限制,在NHibernate 1.0版本中,在查询中不能使⽤内部类。
任何对不可变类的修改操作,mutable="false",都不会被持久化。这可以让NHibernate做⼀些⼩⼩的性能优化。
可选的proxy属性可以允许延迟加载类的持久化实例。NHibernate开始会返回实现了这个接⼝的代理。当代理的某个⽅法被实际调⽤的时候,真正的持久化对象才会被加载。参见下⾯的“⽤于延迟加载的代理”。
Implicit (隐式)的多态是指,如果查询中给出的是任何⽗类、该类实现的接⼝或者该类的名字,都会返回这个类的实例;如果查询中给出的是该类⼦类的名字,则会返回该类的实例。Explicit (显式)的多态是指,只有在查询中给出的明确是该类的名字时才会返回这个类的实例;对于该类的查询也只会返回在 <class> 的定义中作为 <subclass> 或者
<joined-subclass> 出现的⼦类。⼤多数情况下,默认的polymorphism="implicit"都是合适的。显式的多态在有两个不同的类映射到同⼀个表的时候很有⽤。(这就允许⼀个只包含部分表字段的“轻型”类)。
persister属性可以让你⾃定义这个类使⽤的持久化策略。你可以指定你⾃⼰实现的NHibernate.Persister.EntityPersister的⼦类,你甚⾄可以完全从头开始编写⼀个NHibernate.Persister.IClassPersister接⼝的实现,可能是通过调⽤储存过程、将数据序列化到⽂件或者LDAP数据库来实现。参阅NHibernate.DomainModel.CustomPersister,这是⼀个简单的例⼦(“持久化”到⼀个Hashtable)。
请注意dynamic-update和dynamic-insert的设置并不会继承到⼦类,所以在<subclass>或者<joined-subclass>元素中可能需要再次设置。这些设置是否能够提⾼效率要视情形⽽定。请⽤你的智慧决定是否使⽤。
使⽤select-before-update通常会降低性能。但是这种⽅式能够有效地防⽌不必要的数据库更新。
如果你使⽤了select-before-update,你就可以选择⼀种乐观锁的策略:
version检查version/timestamp ⾏
all检查所有⾏
dirty检查改变的⾏
none不使⽤乐观锁
我们强烈建议你使⽤NHibernate的乐观锁功能的时候使⽤version/timestamp 。考虑到性能问题,这个是最佳并且唯⼀的⽅案来正确地处理在session(例如,当使⽤ISession.Update() )之外的修改操作。要记住,version或者timestamp属性永远不能为null,⽆论是哪种unsaved-value ⽅案,或者实体将要变成游离态。
从NHibernate 1.2.0开始,version的是从1开始,⽽不是像之前的版本那样从0开始。这个⽬的是为了让unsaved-value将version设置成0。
⼦查询
⼀个其他的映射类的⽅式是映射⼀个查询。为了达到这个⽬的,我们可以使⽤<subselect>标签,这个标签是独⽴于<class>, <subclass>, <joined-subclass> 和 <union-subclass>的。subselect标签中的内容是⼀个SQL查询:
<subselect>
SELECT cat.ID, cat.NAME, cat.SEX, cat.MATE FROM cat
</subselect>
⼀般来说,当使⽤subselect来mapping⼀个查询的时候,你会将类标记成不变的(mutable="false"),除⾮你使⽤了⾃定义的SQL来完成增删改操作。
其次,强制同步受到查询影响的数据表是有意义的,可以使⽤⼀个或者多个<synchronize> :
<subselect>
SELECT cat.ID, cat.NAME, cat.SEX, cat.MATE FROM cat
</subselect>
<syncronize table="cat"/>
Id
被映射的类必须声明对应数据库表主键字段。⼤多数类有⼀个属性,为每⼀个实例包含唯⼀的标识。 <id> 标签定义了该属性到数据库表主键字段的映射。
<id
name="PropertyName"                      (1)
type="typename"                          (2)
column="column_name"                    (3)
unsaved-value="any|none|null|id_value"  (4)
access="field|property|nosetter|ClassName(5)">
<generator class="generatorClass"/>
</id>
(1)name (可选): 标识属性的名字。
(2)type (可选):标识NHibernate类型的名字
(3)column (可选- 默认是这个属性的名称):主键字段的名字
(4)unsaved-value (可选- 默认是 "sensible" ): ⼀个特定的标识属性值,⽤来标志该实例是刚刚实例化的(还未保存),以此将这个实例与在之前session中保存或者加载过的瞬时态的实例区分开来。
(5)access (可选- 默认值是property): NHibernate⽤来访问属性值的策略
如果name属性不存在,会认为这个类没有标识属性。
unsaved-value属性在NHibernate 1.0中基本不需要。
还有⼀个另外的<composite-id>声明可以访问旧式的多主键数据。我们强烈不⿎励使⽤这种⽅式。
Id⽣成器
必须要有⼀个⽣成器,⽤来为该持久化类的实例⽣成唯⼀的标识。
这个⽣成器可以使⽤<generator>⼦标签来声明。如果这个⽣成器实例需要某些配置值或者初始化参数,⽤ <param>元素来传递。
<id name="Id" type="Int64" column="uid" unsaved-value="0">
<generator class="NHibernate.Id.TableHiLoGenerator">
<param name="table">uid_table</param>
<param name="column">next_hi_value_column</param>
</generator>
</id>
如果没有指定参数,就可以直接在<id> 标签中使⽤⼀个generator 特性来声明⼀个⽣成器,就像下⾯的这样:
<id name="Id" type="Int64" column="uid" unsaved-value="0" generator="native" />
所有的⽣成器实现NHibernate.Id.IIdentifierGenerator接⼝。这是⼀个⾮常简单的接⼝;某些应⽤程序
可以选择提供他们⾃⼰特定的实现。当然,NHibernate提供了很多内置的实现。下⾯是⼀些内置⽣成器的快捷名字:
increment
仅在没有其他进程往同⼀张数据表中插⼊数据的时候⽣成独⼀⽆⼆的整型标识符。不要在⼀个集中使⽤这种⽣成⽅式。
identity
对DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的内置标识字段提供⽀持。返回的标识符是 Int64, Int32 或者 Int16类型的。
sequence
对DB2,MySQL, PostgreSQL, Oracle的内置标识字段提供⽀持。返回的标识符是Int64 Int32  或者 Int16类型的。
hilo
使⽤⼀个⾼/低位算法来⾼效的⽣成Int64, Int32 或者 Int16类型的标识符。给定⼀个表和字段(默认分别是hibernate_unique_key 和next)作为⾼位值得来源。⾼/低位算法⽣成的标识符只在⼀个特定的数据库中是唯⼀的。
seqhilo
使⽤⼀个⾼/低位算法来⾼效的⽣成Int64, Int32 或者 Int16类型的标识符,给定⼀个数据库序列(sequence)的名字。
uuid.hex
⽤⼀个System.Guid和它的ToString(string format)⽅法⽣成字符串类型的标识符。字符串的长度取决于 format的配置。
uuid.string
⽤⼀个新的System.Guid产⽣⼀个byte[] ,把它转换成字符串。
guid
⽤⼀个新的System.Guid 作为标识符。
guidb
native
根据底层数据库的能⼒选择 identity, sequence 或者 hilo中的⼀个。
assigned
让应⽤程序在save()之前为对象分配⼀个标⽰符。
foreign
使⽤另外⼀个相关联的对象的标识符。和<one-to-one>联合⼀起使⽤。
Hi/Lo算法
hilo 和 seqhilo⽣成器给出了两种hi/lo算法的实现,这是⼀种很令⼈满意的标识符⽣成算法。第⼀种实现需要⼀个“特殊”的数据库表来保存下⼀个可⽤的“hi”值。第⼆种实现使⽤⼀个Oracle风格的序列(在被⽀持的情况下)。
<id name="Id" type="Int64" 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="Int64" column="cat_id">
<generator class="seqhilo">
<param name="sequence">hi_value</param>
<param name="max_lo">100</param>
</generator>
</id>
很不幸,你在为NHibernate⾃⾏提供Connection时⽆法使⽤hilo 。Hibernate必须能够在⼀个新的事务中得到⼀个"hi"值。
UUID⼗六进制算法
<id name="Id" type="String" column="cat_id">
<generator class="uuid.hex">
<param name="format">format_value</param>
<param name="separator">separator_value</param>
</generator>
</id>
UUID是通过调⽤Guid.NewGuid().ToString(format)产⽣的。format值的设置请参考MSDN⽂档。默认的seperator很少也不应该被改变。format决定是否配置好的seperator 能替换format使⽤的默认sepera
tor。
UUID String Algorithm
UUID是通过调⽤ Guid.NewGuid().ToByteArray() 并且把 byte[]转换成char[],char[] 做为⼀个16个字符组成的字符串返回。
GUID Algorithms
guid 标识符通过调⽤Guid.NewGuid()产⽣。为了提升Guids在MS SQL中作为主键,外键和索引的⼀部分时的性能,可以使⽤guidb。在别的数据库中使⽤guidb的好处是⽀持⾮标准的GUID。
标识符字段和序列
对于内部⽀持标识字段的数据库(DB2,MySQL,Sybase,MS SQL),你可以使⽤identity关键字⽣成。对于内部⽀持序列的数据库(DB2,Oracle, PostgreSQL),你可以使⽤sequence 风格的关键字⽣成。这两种⽅式对于插⼊⼀个新的对象都需要两次SQL查询。
<id name="Id" type="Int64" column="uid">
<generator class="sequence">
<param name="sequence">uid_sequence</param>
</generator>
</id>
<id name="Id" type="Int64" column="uid" unsaved-value="0">
<generator class="identity"/>
</id>
对于跨平台开发,native策略会从identity, sequence 和hilo中进⾏选择,取决于底层数据库的⽀持能⼒。
由程序分配的标识符
如果你需要应⽤程序分配⼀个标⽰符(⽽⾮NHibernate来⽣成它们),你可以使⽤assigned⽣成器。这种特殊的⽣成器会使⽤已经分配给对象的标识符属性的标识符值。⽤这种特性来分配商业⾏为的关键字要特别⼩⼼(基本上总是⼀种可怕的设计决定)。
因为其继承天性,使⽤这种⽣成器策略的实体不能通过ISession的SaveOrUpdate()⽅法保存。作为替代,你应该明确告知NHibernate是应该被save还是update,分别调⽤ISession的Save()或Update()⽅法。
强化版标识符⽣成器
Starting with NHibernate release 3.3.0, there are 2 new generators which represent a re-thinking of 2 different aspects of identifier generation. The first aspect is database portability; the second is optimization Optimization means that you do not have to query the database for every request for a new identifier value. These two new generators are intended to take the place of some of the named generators described above, starting in However, they are included in the current releases and can be referenced by FQN.
The first of these new generators is NHibernate.Id.Enhanced.SequenceStyleGenerator (short name enhanced-sequence) which is intended, firstly, as a replacement for the sequence generator and, secondly, as a better portability generator than native. This is because native generally chooses between identity and sequence which have largely different semantics that can cause subtle issues in applications eyeing portability. NHibernate.Id.Enhanced.SequenceStyleGenerator, however, achie
ves portability in a different manner. It chooses between a table or a sequence in the database to store its incrementing values, depending on the capabilities of the dialect being used. The difference between this and native is that table-based and sequence-based storage have the same exact semantic. In fact, sequences are exactly what NHibernate tries to emulate with its table-based generators. This generator has a number of configuration parameters:
sequence_name (optional, defaults to hibernate_sequence): the name of the sequence or table to be used.
initial_value (optional, defaults to 1): the initial value to be retrieved from the sequence/table. In sequence creation terms, this is analogous to the clause typically named "STARTS WITH".
increment_size (optional - defaults to 1): the value by which subsequent calls to the sequence/table should differ. In sequence creation terms, this is analogous to the clause typically named "INCREMENT BY".
force_table_use (optional - defaults to false): should we force the use of a table as the backing structure even though the dialect might support sequence?
value_column (optional - defaults to next_val): only relevant for table structures, it is the name of the column on the table which is used to hold the value.
prefer_sequence_per_entity (optional - defaults to false): should we create separate sequence for each entity that share current generator based on its name?
sequence_per_entity_suffix (optional - defaults to _SEQ): suffix added to the name of a dedicated sequence.
optimizer (optional - defaults to none): See
The second of these new generators is NHibernate.Id.Enhanced.TableGenerator (short name enhanced-table), which is intended, firstly, as a replacement for the table generator, even though it actually functions much more like org.hibernate.id.MultipleHiLoPerTableGenerator (not available in NHibernate), and secondly, as a re-implementation of
org.hibernate.id.MultipleHiLoPerTableGenerator (not available in NHibernate) that utilizes the notion of pluggable optimizers. Essentially this generator defines a table capable of holding a number of different increment values simultaneously by using multiple distinctly keyed rows. This generator has a number of configuration parameters:
table_name (optional - defaults to hibernate_sequences): the name of the table to be used.
value_column_name (optional - defaults to next_val): the name of the column on the table that is used to hold the value.
segment_column_name (optional - defaults to sequence_name): the name of the column on the table that is used to hold the "segment key". This is the value which identifies which increment value to use.
segment_value (optional - defaults to default): The "segment key" value for the segment from which we want to pull increment values for this generator.
segment_value_length (optional - defaults to 255): Used for schema generation; the column size to create this segment key column.
initial_value (optional - defaults to 1): The initial value to be retrieved from the table.
increment_size (optional - defaults to 1): The value by which subsequent calls to the table should differ.
optimizer (optional - defaults to ??): See .
标识符⽣成器的优化
For identifier generators that store values in the database, it is inefficient for them to hit the database on each and every call to generate a new identifier value. Instead, you can group a bunch of them in memory and only hit the database when you have exhausted your in-memory value group. This is the role of the pluggable optimizers. Currently only the two enhanced generators ( support this operation.
none (generally this is the default if no optimizer was specified): this will not perform any optimizations and hit the database for each and every request.
hilo: applies a hi/lo algorithm around the database retrieved values. The values from the database for this optimizer are expected to be sequential. The values retrieved from the database structure for this optimizer indicates the "group number". The increment_size is multiplied by that value in memory to define a group "hi value".
pooled: as with the case of hilo, this optimizer attempts to minimize the number of hits to the database. Here, however, we simply store the starting value for the "next group" into the database structure rather than a sequential value in combination with an in-memory grouping algorithm. Here, i
ncrement_size refers to the values coming from the database.
pooled-lo: similar to pooled, except that it's the starting value of the "current group" that is stored into the database structure. Here, increment_size refers to the values coming from the database.
联合ID
<composite-id
name="PropertyName"
class="ClassName"
unsaved-value="any|none"
access="field|property|nosetter|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()持久化状态之前,必须填充他的联合属性。我们会在. 中说明⼀种更加⽅便的⽅法,把联合标识实现为⼀个独⽴的类,下⾯描述的属性只对这种备⽤⽅法有效:
name (可选): ⼀个组件类型,持有联合标识(参见下⼀节)。
access (可选 - 默认为 property): NHibernate⽤来获取属性值的⽅式。
class (可选 - 默认为通过反射(reflection)得到的属性类型): 作为联合标识的组件类名(参见下⼀节)。
识别器
在"⼀棵对象继承树对应⼀个表"的mapping策略中,<discriminator>元素是必需的,它声明了表的识别器字段。识别器字段包含标志值,⽤于告知持久化层应该为某个特定的⾏创建哪⼀个⼦类的实例。只能使⽤如下受到限制的⼀些类型:String, Char, Int32, Byte, Int16, Boolean, YesNo, TrueFalse.
<discriminator
column="discriminator_column"  (1)
type="discriminator_type"      (2)
force="true|false"            (3)
insert="true|false"            (4)
formula="arbitrary SQL expressi(5)on"
/>
(1)  column (可选 - 默认为 class) 识别器字段的名字
(2)  type (可选 - 默认为 String) ⼀个NHibernate字段类型的名字
(3)  force (可选 - 默认为 false) "强制"NHibernate指定允许的识别器值,就算取得的所有实例都是根类的。
(4)  insert (可选 - 默认为 true) 当识别器是被映射的组件的标识符的⼀部分时设置为false。
(5)  formula (可选) an arbitrary SQL expression that is executed when a type has to be evaluated. Allows content-based discrimination. 当⼀个类型需要被推断的时候执⾏的⼀个任意的SQL表达式。允许基于内容的识别。
标识器字段的实际值是根据<class> 和<subclass>元素的discriminator-value得来。
force 特性(仅仅)在表中包含额外的没有映射到持久化对象的识别字段的时候有⽤。这种情形并不常见。
通过使⽤formula 特性,你可以声明⼀个任意的SQL语句⽤来获得某⾏的类型:
<discriminator
formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"
type="Int32"/>
版本(可选)
<version>标签是可选的,表⽰这个数据表包含的数据是划分版本的。如果你想要使⽤长时间事务的时候⾮常有⽤(见下⽂)。
<version
column="version_column"                            (1)
name="PropertyName"                                (2)
type="typename"                                    (3)
access="field|property|nosetter|ClassName"        (4)
unsaved-value="null|negative|undefined|value"      (5)
generated="never|always"                          (6)
/>
(1)column (可选 - 默认为属性的名字): 储存版本数字的字段。
(2)name: 持久化类的版本属性名称。
(3)type (可选 - 默认为Int32): 版本数字的类型。
(4)access (可选 - 默认为property): NHibernate获得版本字段值的⽅法。
(5)unsaved-value (可选 - 默认为 "敏感的" 值): ⼀个版本属性值,表⽰⼀个实体是刚刚实例化的(未保存),将它和在之前的session中保存或者加载的持久化实例区分开来。(undefined说明了这个标识符属性值应该被使⽤)
(6)generated (optional - defaults to never): Specifies that this version property value is actually generated by the database. See the discussion of .说明了这个版本属性值是由数据库⽣成的。可以参见的讨论。
版本数字可以是Int64, Int32, Int16, Ticks, Timestamp, or TimeSpan(或者他们对应的可空值类型)类型。
时间戳(可选)
可选的<timestamp>标签表明这个数据表包含时间戳数据。时间戳可以是版本的⼀个替代品。时间戳是⼀种不太安全乐观锁的实现。然⽽,有些时候应⽤程序会⽤其他⽅式使⽤时间戳。
<timestamp
column="timestamp_column"          (1)
name="PropertyName"                (2)
access="field|property|nosetter|Clas(3)sName"
unsaved-value="null|undefined|value"(4)
generated="never|always"            (5)
/>
(1)column (可选 - 默认为属性的名称): 储存时间戳的字段。
(2)name: .NET的DateTime类型的属性字段名称。
(3)access (可选 - 默认为property): NHibernate获得时间戳字段值的⽅法。
(4)unsaved-value (可选 - 默认为null): ⼀个时间戳属性值,表⽰⼀个实体是刚刚实例化的(未保存),将它和在之前的session中保存或者加载的持久化实例区分开来。(undefined说明了这个标识符属性值应该被使⽤)
(5)generated (可选 - 默认为never): 说明了这个时间戳属性值是由数据库⽣成的。可以参见的讨论。
注意,<timestamp> 和<version type="timestamp">是相同的。
属性
The <property> element declares a persistent property of the class.
<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)
optimistic-lock="true|false"        (7)
generated="never|insert|always"    (8)
lazy="true|false"                  (9)
/>
(1)name: 类中的属性名称。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。