📄 openjpa.htm
字号:
等,或者它们对应的包装器类型 Byte、Short、Integer、Long 等,也可以是字符串类型。
<BR><BR>GeneratedValue 注释可以支持两个属性 strategy 和 generator。
<BR><BR> ● strategy <BR><BR>strategy 是 GenerationType
类型的枚举值,它的内容将指定 OpenJPA 容器自动生成实体标识的方式。strategy 属性可以是下列枚举值:
<BR> ○ GeneratorType.AUTO <BR><BR>表示实体标识由 OpenJPA
容器自动生成,这也是 Strategy 属性的默认值。 <BR> ○ GenerationType.IDENTITY
<BR><BR>OpenJPA
容器将使用数据库的自增长字段为新增加的实体对象赋唯一值,作为实体的标识。这种情况下需要数据库提供对自增长字段的支持,常用的数据库中,HSQL、SQL
Server、MySQL、DB2、Derby 等数据库都能够提供这种支持。 <BR> ○
GenerationType.SEQUENCE
<BR><BR>表示使用数据库的序列号为新增加的实体对象赋唯一值,作为实体的标识。这种情况下需要数据库提供对序列号的支持,常用的数据库中,Oracle、PostgreSQL
等数据库都能够提供这种支持。 <BR> ○ GenerationType.TABLE
<BR><BR>表示使用数据库中指定表的某个字段记录实体对象的标识,通过该字段的增长为新增加的实体对象赋唯一值,作为实体的标识。
<BR> ● String generator <BR><BR>generator
属性中定义实体标识生成器的名称。如果实体的标识自动生成策略不是 GenerationType.AUTO 或者
GenerationType.IDENTITY,就需要提供相应的 SequenceGenerator 或者
TableGenerator 注释,然后将 generator 属性值设置为注释的 name 属性值。
<BR><BR><SPAN
style="FONT-SIZE: 15px; LINE-HEIGHT: normal"><B>@javax.persistence.SequenceGenerator</B></SPAN>
<BR><BR>如果实体标识的自动生策略是 GenerationType.SEQUENCE,开发者需要为实体标识字段提供
SequenceGenerator 注释,它的参数描述了使用序列号生成实体标识的具体细节。该注释支持以下四个属性:
<BR><BR>表 1. SequenceGenerator 注释属性说明 <BR>属性 说明 <BR>name
该属性是必须设置的属性,它表示了 SequenceGenerator 注释在 OpenJPA 容器中的唯一名称,将会被
GeneratedValue 注释的 generator
属性使用。将实体标识的自动生成委托给数据库的序列号特性时,实体标识字段的 GeneratedValue 注释的
generator 属性的值必须和某个 SequenceGenerator 注释的 name 属性值保持一致。
<BR>sequenceName
实体标识所使用的数据库序列号的名称。该属性是可选的,如果我们没有为该属性设置值,OpenJPA 框架将自动创建名为
OPENJPA_SEQUENCE 的序列号。如果一个 OpenJPA
容器中管理的多个实体都选择使用序列号机制生成实体标识,而且实体类中都没有指定标识字段的 sequenceName
属性,那么这些实体将会共享系统提供的默认名为 OPENJPA_SEQUENCE
的序列号。这可能引起实体类编号的不连续。我们可以用下面的这个简单例子说明这种情况:假设 OpenJPA 容器中存在两个实体类
Dog 和 Fish,它们的实体标识字段都是数值型,并且都选择使用序列号生成实体标识,但是实体类中并没有提供
sequenceName 属性值。当我们首先持久化一个 Dog 对象时,它的实体标识将会是 1,紧接着我们持久化一个
Fish 对象,它的实体标识就是 2,依次类推。 <BR>initialValue 该属性设置所使用序列号的起始值。
<BR>allocationSize 一些数据库的序列化机制允许预先分配序列号,比如
Oracle,这种预先分配机制可以一次性生成多个序列号,然后放在 cache 中,数据库用户获取的序列号是从序列号
cache 中获取的,这样就避免了在每一次数据库用户获取序列号的时候都要重新生成序列号。allocationSize
属性设置的就是一次预先分配序列号的数目,默认情况下 allocationSize 属性的值是 50。
<BR><BR><SPAN
style="FONT-SIZE: 15px; LINE-HEIGHT: normal"><B>@javax.persistence.TableGenerator</B></SPAN>
<BR><BR>如果实体标识的自动生策略是 GenerationType.TABLE,开发者需要为实体标识字段提供
TableGenerator 注释,它的参数描述了使用数据库表生成实体标识的具体细节。该注释支持下列属性:
<BR><BR>表 2. TableGenerator 注释属性说明 <BR>属性 说明 <BR>name
该属性是必须设置的属性,它表示了 TableGenerator 注释在 OpenJPA 容器中的唯一名称,将会被
GeneratedValue 注释的 generator 属性所使用。将实体标识的自动生成委托给数据库表时,实体标识字段的
GeneratedValue 注释的 generator 属性的值必须和某个 TableGenerator 注释的 name
属性值保持一致。 <BR>table
该属性设置的是生成序列号的表的名称。该属性并不是必须设置的属性,如果开发者没有为该属性设置值,OpenJPA
容器将会使用默认的表名 OPENJPA_SEQUENCES_TABLE 。 <BR>schema
该属性设置的是生成序列号的表的 schema。该属性并不是必须设置的属性,如果开发者没有为该属性设置值,OpenJPA
容器将会默认使用当前数据库用户对应的 schema。 <BR>catalog 该属性设置的是生成序列号的表的
catalog。该属性并不是必须设置的属性,如果开发者没有为该属性设置值,OpenJPA
容器将会使用默认当前数据库用户对应的 catalog。 <BR>pkColumnName
该属性设置的是生成序列号的表中的主键字段的名称,该字段将保存代表每个实体对应的标识值对应的特征字符串。该属性并不是必须设置的属性,如果开发者没有为该属性设置值,OpenJPA
容器将会使用默认值 ID 。 <BR>valueColumnName
该属性设置的是生成序列号的表中记录实体对应标识最大值的字段的名称。该属性并不是必须设置的属性,如果开发者没有为该
属性设置值,OpenJPA 容器将会使用默认值 SEQUENCE_VALUE 。 <BR>pkColumnValue
该属性设置的是生成序列号的表中的主键字段的特征字符串值 ( 比如 customID
),该字段将保存代表每个实体对应的标识值对应的特征字符串。该属性并不是必须设置的属性,如果开发者没有为该属性设置值,OpenJPA
容器将会使用默认值 DEFAULT 。可以为多个实体设置相同的 pkColumnValue
属性值,这些实体标识的生成将通过同一列的值的递增来实现。 <BR>initialValue
该属性设置的是生成序列号的表实体标识的初始值。该属性并不是必须设置的属性,如果开发者没有为该属性设置值,OpenJPA
容器将会使用默认值 0 。 <BR>allocationSize 为了降低标识生成时频繁操作数据库造成
的性能上的影响,实体标识生成的时候会一次性的获取多个实体标识,该属性设置的就是一次性获取实体标识的数目。该属性并不是必须设置的属性,如果开发者没有为该属性设置值,OpenJPA
容器将会使用默认值 50 。 <BR><BR><SPAN
style="FONT-SIZE: 18px; LINE-HEIGHT: normal"><B>实体标识自动生成</B></SPAN>
<BR><BR>在上面的小节中,我们了解了和实体标识自动生成相关的注释,接下来我们将结合一个简单的例子讲述如何分别使用这些实体标识自动生成策略实现实体标识的自动生成。
<BR><BR>我们首先假设有一个 Animal 实体需要被持久化,它包括 ID 和 NAME 属性,其中 ID
是它的主键字段。Animal 实体的标识需要自动生成,我们将分析在这四种不用的情况下,如何使用 OpenJPA
提供的注释,结合具体数据库支持的特性,如自增长字段、序列号等来实现实体标识的自动生成。 <BR><BR><SPAN
style="FONT-SIZE: 15px; LINE-HEIGHT: normal"><B>容器自动生成</B></SPAN>
<BR><BR>OpenJPA
容器默认的实体标识自动生成策略是由容器管理实体标识的自动生成,容器管理的实体标识可以支持数值型和字符型两种。当容器管理的实体标识是数字型时,OpenJPA
容器自动创建一个数据库表 OPENJPA_SEQUENCE_TABLE,用其中的 SEQUENCE_VALUE
字段来记录实体的实体标识的增长。 <BR><BR>当容器管理的实体标识是字符串类型时,OpenJPA 支持使用
uuid-string 和 uuid-hex 两种方式生成相应的实体标识。如果我们选择使用 uuid-string
方式生成实体标识时,OpenJPA 框架会自动为实体生成一个 128 位的 UUID,并且将这个 UUID 转化为使用 16
位字符表示的字符串。如果我们选择使用 uuid-hex 方式生成实体标识时,OpenJPA 框架会自动为实体生成一个 128
位的 UUID,并且将这个 UUID 转化为使用 32 位字符表示的 16 进制的字符串。
<BR><BR><B>数值标识</B> <BR><BR>容器管理的实体标识可以是数值型的,OpenJPA
框架管理的实体标识借助于数据库的表来实现,在运行时 OpenJPA 框架会自动在数据库中创建表
OPENJPA_SEQUENCE_TABLE。它有两个字段:ID 和 SEQUENCE_VALUE
,这两个字段都是数值类型,其中 ID 是表的主键字段,它的内容是查询当前实体标识时所使用的关键词,默认值是 0。而
SEQUENCE_VALUE 记录了当前 OpenJPA 框架中当前实体标识的历史数据,内容是已经被获取实体标识的最大数值加
1。 <BR><BR>我们要使用注释描述 Animal 实体的标识由容器自动生成,只需要为它的标识字段提供
GeneratedValue 注释,并且把它的 strategy 属性设置为 GenerationType.AUTO ,
Animal 实体类的代码片断如下: <BR><BR>清单 1. 标识由容器自动生成的 Animal 实体类
<BR><BR><BR>1. import javax.persistence.Entity; <BR>2. import
javax.persistence.GeneratedValue; <BR>3. import
javax.persistence.GenerationType; <BR>4. import
javax.persistence.Id; <BR>5. <BR>6. @Entity <BR>7. public
class Animal { <BR>8. @Id <BR>9.
@GeneratedValue(strategy=GenerationType.AUTO) <BR>10. private
long id; <BR>11. private String name; <BR>12. <BR>13. …
<BR>14. <BR>15. } <BR><BR><BR>保存 Animal 实体的第一个实例时,OpenJPA
框架自动调用 SQL 语句 SELECT SEQUENCE_VALUE FROM
OPENJPA_SEQUENCE_TABLE WHERE ID=0,从默认保存实体标识的
OPENJPA_SEQUENCE_TABLE 表中获取实体的标识,如果不存在 ID 为 0 的记录,OpenJPA
框架自动将实体的标识设置为 1。
<BR><BR>容器管理实体标识的情况下,为了获得实体标识,应用程序将不得不频繁地和数据库交互,这会影响应用程序的运行效率。OpenJPA
中使用实体标识缓存机制解决这个问题。默认情况下,当应用程序第一次获取实体标识时,OpenJPA 框架从数据库中一次性获取
50 个连续的实体标识缓存起来,当下一次应用程序需要获取实体标识时,OpenJPA
将首先检测缓存中是否存在实体标识,如果存在,OpenJPA 将直接使用缓存中的实体标识,如果不存在,OpenJPA
框架将会从数据库中再次获取 50
个连续的实体标识缓存起来,如此类推。这样的处理方式可以大大减少由于获取实体标识而产生的数据库交互,提升应用程序的运行效率。
<BR><BR>当实体标识成功获取之后,OpenJPA 框架会把当前实体标识的最大值 +1
后持久化到数据库中。由于实体标识缓存的原因,当我们第一次获取实体标识后,OpenJPA 会将
OPENJPA_SEQUENCE_TABLE 表的 SEQUENCE_VALUE 的值设置为 51,当 OpenJPA
多次从数据库中获取实体标识后,SEQUENCE_VALUE 的值会以 50 为单位递增,变为 101、151、201 …。
<BR><BR>OpenJPA 缓存的实体标识不是永久存在的,只能在同一个 EntityManagerFactory
管理范围内起作用,也就是说,当获取实体标识的 EntityManagerFactory
对象被关闭后,这些被获取的实体标识中没有用掉的那一部分标识就丢失了,这会造成实体标识的不连续。由同一个
EntityManagerFactory 对象创建的 EntityManager 上下文之间则能够共享 OpenJPA
框架获取的实体标识,这意味着,我们可以使用同一个 EntityManagerFactory 对象创建多个
EntityManager
对象,用它来持久化实体,然后关闭它,在持久化过程中所需要的实体表示将会使用同一个实体标识的缓存区,因此不会引起实体标识的丢失。
<BR><BR>容器管理的实体标识还有一个非常重要的特性:所有被容器管理的实体标识都是共享的。不管 OpenJPA
容器中存在多少个不同的被容器管理的实体标识,它们都会从同一个实体标识缓存中获取实体标识。我们可以用下面的例子说明这种情况:假设
OpenJPA 容器中存在两个实体类 Dog 和 Fish,它们的实体标识字段都是数值型,并且都由 OpenJPA
管理。当我们首先持久化一个 Dog 对象时,它的实体标识将会是 1,紧接着我们持久化一个 Fish 对象,它的实体标识就是
2,依次类推。 <BR><BR><B>uuid-string</B> <BR><BR>要使用 uuid-string
机制自动生成实体标识,我们需要将实体主键字段的 GeneratedValue 注释的 strategy 属性设置为
GenarationType.AUTO,然后将 GeneratedValue 注释的 generator 属性设置为
uuid-string。以 Animal 实体类为例,我们只需要将 Animal 实体修改为如下内容: <BR><BR>清单
2. 使用 uuid-string 机制自动生成实体标识 <BR><BR><BR>1. import
javax.persistence.Entity; <BR>2. import
javax.persistence.GeneratedValue; <BR>3. import
javax.persistence.GenerationType; <BR>4. import
javax.persistence.Id; <BR>5. <BR>6. @Entity <BR>7. public
class Animal { <BR>8. @Id <BR>9.
@GeneratedValue(strategy=GenerationType.AUTO, generator =
"uuid-string") <BR>10. private String id; <BR>11. private
String name; <BR>12. <BR>13. … <BR>14. <BR>15. }
<BR><BR><BR><B>uuid-hex</B> <BR><BR>要使用 uuid-hex
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -