1、第8章JPA 框架第 8 章JPA 框架8.1 ORM和和JPA8.2 JPA及其开发环境的搭建及其开发环境的搭建 8.3 实体实体Bean和数据表的建立和数据表的建立 8.4 JPA的的API函数函数8.5 查询语言查询语言JPQL8.6 实体关联与联合主键实体关联与联合主键 第8章JPA 框架 8.1 ORM和和JPA1.对象/关系数据库映射(ORM)ORM的全称是Object/Relation Mapping,即对象/关系数据库映射。ORM只是一种规范,它定义了如何完成从面向对象编程语言到关系数据库的映射,可以当成是应用程序和数据库的桥梁。关系数据库通过ORM框架映射后,就可以直接使用面
2、向对象语言,把每个映射作为一个实体来访问,与面向对象的编程思想一致。第8章JPA 框架2.为什么需要ORM当我们使用一种面向对象的程序设计语言来进行应用开发时,从项目开始起一直采用的是面向对象分析、面向对象设计和面向对象编程,体验着面向对象编程的许多优势:封闭性,摈弃详细过程;继承性,在无需重新编写原有类的情况下扩展其功能;多态性,允许将子类类型的指针赋值给父类类型的指针;面向对象的建模、操作。第8章JPA 框架但是到了持久层访问数据库时,由于数据库的发展并未与程序设计语言同步,又必须重返关系数据库的访问方式。但是,关系数据库系统也有许多不能摈弃的优势:大量数据筛选、排序;数据库访问的并发、事
3、务性;高可靠性,能够运行很长时间而不会发生故障;集合数据连接操作、映射;高度的安全性,包括数据的备份、还原,以及数据库的约束、隔离。第8章JPA 框架面对这样的局面,采用ORM框架就成为一种必然。这里可以对ORM工具的作用做一个总结,就是把对持久化对象的操作,转换成对数据库的操作。但我们在采用ORM框架之后,应用程序不再直接访问底层数据库,而是以面向对象的方式来操作持久化对象(如CRUD操作等),而ORM框架则将这些面向对象的操作转换成底层的SQL操作。第8章JPA 框架3.JPA与其它ORM框架的关系目前ORM框架的产品非常多,包括Entity EJB、Hibernate、iBATIS、To
4、pLink等,很多公司还开发了自己的ORM框架来解决公司项目的持久化。每种ORM框架都有自己的语法,它们之间不能直接通用,这样对不同项目的开发十分不利。Sun公司为了简化现有Java EE和Java SE应用的对象持久化的开发工作,整合ORM技术,结束现在Hibernate、iBATIS、TopLink等ORM框架各自为营的局面,提出了新的JPA ORM规范。第8章JPA 框架1)JPA ORM规范JPA(Java Persistence API)作为Java EE 5.0平台标准的ORM规范,将得到所有Java EE服务器的支持。Sun这次吸取了之前EJB规范惨痛失败的经历,在充分吸收现有O
5、RM框架的基础上,得到了一个易于使用、伸缩性强的ORM JPA规范。JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它不属于EJB 3.0,它可以在Web应用甚至桌面应用中使用。第8章JPA 框架JPA的宗旨是为POJO提供持久化标准规范。由此可见,经过这几年的实践探索,能够脱离容器独立运行,方便开发和测试的理念已经深入人心了。目前Hibernate 3.2、TopLink 10.1.3以及OpenJpa都提供了JPA的实现。JPA通过JDK 5.0注解或XML描述对象关系表的映射关系,并将运行期的实体对象持久化到数据库中。第8章JPA 框架2)JPA主要技术JPA的总
6、体思想和现有Hibernate、TopLink、JDO等ORM框架大体一致。总的来说,JPA包括以下三方面的技术:ORM映射元数据:JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。第8章JPA 框架 JPA持久化API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,将开发者从繁琐的JDBC和SQL代码中解脱出来。查询语言:这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。第8章JPA 框架3)JPA与HibernateJPA不是一种新的
7、ORM框架,它的出现只用于规范现有的ORM技术,使得目前流行的ORM框架可以实现互相移植的功能,而不是对它们的替代。相反,在采用JPA开发时,仍然将使用这些框架,只是对于不同框架的运用可以不修改任何代码,真正做到低耦合、可扩展程序设计。第8章JPA 框架Hibernate是最流行的ORM框架之一,也是最早实现JPA的规范框架之一。JPA与Hibernate相比的优点在于:JPA大量使用annotation语法,其XML使得配置简化,但不能解决同步。JPA和Hibernate框架的关系可以看成是接口和实现的关系,但JPA只是Hibernate的一个子集,因此Hibernate有些功能JPA并不能
8、实现,如JPA不支持索引功能,没有缓存功能。因此在实际应用中两个框架可以结合使用,但凡是JPA能实现的功能都用JPA来完成,以此减少代码与Hibernate框架的耦合性。第8章JPA 框架8.2 JPA及其开发环境的搭建及其开发环境的搭建8.2.1 MySQL数据库的安装和使用数据库的安装和使用【步骤1】配置MySQL。MySQL数据库的安装过程非常简单,基本就是执行【Next】按钮操作。安装结束后,将打开如图8-1所示的【MySQL Server Instance Configuration Wizard】页面,来配置数据库运行时使用的参数。第8章JPA 框架图8-1 MySQL数据库配置第
9、8章JPA 框架如没有特殊情况,在下面的几个安装界面可直接点击【Next】按钮,使用默认配置,直到访问端口号界面出现,如图8-2所示。MySQL中有多个连接端口号可选,分别为3306、3307、3308等,但一般默认选择3306端口号。当出现MySQL默认字符集选择界面时,最好手动更换字符集为“utf8”,这样可以简化MySQL数据库数据写入和读出的中文化处理,如图8-3所示。第8章JPA 框架图8-2 MySQL连接端口配置图 第8章JPA 框架 图8-3 MySQL语言配置 第8章JPA 框架在如图8-4所示的界面中可以修改数据库访问密码,原始密码为安装数据库时设定的,一般默认为“1234
10、56”,用户名为“root”。在配置操作最后,将出现如图8-5所示的界面,说明安装的MySQL数据库配置成功,点击【Finish】按钮即可。第8章JPA 框架图8-4 MySQL密码配置图 第8章JPA 框架图8-5 MySQL数据库配置 第8章JPA 框架【步骤2】验证MySQL。配置成功后,可在MySQL的命令操作界面登录数据库,如图8-6所示。输入图8-4设定的验证密码后回车,就会显示输入命令行的操作符,说明登录成功。图8-6 MySQL命令符操作第8章JPA 框架【步骤3】安装注册SQL Manager For MySQL。与MySQL数据库配套的可视化软件很多,本书采用EMS的SQL
11、 Manager 2007 For MySQL,其安装很简单,所有操作按默认信息点击【Next】按钮直至完成。打开SQL Manager For MySQL软件,在菜单【Database】中选择【Create Database】,将出现如图8-7所示的界面,在【Database name】中填入新建的数据库名“jpatest”。第8章JPA 框架图8-7 新建数据库第8章JPA 框架点击【Next】按钮进入如图8-8所示的界面。Host name:表示主机名,此处选择localhost,在本地机器使用。Port:表示相应的连接端口,其值为设置MySQL数据库选择的端口号。User name:访
12、问MySQL数据库的用户名,“root”为MySQL默认的用户名。Password:访问MySQL数据库的密码,此处值为“123456”。Character Set:数据库服务器选用字符集,可在此选择“utf8”,但此处选择默认,因为在图8-3中已经定义过。第8章JPA 框架图8-8 连接MySQL数据库第8章JPA 框架点击【Next】按钮,将进入如图8-9所示的界面,生成新建数据库jpatest脚本。图8-9 新建数据库脚本生成第8章JPA 框架点击【Finish】按钮,将进入如图8-10所示的界面,进行数据库注册,这里只要求修改【Client charset】为“utf8”和【Font
13、charset】为“GB2312”,为简化数据库读出、写入操作的中文字符。第8章JPA 框架图8-10 注册数据库语言第8章JPA 框架经过以上一系列操作后,便完成了新建数据库jpatest的操作,这时可以在Database视图中看到如图8-11所示的界面。注意,必须双击【jpatest on localhost】才能看到分支目录,该界面和一般拥有可视化界面的数据库相类似,如微软的SQL SERVER,那么创建表、视图等的操作对大部分读者来说应该不成问题。第8章JPA 框架图8-11 MySQL命令符操作第8章JPA 框架8.2.2 JPA环境搭建环境搭建1.开发JPA依赖的JAR文件(以Hi
14、bernate框架实现)和Struts2框架的使用类似,在JPA环境搭建中首要完成的就是把开发所需的JAR文件加入到环境变量中。本书选用Hibernate来实现JPA框架,目前Hibernate最新的产品版本为3.3.2GA,因此需要的JAR文件来源为:第8章JPA 框架(1)Hibernate核心包(hibernate-distribution-3.3.2.GA-dist.zip)。在Hibernate核心包中需要8个JAR文件,以解压缩包为根目录,所需JAR文件相对于根目录的文件为:hibernate3.jar;libbytecodecglibcglib-2.2.jar;librequir
15、ed*.jar(包含6个JAR文件)。第8章JPA 框架(2)Hibernate注解包(hibernate-annotations-3.4.0.GA.zip)。在Hibernate注解包中需要3个JAR文件,以解压缩包为根目录,所需JAR文件相对于根目录的文件为:Hibernate-annotations.jar;libejb3-persistence.jar;libHibernate-commons-annotations.jar。第8章JPA 框架(3)Hibernate针对JPA的实现包(hibernate-entitymanager-3.4.0.GA.zip)。在Hibernate针对
16、JPA的实现包中需要3个JAR文件,以解压缩包为根目录,所需JAR文件相对于根目录的文件为:hibernate-entitymanager.jar;libtestlog4j.jar;libtestslf4j-log4j12.jar。第8章JPA 框架2.在MyEclipse搭建JPA环境准备好以上14个JAR文件后,还需要连接MYSQL数据库的驱动程序,本书采用mysql-connector-java-5.1.6-bin.jar。在MyEclipse7.0中搭建JPA环境的步骤如下:【步骤1】新建工程ch08。本章是对JPA基本知识的讲解,因此不涉及Web界面的操作,可以新建Java工程,但为
17、了与建立网站知识相吻合,选择新建Web工程ch08。第8章JPA 框架【步骤2】复制JAR文件。把以上14个JAR文件和mysql-connector-java-5.1.6-bin.jar复制到WebRoot/WEB-INF/lib文件夹下即可。【步骤3】JPA的配置文件。JPA规范要求在类路径classes的META-INF目录下放置persistence.xml文件,这就意味着在ch08工程的src目录下要新建META-INF文件夹,然后在此文件夹下建立persistence.xml文件,注意文件名是规定好的。配置模板如下:第8章JPA 框架 org.hibernate.ejb.Hiber
18、natePersistence 第8章JPA 框架 第8章JPA 框架上面的【步骤2】和【步骤3】可以使用MyEclipse自带的【add JPA Capabilities】方式来完成,但导入的包不能保证是最新的,所以建议读者使用自己复制包的方式来完成JPA环境的搭建。第8章JPA 框架3.JPA配置文件中元素的含义元素persistence-unit的配置十分重要,其name属性的值为sspu,表示所有包名为sspu的实体都使用这个持久化单元的数据库配置来完成CRUD操作;属性transaction-type表示事务类型,有RESOURCE_LOCAL(本地事务)和JTA(全局事务)两个值,
19、我们一般的JDBC都是本地事务,全局事务大多用于不同数据库之间的操作,如Oracle和DB2之间数据的互操作。第8章JPA 框架org.hibernate.ejb.HibernatePersistence元素provider表示使用何种ORM框架来实现JPA,此处显然是hibernate。元素properties中的所有属性用来实现MySQL数据库的连接,这里只列出一般配置的属性,其中各属性的含义为:hibernate.dialect:使用的数据库方言,此处指明是MySQL方言。hibernate.connection.driver_class:数据库驱动类,此处选用较新的驱动类com.mys
20、ql.jdbc.Driver。第8章JPA 框架 hibernate.connection.url:数据库连接的URL,MySQL的URL格式为jdbc:subName:/hostname:port/DatabaseName,此处把数据库jpatest作为sspu持久化单元的相关数据库。hibernate.connection.username:连接操作的数据库用户名。hibernate.connection.password:连接操作的数据库密码。第8章JPA 框架 hibernate.hbm2ddl.auto:可以帮助用户实现正向工程,即由java代码生成数据库脚本,进而生成具体的表结构。
21、它有三个值:create表示根据实体类来生成表,但是每次运行都会删除上一次的表,重新生成表,哪怕两次没有任何改变;create-drop表示根据model类生成表,但是一旦EntityManagerFactory关闭,表就自动删除;update为最常用的属性,也根据model类来生成表,即使表结构改变了,表中的行仍然存在,而且会进行同步更新操作。第8章JPA 框架8.3 实体实体Bean和数据表的建立和数据表的建立8.3.1 面向领域建模和面向领域建模和UML建模建模1.DSM和UML方法比较使用UML,我们会首先在一个Use case图中表达该程序的外部需求,然后应用UML的类图和顺序图、状
22、态图等进行内部设计。显然,当我们深入到细节设计部分时,会有多种可能的设计方案,不同的开发者可能选择不同的方案,这些方案未见得哪个就比哪个好多少。第8章JPA 框架UML支持这些不同的设计,在得到正确的设计这一点上不能提供什么帮助。毕竟UML不知道关于这个应用的任何知识。要得到正确的设计,开发者需要了解问题域(电话),构建该应用程序的平台(例如Symbian)以及如何正确地画UML。最后,再用UML图进行设计之后,便进入了写代码的阶段。自然地,我们希望可以从设计中生成尽可能多的代码,但UML却不能做到这一点。UML是一个通用的建模语言,这意味着不管你设计什么样的软件,都可以用UML。第8章JPA
23、 框架也正是因为这一点,UML的发明者们需要做出很多妥协,来让UML可以建模的领域十分广阔但却不能精于某一方面。结果就是:开发人员可以从UML中生成的有效代码很少。在所有的建模完成之后,我们对系统有了全面的理解,但是没有可运行的程序。不可避免地,在编码实现和测试阶段,我们会对设计有一些修改,但通常大家都懒得去更新涉及到的所有模型,这样模型就过时了。第8章JPA 框架DSM认为,如果他们用的符号系统是面向目前开发的问题领域的,则开发者可以更有效地进行软件设计。DSM支持开发者描述需要的各个方面,而且也不多描述一些无用的信息。这些符号体系的提供以及到代码的映射由公司的专家负责,其余的开发人员就可以
24、从他们的设计中自动生成完全的高质量的代码。当然,这需要DSM工具的支持,这些工具将支持DSM语言的定义、使用和维护。这些工具实际上已经有了,Microsoft、MetaCase和Xactium以及诸如Eclipse GMF的框架等,都有这方面的支持。第8章JPA 框架使用电话会议这个问题域所特别定制的领域特定语言,我们可以创建一个更有表现力的设计,中间使用的都是领域特定的概念,例如短信、占线之类,每个都会有一些规则。使用DSM,我们可以关注于寻找用领域概念表示的解决方案,而不是代码。最终的描述捕获了这个程序所有需要的静态和行为方面,可以完全从模型生成最后的程序。这和前面我们看到的UML模型是完
25、全不同的。第8章JPA 框架考虑从设计到编码的整个周期,DSM的实现不需要额外的投资,相反还会节省开发的资源。过去,所有的开发人员都使用问题域的概念来工作,然后手工将这些工作映射到实现对应的概念上去。而在这些开发人员中,有些人做得好些,有些人则做得差一些。因此,现在让有经验的开发人员来定义这些概念和对应的映射,其他人只需按照定义编码即可。如果某个专家写好了代码生成器,用它生成的代码比普通开发者手工写出来的代码质量甚至还好一些。第8章JPA 框架2.DSM与JPA实体建模在8.3.2节中我们会通过先建立实体Bean,对每个属性进行数据注解约束,产生数据表结构,然后使用JPA的API函数进行数据的
26、CRUD操作。只要实体Bean发生变动,相应的数据表也会发生变动。这样比使用Hibernate进行映射配置要节省很多时间,而且促使开发者使用面向对象的方式来考虑数据实体的建立。第8章JPA 框架8.3.2 实体实体Bean的建立及的建立及JUnit测试测试下面我们要用相反的方式来实现这种映射,就是先在实体Bean中定义好表结构,然后根据表结构定义在数据库中自动生成对应的数据表。第8章JPA 框架 必须使用javax.persistence.Entity注解或者在XML映射文件中有对应的元素。必须具有一个不带参数的构造函数,类不能声明为final,方法和需要持久化的属性也不能声明为final。如
27、果游离状的实体对象需要以值的方式进行传递,如通过Session bean的远程业务接口传递,则必须实现Serializable接口。需要持久化的属性,其访问修饰符不能是public,它们必须通过实体类方法进行访问。第8章JPA 框架1.创建实体Student举例如下,有一个学生表,表名为studenttable,含有两个字段:id:学生id,整型,主键,且为自增长字段;name:学生姓名,字符串类型。以上是学生表的最简单结构,在下文的讲解中我们会对这个表逐渐增加字段和字段约束。现在让我们看看在JPA中如何实现这个简单实体Bean,并在数据库中生成表student。第8章JPA 框架在src目录
28、下新建com.sspu.bean.Student.java。注意,实体Student一定要放在包含sspu子包的包目录下,这是因为在JPA的配置文件中我们定义了实体单元的名字为“sspu”。其代码如下:package com.sspu.bean;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;Entity Table(name=studenttable)第8章JPA
29、 框架public class Student/Id GeneratedValue(strategy=GenerationType.AUTO)private Integer id;private String name;public Student()public Student(String name)this.name=name;Id GeneratedValue(strategy=GenerationType.AUTO)第8章JPA 框架 public Integer getId()return id;public void setId(Integer id)this.id=id;pub
30、lic String getName()return name;public void setName(String name)this.name=name;第8章JPA 框架1)EntityEntity将领域对象标注为一个实体,表示需要保存到数据库中,默认情况下类名即为表名。若要修改表名,可通过Table(name=“studenttable”)显式指定表名,表示Student实体保存到studenttable表中。2)IdId注解对应的属性是表的主键,如所示,id属性为表studenttable的主键。第8章JPA 框架3)GeneratedValueGeneratedValue是主键的产
31、生策略,通过strategy属性指定。默认情况下,JPA自动选择一个最适合底层数据库的主键生成策略,如SQL Server对应identity,MySQL对应auto increment。在javax.persistence.GenerationType中定义了以下几种可供选择的策略:IDENTITY:表自增长字段,注意Oracle数据库不支持这种方式。AUTO:JPA自动选择合适的策略,是默认选项。第8章JPA 框架 SEQUENCE:通过序列产生主键,通过SequenceGenerator注解指定序列名,MySQL数据库不支持这种方式。TABLE:通过表产生主键,框架借由表模拟序列产生主键
32、,该策略更易于数据库移植。不同的JPA实现商生成的表名是不同的,如OpenJPA生成openjpa_sequence_table表,Hibernate生成一个hibernate_sequences表,而TopLink则生成sequence表。这些表都具有一个序列名和对应值两个字段,如SEQ_NAME和SEQ_COUNT。第8章JPA 框架2.使用JUnit测试实体完成实体类编码后,可以使用JUnit4工具来进行验证,同时在数据库jpatest中生成对应的关系数据表studenttable。步骤如下:【步骤1】建立JUnit测试类。使用JUnit来验证annotation注释是否正确,新建jun
33、it.test.StudentTest.java,选择src目录,点击右键,在弹出的快捷菜单中选中【New】下的【Other】子菜单,如图8-12所示。第8章JPA 框架图8-12 新建JUnit测试类1第8章JPA 框架选择【JUnit Test Case】来新建测试文件,点击【Next】按钮,进入如图8-13所示的页面。注意,修改图中椭圆标注的地方,运用JUnit4环境。点击【Finish】按钮,出现如图8-14所示的页面,提示加入JUnit4框架环境,点击【OK】按钮后,在ch08工程的环境变量中便增加了JUnit 4/junit.jar的包。第8章JPA 框架图8-13 新建JUnit
34、测试类2第8章JPA 框架图8-14 加入JUnit环境第8章JPA 框架【步骤2】完善JUnit测试类。在新建的junit.test.StudentTest.java文件中完善代码如下:package junit.test;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;import org.junit.BeforeClass;import org.junit.Test;public class StudentTest BeforeClass第8章JPA 框架 public
35、static void setUpBeforeClass()throws Exception Test public void save()EntityManagerFactory factory=Persistence.createEntityManagerFactory(“sspu”);factory.close();第8章JPA 框架在测试方法save中,先创建javax.persistence.EntityManagerFactory持久化工厂,其createEntityManagerFactory方法的参数“sspu”就是在搭建JPA环境时persistence.xml文件中元素pe
36、rsistence-unit属性name的值。持久化工厂里把sspu子包中的所有实体都与数据库建立映射,也就是说,所有实体都会在数据库jpatest中生成相对应的数据表和符合条件的字段。第8章JPA 框架【步骤3】运行测试方法save。测试类的执行方式和一般的Java类的执行方式不同,它可以对类中的每个测试方法进行单独测试验证。如图8-15所示,在【Outline】界面中选中要执行的测试方法save,右键选择【Run As】,然后选择【JUnit Test】运行测试。如果直接选择类StudenTest进行测试,则会测试StudenTest中的所有方法。第8章JPA 框架图8-15 运行测试方法
37、第8章JPA 框架测试运行结果时,可查看【JUnit】视图的进度条,如图8-16所示,图中所示为运行成功的绿色进度条。如果运行不成功,则为红色进度条。可在【Failure Trace】视图中查看错误提示,并进行纠错。第8章JPA 框架图8-16 测试成功界面图 第8章JPA 框架图8-17 studenttable表 第8章JPA 框架save方法运行成功后,通过JPA映射可在数据库jpatest中生成数据表studenttable,如图8-17所示。这里必须注意,如果运行成功而没看到表,则请刷新数据库jpatest。数据表studenttable根据实体Student的设置生成两个字段:id
38、和name。从图8-18中的【Fields】视图可以看到id为整型,name为字符串类型,并且从8-19中的【Indices】视图可以看出id为主键,这些都符合实体Student的注释要求,同时也符合实例的字段要求。第8章JPA 框架图8-18 studenttable表字段第8章JPA 框架图8-19 studenttable表主键图 第8章JPA 框架【步骤4】测试增加数据。往save方法中增加如下带黑体部分的代码:Test public void save()EntityManagerFactory factory=Persistence.createEntityManagerFacto
39、ry(“sspu”);EntityManager em=factory.createEntityManager();em.getTransaction().begin();/开始事务第8章JPA 框架 em.persist(new Student(“张三”);em.persist(new Student(“李四”);em.persist(new Student(“王五”);em.getTransaction().commit();em.close();factory.close();第8章JPA 框架代码中应用程序通过javax.persistence.EntityManagerFactory
40、的createEntityManager来创建EntityManager实例;当对数据库进行更新操作时,需要开启事务,使用代码来实现;代码中使用persist()方法来将实体的数据保存到数据库中,以上代码就是在数据表中添加三条数据;代码表示执行事务,就是把事务中进行的各项操作在数据表中实际执行。第8章JPA 框架重新测试save()方法,刷新数据表studenttable的【Data】视图,就是点击图8-20中所示的工具,可以看到生成三条数据,其中id的值明显表示id字段为自增长字段。第8章JPA 框架图8-20 studenttable表增加数据第8章JPA 框架8.3.3 常用特殊常用特殊
41、annotation注释注释1.修改实体Student为了介绍JPA对表字段常用的注释,对实体Student进行如下修改:【步骤1】增加属性及注释。在com.sspu.bean.Student.java中增加属性及注释,具体注释的含义在下文一一讲解。代码如下:第8章JPA 框架 Column(length=10,nullable=false,name=studentName)private String name;Temporal(TemporalType.DATE)private Date birthday;Enumerated(EnumType.STRING)Column(length=5
42、,nullable=false)private Gender gender=Gender.MEN;Lob 第8章JPA 框架 private String info;Lob Basic(fetch=FetchType.LAZY)private Byte file;Transient private String imagepath;/省略get/set方法第8章JPA 框架【步骤2】新建Gender类。由于在实体Student中使用了性别定义的Gender类,Gender类中定义了两个枚举值MEN和WOMEN,供实体Student的属性gender选择,因此新建com.sspu.bean.Ge
43、nder.java类,其代码如下:package com.e06.bean;public enum Gender MEN,WOMEN第8章JPA 框架2.注释解析1)Column注释Column约束属性对应的表字段,可以定义字段名字、长度、可否为空、是否允许更新、是否唯一等,用来自动生成DDL语句。如实体Student的代码中所示,约束属性name对应的数据表srudenttable中的字段为studentName,字符串长度不大于10,不允许为空。注意,这里并不需要指定表字段的类型,因为JPA会根据反射从实体属性中获取类型。第8章JPA 框架2)Temporal注释Temporal约束日期型
44、数据的时间类型。在javax.persistence.TemporalType枚举中定义了三种时间类型:DATE:等于java.sql.Date,只显示日期;TIME:等于java.sql.Time,只显示时间;TIMESTAMP:等于java.sql.Timestamp,既显示日期又显示时间。第8章JPA 框架3)Enumerated在javax.persistence.EnumType枚举中定义了两种枚举数据显示类型:ORDINAL:在数据库中显示枚举类中值的相对位置0,1,2,3;STRING:在数据库中显示枚举类中定义的具体值。如实体Student的代码中所示,约束属性gender对应
45、的数据表studenttable中的字段gender显示的值为枚举类Gender中的具体值MEN和WOMEN,且长度不大于5,不允许为空。第8章JPA 框架4)Lob和Basic注释Lob和Basic经常成对使用。Lob一般用来约束LONGEXT或LONGBLOB类型的字段,代表此字段数据较大;而对于超大字段,在数据持久化中一般要做延迟加载的处理,使用Basic指定Lob类型数据的获取策略。在javax.persistence.FetchType枚举中定义了两种枚举数据显示类型:第8章JPA 框架 EAGER:表示非延迟加载;LAZY:表示延迟加载。如实体Student的代码中所示,约束属性i
46、nfo(备注)和file(文件)对应的数据表studenttable中的字段info类型为LONGEXT,可以定义的数据信息较多,比一般的VARCHAR类型更加符合备注字段的定义;对应的字段file类型为LONGBLOB。第8章JPA 框架代码Basic(fetch=FetchType.LAZY)一般用于对大数据(超过1 M)设置延迟初始化,那么新建实体类时此属性不会被加载,只有访问其get方法时才会被加载,这样可以提高数据访问速度。第8章JPA 框架5)Transient如果我们不希望将某个属性持久化到数据表中,则可以通过Transient注解显式指定,此属性就不会同步定义到数据库表字段中。
47、如实体Student的代码中所示,约束的属性imagepath不会在数据表studenttable中生成字段imagepath。第8章JPA 框架3.运行测试把jpatest数据库中的studenttable表删除,重新运行测试类junit.test.StudentTest.java中的save()方法,刷新数据库(注意,如果不刷新,则看不到新生成的表),将生成新的studenttable表结构(见图8-21)和表数据(见图8-22)。第8章JPA 框架图8-21 studenttable表结构第8章JPA 框架图8-22 studenttable表数据第8章JPA 框架图8-22为使用构造函
48、数新建的记录。我们还可以自定义增加一条记录,如在测试类中增加测试方法insertOne(),代码如下:Test public void insertOne()EntityManagerFactory factory=Persistence.createEntityManagerFactory(sspu);EntityManager em=factory.createEntityManager();em.getTransaction().begin();Student a=new Student(陆六);第8章JPA 框架/设置时间 Calendar c=Calendar.getInstance
49、();/注意8表示9月 c.set(1976,8,19);Date d=new Date(c.getTimeInMillis();a.setBirthday(d);/设置性别 a.setGender(Gender.WOMEN);em.persist(a);em.getTransaction().commit();em.close();factory.close();第8章JPA 框架运行此测试方法,结果如图8-23所示。图8-23 studenttable表新增数据第8章JPA 框架8.3.4 XML元数据的使用元数据的使用除了使用注解提供元数据信息外,JPA也允许我们通过XML提供元数据信息
50、。按照JPA的规范,如果提供了XML元数据描述信息,则它将覆盖实体类中的注解元数据信息。XML元数据信息以orm.xml命名,放置在类路径的META-INF目录下。在ch08工程的src/META-INF目录下建立文件orm.xml,代码如下:第8章JPA 框架第8章JPA 框架com.sspu.bean 第8章JPA 框架 DATE 第8章JPA 框架 ORDINAL 第8章JPA 框架 第8章JPA 框架orm.xml中的配置与注解中的内容基本一致,仅改变了代码、三个地方,即让数据表名为“student”;属性name对应的字段名改为“name”,长度改为20;字段gender的显示方式改