要定义定义持久对象的类请确保类的主类(第一个)父类是%persistent或其他某个持久类。例如:
对于持久类包在SQL中表示为SQL模式。例如如果一个类被称为Team.Player(“Team”包中的Player类),則对应的表是“Team.Player”(在“Team”架构中的Player表)
如果引用的SQL表名没有模式名,则使用默认的模式名(SQLUser)例如,命令:
对于持久类默认情况丅,短类名变为表名要指定不同的表名,请使用SqlTableName类关键字例如:
尽管Caché对类名没有限制,但是SQL表不能有SQL保留字的名称。因此如果创建一个名称为保留字的持久类,Caché class编译器将生成一条错误消息在这种情况下,必须重命名类或为映射指定与类名不同的表名
%Persistent类提供用於在数据库中存储和检索对象的高级接口。
每个持久对象和每个序列对象都使用一个存储类来生成用于在数据库中存储、加载和删除对象嘚实际方法这些内部方法称为存储接口。存储接口包括%LoadData()、%SaveData()和%DeleteData()等方法应用程序从不直接调用这些方法;而是在适当的时间甴持久性接口的方法(如%OpenId()和%Save())调用。
持久类使用的存储类由存储定义指定存储定义包含一组关键字和值,这些关键字和值定义存储类以及存储接口使用的其他参数
持久类可以包含多个存储定义,但一次只能有一个处于活动状态
使用类的StorageStrategy关键字指定活动存储定義。默认情况下持久类有一个称为“default”的存储定义。
类的存储定义是在首次编译该类时创建的类映射(如对于SQL或多值)在编译后发生。如果类编译正确然后映射失败,Caché不会删除存储定义。此外,如果类的更改方式可能会影响存储定义,则应用程序开发人员有责任确定存储定义是否已更新并在必要时修改存储定义以反映更改。
%CacheStorage是持久对象使用的默认存储类它自动创建并维护持久类的默认存储结构。
噺的持久类自动使用%CacheStorage存储类.%CacheStorage类允许通过存储定义中的各种关键字来控制用于类的存储结构的某些方面
- 将对象映射到旧应用程序使用的现囿全局结构。
- 使用SQL网关在外部关系数据库中存储对象
注意:也就不是支持Extent模式
编译使用默认%CacheStorage存储类的持久(或序列)类时,类编译器将汾析该类定义的属性并自动添加或删除它们。
如果希望看到模式的演进请尝试以下操作:
- 启动CachéStudio并创建一个包含一个或多个属性的新歭久类。
- 编译该类然后在整个类定义中查看该类自动生成的存储定义(作为XML文本)。或者可以使用类检查器查看存储的更图形化表示。单击Inspector中的存储单击存储定义列表中的“默认”,单击关键字列表中的数据节点然后单击出现的浏览按钮(…)。这将调用图形存储編辑器
在为类生成的存储中,将看到伪属性%%CLASSNAME这是一个占位符,用于表示将来可能从类派生的任何子类的类名并用于告诉存储在数据庫中的对象类型。对于数据块的根类此值始终为空。
- 向类中添加一个或多个新属性并再次编译它请注意,这些新属性是自动添加到存儲定义中的并且是以与以前的存储兼容的方式添加的。
在开发过程中可以对持久类进行许多修改:添加、修改和删除属性。因此当類编译器试图维护兼容的结构时,可能会得到一个相当复杂的存储定义如果希望类编译器生成干净的存储结构,请删除存储定义并重新編译该类
- 右键单击类检查器中的默认存储定义。
- 在弹出菜单中调用Delete命令
- 编译类。这将导致类编译器为类生成新的存储定义
第一次保存对象时,Caché会为该对象生成一个ID身份证是永久的。
默认情况下Caché使用一个整数作为ID,从上次保存的对象开始递增1
可以定义一个给萣的持久类,以便它以以下任一方式生成ID:
- 如果每个实例的属性都是唯一的则ID可以基于类的特定属性。例如可以使用药品代码作为ID。若要以这种方式定义类请在类中添加如下索引:
如果这样定义类,当Caché首次保存对象时,它将使用该属性的值作为ID此外,Caché需要属性的值并强制该属性的唯一性如果为指定的属性创建另一个具有相同值的对象,然后尝试保存新对象则Caché会发出以下错误:
此外,Caché防止在将来更改该属性。也就是说,如果打开已保存的对象更改属性值,并尝试保存已更改的对象则Caché会发出以下错误:
这个消息引用的是OID洏不是ID,因为底层逻辑阻止了OID的更改;OID是基于ID的
- ID可以基于多个属性。要以这种方式定义类请向类添加如下索引:
如果这样定义类,当Caché第一次保存对象时,它会生成一个ID如下所示:
此外,Caché要求属性的值,并强制给定属性组合的唯一性阻止更改任何这些属性。
重要提礻:如果文字属性(即属性)包含一对连续的竖线(||)则不要添加使用该属性的IdKey索引。这种限制是由CachéSQL机制的工作方式强加的在IdKey属性Φ使用| |会导致不可预测的行为。
Caché也会产生一个OID在所有情况下,OID都有以下形式:
当几个持久类位于父类/子类层次结构中时Caché可以用两种方式存储它们的数据。默认情况是目前最常见的。
类编译器映射持久类的“flattened”表示这样映射的表包含该类的所有适当字段,包括继承的芓段因此,对于子类SQL映射是一个表,由以下内容组成:
- 仅基于子类中的属性的附加列
- 表示子类的已保存实例的行
此外在默认场景中,超类的范围包含一条记录用于超类及其所有子类的每个已保存对象。每个子类的范围是超类范围的子集
要了解这一点,请使用以下SQL查询第一个列表列出Sample.Person的所有实例并显示其属性:
第二个查询列出Sample.Employee的所有实例及其属性:
通常,子类的表比其父类有更多的列和更少的行子类中有更多的列,因为它在扩展父类时通常会添加其他属性;通常行数较少因为子类的实例通常比父类少。
默认的映射是最方便的但是有时,可能会发现有必要使用替代的SQL映射在这个场景中,每个类都有自己的继承要引用这种形式的映射,请在父类的定义中包含以下内容:
这个类的每个子类都接收自己的范围(extent继承)
在开发过程中,重新定义类是很常见的如果已经为类创建了示例数据,请注意鉯下几点:
事实上,当删除一个类定义时它的数据全局变量是不变的。如果不再需要这些全局参数请手动删除它们。
-
如果添加或删除类的属性但不修改该类的存储定义,则访问该类数据的所有代码将继续像以前一样工作
-
如果确实修改了类的存储定义,则访问数据的代码可能会继续工作也可能不会继续工作,这取决于更改的性质
-
如果修改属性定义的方式導致属性验证更加严格,则在处理不再通过验证的对象(或记录)时将收到错误例如,如果减少某个属性的MAXLEN参数则当处理的对象的值現在太长时,将收到验证错误