MyEclipse6Java开发中文教程 Hibernate不同的,每个持久化单元可以连接到各自的数据库上去。每个持久化单元都有自 己的名字(name属性)和事务类型的定义( transaction-type属性)。名字用来访问数据的 时候根据其取值来创建持久化单元。事务类型则分为 RESOURCE LOCAL(本地事务,适 用于独立运行的或者没有EJB容器的环境)和JTA( Java transaction aPl,Java事务APl 般用于带有EJB容器的环境,或者说运行于服务器中)。如上面代码所示,这份文件中定 义了一个名为 JPADemoPU的持久化单元。 在每个持久化单元的定义里面,还需要定义 provider,它指定了JPA的底层实现类。 前面已经介绍过了,JPA核心是一套接口(规范,本身无功能,只是规定应该有什么样的行 为),它一定要有底层的实现类才可以。这个提供者,就是类似于 Hibernate Entity Manager, KODO, TopLink这样的框架中所提供的核心实现类了。JPA的优点就在于,如果我们想切 换到别的框架上,只需要将这个提供者改掉,相关的属性(见后面 properties)加以修改即 可,别的所有的Java代码都不需要重新变动即可工作。 再接着的内容,就是cass定义,它定义了有哪些类是实体类,可以用来做持久化管理。 在例子中取值为 jiadao. Muse,它是一个普通的 Javabean。因为JPA中的实体类就是普 通的加了些标注的 JavaBean,因此在独立运行的情况下,这样的符合要求的 JavaBean有 成千上亿个之多,如果一个个的去检查这些类是不是加了标注,那将是十分消耗时间的。所 以,在普通模式下,我们通过多个cass标签来列出哪些是需要被作为实体类来处理的,这 样系统的复杂度和启动速度都会大大加快。这就好像是要你找出本市的所有女人一样(咱们 假设不算流动人口),最直接的办法就是把所有女人集中到一个广场里,数一数有多少个是 女人:然而还有一个办法,是通过查国家安全部门的身份证,因为每个人都是有标注的(身 份证信息),可以表明它是男还是女,这样,就很快可以精确的找到北京有多少个人了,很 显然,这些信息是要保存在一个地方的,就像是在这个配置文件中通过cass标签来声明有 多少个类是实体类一样 最后面出现的内容是 properties(复数的属性)标签,它的下面是对应的定义了一个或 者多个的 property(单个属性)子标签。这些属性的名称和取值,一般都是和特定的JPA 实现相关的。不过,一般来说这些属性包括了和数据库相关联的信息,包括驱动,URL,用 户名和密码等等。另外,还可以多设置一些额外的信息例如和特定的ORM实现相关的扩展, 例如 Hibernate可以设置一个属性来打印出每次操作所使用的SQL语句 关于这个文件还有一些别的配置信息,例如∫ta-data- source标记,是用于服务器环境 下的数据源访问的,它指定实体Bean使用的数据源JNDI名称,将在EJB一节进行讨论, 在这里我们暂时还不多做介绍。 13133实体类及标注 开发的第二步,就是编写实体类。和 Hibernate中的实体类一样,它一般是和数据库中 的某个表相对应的。不过在JPA中,实体类可以加入标注,因此它还担负着如何让实体类 中的属性和数据库中的表和字段相对应的责任。简言之就是JPA实体类就是一个普通的带 有属性的 Javabean外加实体标注。在图113中,左侧列出了 My SQL数据库中的test数 据库中的表user及其表的三个字段,而在右侧则列出了实体类及所标注的各个信息和表的 对应关系。 刘长炯著
MyEclipse 6 Java 开发中文教程 6 刘长炯著 Hibernate 不同的,每个持久化单元可以连接到各自的数据库上去。每个持久化单元都有自 己的名字(name 属性)和事务类型的定义(transaction-type 属性)。名字用来访问数据的 时候根据其取值来创建持久化单元。事务类型则分为 RESOURCE_LOCAL(本地事务,适 用于独立运行的或者没有 EJB 容器的环境)和 JTA(Java Transaction API,Java 事务 API, 一般用于带有 EJB 容器的环境,或者说运行于服务器中)。如上面代码所示,这份文件中定 义了一个名为 JPADemoPU 的持久化单元。 在每个持久化单元的定义里面,还需要定义 provider,它指定了 JPA 的底层实现类。 前面已经介绍过了,JPA 核心是一套接口(规范,本身无功能,只是规定应该有什么样的行 为),它一定要有底层的实现类才可以。这个提供者,就是类似于 Hibernate EntityManager, KODO,TopLink 这样的框架中所提供的核心实现类了。JPA 的优点就在于,如果我们想切 换到别的框架上,只需要将这个提供者改掉,相关的属性(见后面 properties)加以修改即 可,别的所有的 Java 代码都不需要重新变动即可工作。 再接着的内容,就是 class 定义,它定义了有哪些类是实体类,可以用来做持久化管理。 在例子中取值为 jpadao.Myuser,它是一个普通的 JavaBean。因为 JPA 中的实体类就是普 通的加了些标注的 JavaBean,因此在独立运行的情况下,这样的符合要求的 JavaBean 有 成千上亿个之多,如果一个个的去检查这些类是不是加了标注,那将是十分消耗时间的。所 以,在普通模式下,我们通过多个 class 标签来列出哪些是需要被作为实体类来处理的,这 样系统的复杂度和启动速度都会大大加快。这就好像是要你找出本市的所有女人一样(咱们 假设不算流动人口),最直接的办法就是把所有女人集中到一个广场里,数一数有多少个是 女人;然而还有一个办法,是通过查国家安全部门的身份证,因为每个人都是有标注的(身 份证信息),可以表明它是男还是女,这样,就很快可以精确的找到北京有多少个人了,很 显然,这些信息是要保存在一个地方的,就像是在这个配置文件中通过 class 标签来声明有 多少个类是实体类一样。 最后面出现的内容是 properties(复数的属性)标签,它的下面是对应的定义了一个或 者多个的 property(单个属性)子标签。这些属性的名称和取值,一般都是和特定的 JPA 实现相关的。不过,一般来说这些属性包括了和数据库相关联的信息,包括驱动,URL,用 户名和密码等等。另外,还可以多设置一些额外的信息例如和特定的 ORM 实现相关的扩展, 例如 Hibernate 可以设置一个属性来打印出每次操作所使用的 SQL 语句。 关于这个文件还有一些别的配置信息,例如 jta-data-source 标记,是用于服务器环境 下的数据源访问的,它指定实体 Bean 使用的数据源 JNDI 名称,将在 EJB 一节进行讨论, 在这里我们暂时还不多做介绍。 13.1.3.3 实体类及标注 开发的第二步,就是编写实体类。和 Hibernate 中的实体类一样,它一般是和数据库中 的某个表相对应的。不过在 JPA 中,实体类可以加入标注,因此它还担负着如何让实体类 中的属性和数据库中的表和字段相对应的责任。简言之就是 JPA 实体类就是一个普通的带 有属性的 JavaBean 外加实体标注。在图 11.3 中,左侧列出了 MySQL 数据库中的 test 数 据库中的表 user 及其表的三个字段,而在右侧则列出了实体类及所标注的各个信息和表的 对应关系
MyEclipse6Java开发中文教程 百 mydatabase 214 eTable(na CL三"test";unic +百 LOCAL TEMPORARY //Fie⊥ds 20 private String- username iwate st 图133实体类标注和数据库表格的对应关系 现在我们来列出一个简单的实体类代码,并加以分析和介绍 package users; lmport javax. persistence.* ENtity (name=User" @Table(name ="myuser", catalog ="test", uniqueConstraints =() public class Myuser implements java. io Serializable i /变量定义 private Integer id private string username private String password public Myuser()i Property acce @Column id", unique true, nullable false, insertable true, updatable aGene alue(strategy=GenerationType IDENTITY) public Integer getId(t return this. id public void setId(Integer id)( this, id id @Column(name unique false, nullable false, insertable true, updatable rue, length 200 public string getUsername()i return this username 刘长炯著
MyEclipse 6 Java 开发中文教程 7 刘长炯著 图 13.3 实体类标注和数据库表格的对应关系 现在我们来列出一个简单的实体类代码,并加以分析和介绍: package users; import javax.persistence.*; @Entity(name="User") @Table(name = "myuser", catalog = "test", uniqueConstraints = {}) public class Myuser implements java.io.Serializable { // 变量定义 private Integer id; private String username; private String password; public Myuser() { } // Property accessors @Id @Column(name = "id", unique = true, nullable = false, insertable = true, updatable = true) @GeneratedValue(strategy=GenerationType.IDENTITY) public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @Column(name = "username", unique = false, nullable = false, insertable = true, updatable = true, length = 200) public String getUsername() { return this.username;
MyEclipse6Java开发中文教程 public void setUsername(String username) I this, username username //省略更多属性定义 首先可能部分读者对Java5的标注还不是特别的熟悉。比较正式的文档都会这样介绍: Annotation提供一种机制,将程序中元素(如类、方法、属性等)和元数据联系起来。这 样编译器可以将元数据保存的cass文件中。代码分析工具就可以使用这些元数据执行的额 外任务。注释采用“at”标记形式(@),后面是注释名称。那么标注呢,其实就是。个特 殊的只是用来附加一些信息用的类,在英文中它的写法是 Annotation,本意就是注释的意思 关于这个词还有其它的一些翻译方式,例如叫元数据,注解,注释等等,都是指代的同一个 东西。不管怎么说,它其实就相当于一个超市里商品的标签,虽然大家都知道店面上摆着 排苹果,从外观来看大概这些苹果也相同,但是定价和产地等信息呢,一般则是卖家提供的 所以他们会在上面贴一个标签,表明定价,产地等信息。再比如说,大家买一台电脑,店家 肯定不是只告诉你一个总价钱了事,这样你也不会答应啊,所以,这台电脑的各个部件都会 有说明信息,店家会给你一个列表,标明: CPU Intel权核,主频2G,内存大小2G等等 类似的信息,这和中的标注也是类似的,它可以标到类型的声明上,或者是构造器 变量和方法上。要用一个标注,首先当然是需要创建一个标注类了,选择菜单Fie>New> Annotation,输入标注名,就可以创建标注了,下面列出了我们所创建的一个名 TestAnnotation的标注的代码清单,并列出了它的示例用法 import java. lang annotation. ted//是否 的时候列出此标 tArget(ElementType. TYPE, ElementType CONSTRUCTOR ElementType METHOD, Element Type FIELD]) /指定目标,可以标到类型构造器,方法和变量上 rEtention( Retention1icy.RMIM)/设置保持性 iNherited public interface TestAnnotation String va1ue() default"test1";//这里定义了一个属性 value(通过方法名来定 义,不是变量声明),并指定了默认值test1 String name()default ""i @TestAnnotation(name="Samplel",value="Valuel") //标注的使用简单示例 class sampleS t @TestAnnotation(value =id 1") private int id 刘长炯著
MyEclipse 6 Java 开发中文教程 8 刘长炯著 } public void setUsername(String username) { this.username = username; } //省略更多属性定义 } 首先可能部分读者对 Java 5 的标注还不是特别的熟悉。比较正式的文档都会这样介绍: Annotation 提供一种机制,将程序中元素(如类、方法、属性等)和元数据联系起来。这 样编译器可以将元数据保存的 class 文件中。代码分析工具就可以使用这些元数据执行的额 外任务。注释采用“at”标记形式 ( @ ),后面是注释名称。那么标注呢,其实就是一个特 殊的只是用来附加一些信息用的类,在英文中它的写法是 Annotation,本意就是注释的意思。 关于这个词还有其它的一些翻译方式,例如叫元数据,注解,注释等等,都是指代的同一个 东西。不管怎么说,它其实就相当于一个超市里商品的标签,虽然大家都知道店面上摆着一 排苹果,从外观来看大概这些苹果也相同,但是定价和产地等信息呢,一般则是卖家提供的, 所以他们会在上面贴一个标签,表明定价,产地等信息。再比如说,大家买一台电脑,店家 肯定不是只告诉你一个总价钱了事,这样你也不会答应啊,所以,这台电脑的各个部件都会 有说明信息,店家会给你一个列表,标明:CPU Intel 双核,主频 2G,内存大小 2G 等等 类似的信息。这和 Java 中的标注也是类似的,它可以标注到类型的声明上,或者是构造器, 变量和方法上。要用一个标注,首先当然是需要创建一个标注类了,选择菜单 File > New > Annotation,输入标注名,就可以创建标注了。下面列出了我们所创建的一个名为 TestAnnotation 的标注的代码清单,并列出了它的示例用法: import java.lang.annotation.*; @Documented// 是否产生JavaDoc的时候列出此标注信息 @Target({ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD}) //指定目标, 可以标到类型,构造器,方法和变量上 @Retention(RetentionPolicy.RUNTIME)//设置保持性 @Inherited public @interface TestAnnotation { String value() default "test1";//这里定义了一个属性 value(通过方法名来定 义,不是变量声明),并指定了默认值test1 String name() default ""; } @TestAnnotation(name="Sample1", value="Value1") // 标注的使用简单示例 class SampleUse { @TestAnnotation(value = "id_1") private int id;
MyEclipse6Java开发中文教程 TestAnnotation("id2")//当只有一个名为 的属性的时候,可以省略属性名 public int getid)[ return id; 。它使用@ Dinterface这样的关键字来定义的。好了,这些标注到底有什么用?Java的发明 者为什么要发明这个玩意呢?希望通过刚才的例子,读者已经可以简单理解到标注可以自己 带一些值附加到当前类上,那么很好,它的好处就在这里:给类多一些附加的信息。这些信 息可以通过反射( reflection)的APl读取出来,然后进行更进一步的处理。必须澄清一个 概念:依赖注入和代码写标注以及容器解析标注是三码事,要实现标注注入缺一不可。把自 己写的类加个写个@ Entity或者@EJB,不放入对应的容器里执行,那就还是普通的类而 已。所有的 Annotation本身什么也不能做,要做注入需要通过容器来获取对应的实例然后 解析上面的标注后做对应的操作。换句话说你自己new一个带标注的Bean,是什么效果 也没有的,只能通过容器来初始化,用类似于 getBean的方式,容器才能有机会进行注入 操作。 JPA通过定义一些不同的标注类型,将原来的配置文件信息从ⅩML配置文件中转移到 了Java类中。那么有什么好处呢?有一些资料已经列出了它的一些好处: 类似于 Hibernate的传统模式的ORM框架大都是采用xm作为配置文件,但采用文本 的xm配置存在一些缺陷: 描述符多,不容易记忆和掌握 ●无法做自动的校验,需要人工排错 当系统变大时,大量的xm配置难以管理 读取和解析xm配置非常耗时,导致应用启动缓慢,不利于测试和维护 做 O/R Mapping的时候需要在java文件和xm配置文件之间交替,增大了工作量 运行中保存xm配置需要消耗额外的内存 采用标注可以很好的解决这些问题 1.描述符大量减少。以往在xm配置中往往需要描述java属性的类型,关系等等。 而标注本身就是java语言,从而省略了大量的描述符 2.编译期校验。错误的批注在编译期间就会报错 3.标注批注在java代码中,避免了额外的文件维护工作 4.标注被编译成 java bytecode,消耗小的多内存,读取也非常迅速,往往比xm配 置解析快几个数据量级,利于测试和维护 。好了,这就是它的优点,最大的好处恐怕不在于3,而在于1和。4勉强算一个,因为3 和4都牵扯到改动信息的时候,需要找到类的源代码才可以,而且必须通过编译这一步, 所以有时候,例如成百上千的标注需要修改的时候,优势就不是那么的明显了。 注意:由于JPA依赖标注进行工作,所以JAP应用和标注代码都必须运行在Java5(JDK 15)或者更高版本上! 好了,现在我们的话题已经跑的足够远了,需要回过头来再看看刚才的实体类定义了 先来看看类的标注。 @ Entity:将 JavaBean标注为一个实体,表示需要保存到数据库中,默认情况下类名 即为表名,通过name属性可以显式指定实体名。在这个地方某些资料介绍有误,实体名 并不等于表名,只能说默认情况下实体名和表名以及类名这三者是一致的。然而,实体名最 刘长炯著
MyEclipse 6 Java 开发中文教程 9 刘长炯著 @TestAnnotation("id_2")//当只有一个名为value的属性的时候,可以省略属性名 value public int getID() { return id; } } 。它使用@interface 这样的关键字来定义的。好了,这些标注到底有什么用?Java 的发明 者为什么要发明这个玩意呢?希望通过刚才的例子,读者已经可以简单理解到标注可以自己 带一些值附加到当前类上,那么很好,它的好处就在这里:给类多一些附加的信息。这些信 息可以通过反射(reflection)的 API 读取出来,然后进行更进一步的处理。必须澄清一个 概念:依赖注入和代码写标注以及容器解析标注是三码事,要实现标注注入缺一不可。把自 己写的类加个写个 @Entity 或者 @EJB,不放入对应的容器里执行,那就还是普通的类而 已。所有的 Annotation 本身什么也不能做,要做注入需要通过容器来获取对应的实例然后 解析上面的标注后做对应的操作。换句话说你自己 new 一个带标注的 Bean,是什么效果 也没有的,只能通过容器来初始化,用类似于 getBean 的方式,容器才能有机会进行注入 操作。 JPA 通过定义一些不同的标注类型,将原来的配置文件信息从 XML 配置文件中转移到 了 Java 类中。那么有什么好处呢?有一些资料已经列出了它的一些好处: 类似于 Hibernate 的传统模式的 ORM 框架大都是采用 xml 作为配置文件,但采用文本 的 xml 配置存在一些缺陷: z 描述符多,不容易记忆和掌握 z 无法做自动的校验,需要人工排错 z 当系统变大时,大量的 xml 配置难以管理 z 读取和解析 xml 配置非常耗时,导致应用启动缓慢,不利于测试和维护 z 做 O/R Mapping 的时候需要在 java 文件和 xml 配置文件之间交替,增大了工作量 z 运行中保存 xml 配置需要消耗额外的内存 采用标注可以很好的解决这些问题: 1. 描述符大量减少。以往在 xml 配置中往往需要描述 java 属性的类型,关系等等。 而标注本身就是 java 语言,从而省略了大量的描述符 2. 编译期校验。错误的批注在编译期间就会报错。 3. 标注批注在 java 代码中,避免了额外的文件维护工作 4. 标注被编译成 java bytecode,消耗小的多内存,读取也非常迅速,往往比 xml 配 置解析快几个数据量级,利于测试和维护 。好了,这就是它的优点,最大的好处恐怕不在于 3,而在于 1 和。4 勉强算一个,因为 3 和 4 都牵扯到改动信息的时候,需要找到类的源代码才可以,而且必须通过编译这一步, 所以有时候,例如成百上千的标注需要修改的时候,优势就不是那么的明显了。 注意:由于JPA依赖标注进行工作,所以JAP应用和标注代码都必须运行在Java 5(JDK 1.5)或者更高版本上! 好了,现在我们的话题已经跑的足够远了,需要回过头来再看看刚才的实体类定义了。 先来看看类的标注。 @Entity:将 JavaBean 标注为一个实体,表示需要保存到数据库中,默认情况下类名 即为表名,通过 name 属性可以显式指定实体名。在这个地方某些资料介绍有误,实体名 并不等于表名,只能说默认情况下实体名和表名以及类名这三者是一致的。然而,实体名最
MyEclipse6Java开发中文教程 主要的用途是为了进行查询时(通过 JPA QL)区分不同的实体,例如下面的查询代码: select mode/ from User model和 select model from Myuser model,将会最终去寻找不同 的实体定义。而例子中的实体名则是User。实际使用中可以不用写name属性,只写一个 @ Entity的标注,这时候实体名等于类名(不含包路径,例如 entity. MyUser最后对应的实 体名是 MyUser)。和 Hibernate中一样,这个实体名必须是唯一的!而此标注也是必须的! @ Table:顾名思义,定义当前 Entity对应数据库中的表,需要注意的是主表( pnmary tabe),因为其它的表还可以通过@ Secondary Table或者@ Secondary Tables来进行标注 在例子中它对应的数据库中的表是 myuser(用name属性定义),所在的数据库名为test (用 catalog属性定义)。实践中此标记及其附属的属性都可以省略不写,这时候对应的数 据库表就是对应着实体的名字。这个标注可以不用定义,不是必须的 @d:定义了实体的主键信息。在一个实体类中只有一个主键标注,而此标注也是必须 的!它本身没有任何额外的属性可以设置。默认情况下它对应数据库中的类型和名字和当前 属性或者实体的变量相同的列(这是因为属性可以标注在属性和变量上,后文会有进一步的 介绍)。如果下面有@ Column标记,那么对应的数据库列信息以此标记中的内容为准。 @ Generatedvalue:一般它和ID的标注配合使用,用来制定主键的生产策略。通过 strategy属性指定。默认情况下,JPA自动选择一个最适合底层数据库的主键生成策略,如 Sq| Server对应 identity,MySq对应 auto increment e在 javax. persistence. GenerationType 这个枚举类中定义了以下几种可供选择的策略: 1)∥ DENT/TY:表自增键字段, Oracle不支持这种方式; 2)AUTO:JPA自动选择合适的策略,是默认选项(不幸的是大部分时候都会选择成 Sequence); 3) SEQUENCE:通过序列产生主键,还可以进一步通过@ Sequence Generator标注来指定 更详细的生产方式,MySq不支持这种方式(注:@ Sequence Generator用法示例: @Generatedvaluestrategy=Generation Type SEQUENCE) @ Sequence Generator(name="sEQ_TEST,∥此生成器的别名 sequence Name=" ser SEQ"∥对应的 Oracle sequence的名字 allocation Size=25) ) 4) TABLE:通过表彥生主键,框架借由表模拟序列( sequence)产生主键,使用该策略可 以使应用更易于数据库移植。不同的JPA厂商所默认生成的表名是不同的,如 OpenJPA 生成 openjpa sequence table表, Hibernate生成一个 hibernate sequences表,而 TopLink则生成 sequence表。这些表都具有一个序列名和对应值两个字段,如SEQ_NAME 和SEQ_ COUNT 另外还有一个重要的属性就是 generator,它可以更进一步制定主键生成器所采用的参 数,例如 sequence表的表名可以这样定义:@ Generated Value( strategy= SEQUENCE, generator="CUST_SEQ")。同样的也可以用于 TABLE方式的生成器上 @Generated Value(strategy= TABLE, generator="CUST GEN) @ Column:属性或者变量对应的表字段。一般来说我们并不需要指定表字段的类型, 因为JPA会根据反射从实体属性中获取类型;如果是字符串类型,我们可以指定字段长度, 以便可以自动生成DDL语句:还可以指定一些其它的属性例如是否唯一( unique),是否可 以为空( nullable),是否可以插入和更新等等( insertable和 updatable);name属性指定 了它对应于数据库中的列名。如果是时间类型,一般还需要指定精度,用@7 emporal来进 行标注。同样的这个标注也不是必须的,如果没有写任何参数的话,它的名字和类型都和当 前标注的属性或者变量的名字和类型相同 刘长炯著
MyEclipse 6 Java 开发中文教程 10 刘长炯著 主要的用途是为了进行查询时(通过 JPA QL)区分不同的实体,例如下面的查询代码: select model from User model 和 select model from Myuser model,将会最终去寻找不同 的实体定义。而例子中的实体名则是 User。实际使用中可以不用写 name 属性,只写一个 @Entity 的标注,这时候实体名等于类名(不含包路径,例如 entity.MyUser 最后对应的实 体名是 MyUser)。和 Hibernate 中一样,这个实体名必须是唯一的!而此标注也是必须的! @Table:顾名思义,定义当前 Entity 对应数据库中的表,需要注意的是主表(primary table),因为其它的表还可以通过@SecondaryTable 或者@SecondaryTables 来进行标注。 在例子中它对应的数据库中的表是 myuser(用 name 属性定义),所在的数据库名为 test (用 catalog 属性定义)。实践中此标记及其附属的属性都可以省略不写,这时候对应的数 据库表就是对应着实体的名字。这个标注可以不用定义,不是必须的。 @Id:定义了实体的主键信息。在一个实体类中只有一个主键标注,而此标注也是必须 的!它本身没有任何额外的属性可以设置。默认情况下它对应数据库中的类型和名字和当前 属性或者实体的变量相同的列(这是因为属性可以标注在属性和变量上,后文会有进一步的 介绍)。如果下面有@Column 标记,那么对应的数据库列信息以此标记中的内容为准。 @GeneratedValue:一般它和 ID 的标注配合使用,用来制定主键的生产策略。通过 strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略,如 SqlServer 对应 identity,MySql 对应 auto increment。在 javax.persistence.GenerationType 这个枚举类中定义了以下几种可供选择的策略: 1) IDENTITY:表自增键字段,Oracle 不支持这种方式; 2) AUTO: JPA 自动选择合适的策略,是默认选项(不幸的是大部分时候都会选择成 Sequence); 3) SEQUENCE:通过序列产生主键,还可以进一步通过@SequenceGenerator 标注来指定 更详细的生产方式,MySql 不支持这种方式(注:@SequenceGenerator 用法示例: @GeneratedValue(strategy=GenerationType.SEQUENCE) @SequenceGenerator(name="SEQ_TEST", // 此生成器的别名 sequenceName="User_SEQ",// 对应的 Oracle sequence 的名字 allocationSize=25) ); 4) TABLE:通过表产生主键,框架借由表模拟序列(sequence)产生主键,使用该策略可 以使应用更易于数据库移植。不同的 JPA 厂商所默认生成的表名是不同的,如 OpenJPA 生成 openjpa_sequence_table 表,Hibernate 生成一个 hibernate_sequences 表,而 TopLink 则生成 sequence 表。这些表都具有一个序列名和对应值两个字段,如 SEQ_NAME 和 SEQ_COUNT。 另外还有一个重要的属性就是 generator,它可以更进一步制定主键生成器所采用的参 数,例如 sequence 表的表名可以这样定义:@GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ") 。同样的也可以用于 TABLE 方式的生成器上: @GeneratedValue(strategy=TABLE, generator="CUST_GEN")。 @Column:属性或者变量对应的表字段。一般来说我们并不需要指定表字段的类型, 因为 JPA 会根据反射从实体属性中获取类型;如果是字符串类型,我们可以指定字段长度, 以便可以自动生成 DDL 语句;还可以指定一些其它的属性例如是否唯一(unique),是否可 以为空(nullable),是否可以插入和更新等等(insertable 和 updatable);name 属性指定 了它对应于数据库中的列名。如果是时间类型,一般还需要指定精度,用@Temporal 来进 行标注。同样的这个标注也不是必须的,如果没有写任何参数的话,它的名字和类型都和当 前标注的属性或者变量的名字和类型相同