ITjob就业培训java教材34_第1页
ITjob就业培训java教材34_第2页
ITjob就业培训java教材34_第3页
ITjob就业培训java教材34_第4页
ITjob就业培训java教材34_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

ITjob就业培训java教材34ITjob就业培训java教材34ITjob就业培训java教材34xxx公司ITjob就业培训java教材34文件编号:文件日期:修订次数:第1.0次更改批准审核制定方案设计,管理制度第三十四章:Hibernate基础学习目标理解ORM机制理解Hibernate的工作原理Hibernate的配置和对象-映射文件理解对象持久化Hibernate简介Hibernate是Java应用和关系数据库之间的桥梁,它负责Java对象关系数据之间的映射。Hibernate内部封装了通过JDBC访问数据库的操作,向上层应用提供了面向对象的数据访问API。在Java应用中使用Hibernate包含以下步骤。(1)创建Hibernate的配置文件。(2)创建持久化类。(3)创建对象-关系映射文件。(4)通过HibernateAPI编写访问数据库的代码。建立简单的Hibernate应用本章通过一个简单的例子customerApp应用,演示如何运用Hibernate来访问关系数据库。customerApp应用的功能非常简单:通过Hibernate保存、更新、删除、加载以及查询Customer对象。创建Hibernate的配置文件Hibernate从其配置文件中读取和数据库连接有关的信息,这个配置文件应该位于应用的classpath中。Hibernate的配置文件有两种形式:一种是XML格式的文件;还有一种是Java属性文件,采用“健=值”的形式。下面介绍如何以Java属性文件的格式来创建Hibernate的配置文件。这种配置文件的默认文件名为。的内容如下:==true以上文件包含了一系列属性及其属性值,Hibernate将根据这些属性来连接数据库,本例为连接MySQL数据库的配置代码。下表对以上文件中的所有属性做了描述。属性描述SQL指定数据库使用的方言指定数据库的驱动程序指定连接数据库的指定连接数据库的用户名指定连接数据库的口令如果为true,表示在程序运行时,会在控制台输出SQL语句,这有利于跟踪Hibernate的运行状态。默认为false。在应用开发和测试阶段,可以把这个属性设为true,以便跟踪和调试应用程序,在应用发布阶段,应该把这个属性设为false,以便减少应用的输出信息,提高运行性能。Hibernate能够访问多种关系数据库,如MySQL、Oracle和Sybase等。尽管多数关系数据库都支持标准的SQL语言,但是它们往往还有各自的SQL方言,就象不同地区的人既能说标准的普通话,还能讲各自的方言一样。属性用于指定被访问数据库使用的SQL方言,当Hibernate生成SQL查询语句,或者使用native对象标识符生成策略时,都会参考本地数据库的SQL方言。创建持久化类持久化类是指其实例需要被Hibernate持久化到数据库中的类。持久化类通常都是域模型中的实体域类。持久化类符合JavaBean的规范,包含一些属性,以及与之对应的getXXX()和setXXX()方法。以下定义了一个名为Customer的持久化类。packageimportimportimportpublicclassCustomerimplementsSerializable{privateLongid;privateStringname;privateStringemail;privateStringpassword;privateintphone;privatebooleanmarried;privateStringaddress;privatecharsex;privateStringdescription;privatebyte[]image;privateDatebirthday;privateTimestampregisteredTime;publicCustomer(){}publicLonggetId(){returnid;}publicvoidsetId(Longid){=id;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){=name;}quals())的结果是true,就表示customerA和customerB对象指的是同一个客户,它们和CUSTOMERS表中的同一条记录对应。Hibernate要求持久化类必须提供一个不带参数的默认构造方法,在程序运行时,Hibernate运用Java反射机制,调用方法来构造持久化类的实例。如果对这个持久化类使用延迟检索策略,为了使Hibernate能够在运行时为这个持久化类创建动态代理,要求持久化类的默认构造方法的访问级别必须是public或protected类型,而不能是default或private类型。在Customer类中没有引入任何HibernateAPI,Customer类不需要继承Hibernate的类,或实现Hibernate的接口,这提高了持久化类的独立性。如果日后要改用其他的ORM产品,比如由Hibernate改为OJB,不需要修改持久化类的代码。创建数据库Schema在本例中,与Customer类对应的数据库表名为CUSTOMERS,它在MySQL数据库中的DDL定义如下:createtableCUSTOMERS(IDbigintnotnullprimarykey,NAMEvarchar(15)notnull,EMAILvarchar(128)notnull,PASSWORDvarchar(8)notnull,PHONEint,ADDRESSvarchar(255),SEXchar(1),IS_MARRIEDbit,DESCRIPTIONtext,IMAGEblob,BIRTHDAYdate,REGISTERED_TIMEtimestamp);CUSTOMERS表有一个ID字段,它是表的主键,它和Customer类的id属性对应。CUSTOMERS表中的字段使用了各种各样的SQL类型,参见下表。字段名SQL类型说明IDBIGINT整数,占8字节,取值范围为:-2^63~2^63-1NAMEVARCHAR变长字符串,占0~255个字节SEXCHAR定长字符串,占0~255个字节IS_MARRIEDBIT布尔类型DESCRIPTIONTEXT长文本数据,占0~65535255字节。如果字符串长度小于255,可以用VARCHAR或CHAR类型来表示。如果字符串长度大于255,可以定义为TEXT类型。IMAGEBLOB二进制长数据,占0~65535字节,BLOB是BinaryLargeObject的缩写。IMAGE在本例中,字段用来存放图片数据BIRTHDAYDATE代表日期,格式为“YYYY-MM-DD”REGISTERED_TIMETIMESTAMP代表日期和时间,格式为“YYYYMMDDHHMMSS”创建对象-关系映射文件Hibernate采用XML格式的文件来指定对象和关系数据之间的映射。在运行时,Hibernate将根据这个映射文件来生成各种SQL语句。在本例中,将创建一个名为的文件,它用于把Customer类映射到CUSTOMERS表,这个文件应该和文件存放在同一个目录下。以下为文件的源代码。<xmlversion=""><!DOCTYPEhibernate-mappingPUBLIC"-java]Errorreadingresource:mypack/at把Customer持久化类映射到CUSTOMERS表文件用于映射Customer类。如果需要映射多个持久化类,那么既可以在同一个映射文件中映射所有类,也可以为每个类创建单独的映射文件,映射文件和类同名,扩展名为“”。后一种做法更值得推荐,因为在团队开发中,这有利于管理和维护映射文件。<class>元素指定类和表的映射,它的name属性设定类名,table属性设定表名。以下代码表明和Customer类对应的表为CUSTOMERS表:<classname=""table="CUSTOMERS">如果没有设置<class>元素的table属性,Hibernate将直接以类名作为表名,也就是说,默认情况下,与类对应的表为Customer表。<class>元素包含一个<id>子元素以及多个<property>子元素。<id>子元素设定持久化类的OID和表的主键的映射。以下代码表明Customer类的id属性和CUSTOMERS表中的ID字段对应。<idname="id"column="ID"type="long"><generatorclass="increment"/></id><id>元素的<generator>子元素指定对象标识符生成器,它负责为OID生成惟一标识符。<property>子元素设定类的属性和表的字段的映射。<property>子元素主要包括name、type、column和not-null属性。1.<property>元素的name属性<property>元素的name属性指定持久化类的属性的名字。2.<property>元素的type属性<property>元素的type属性指定Hibernate映射类型。Hibernate映射类型是Java类型与SQL类型的桥梁。3.<property>元素的not-null属性如果<property>元素的not-null属性为true,表明不允许为null,默认为false。例如以下代码表明不允许Customer类的name属性为null:<propertyname="name"column="NAME"type="string"not-null="true"/>Hibernate在持久化一个Customer对象时,会先检查它的name属性是否为null,如果为null,就会抛出以下异常:not-nullpropertyreferencesanullortransientvalue:如果数据库中CUSTOMERS表的NAME字段不允许为null,但在映射文件中没有设置not-null属性:<propertyname="name"column="NAME"type="string"/>那么Hibernate在持久化一个Customer对象时,不会先检查它的name属性是否为null而是直接通过JDBCAPI向CUSTOMERS表插入相应的数据,由于CUSTOMERS表的NAME字段设置了notnull约束,因此数据库会抛出错误:708ERRORJDBCExceptionReporter:58-Generalerror,messagefromserver:"Column'NAME'cannotbenull"4.<property>元素的column属性<property>元素的column属性指定与类的属性映射的表的字段名。以下代码表明和address属性对应的字段为ADDRESS字段:<propertyname="address"column="ADDRESS"type="string"/>如果没有设置<property>元素的column属性,Hibernate将直接以类的属性名作为字段名,也就是说,默认情况下,与Customer类的address属性对应的字段为address字段。<property>元素还可以包括<column>子元素,它和<property>元素的column属性一样,都可以设定与类的属性映射的表的字段名。以下两种设置方式是等价的:<propertyname="address"column="ADDRESS"type="string"/>或者<propertyname="address"type="string"><columnname="ADDRESS"/></property><property>元素的<column>子元素比column属性提供更多的功能,它可以更加详细的描述表的字段。例如以下<column>子元素指定CUSTOMERS表中的NAME字段的SQL类型为varchar(15),不允许为null,并且为这个字段建立了索引:<propertyname="name"type="string"><columnname="NAME"sql-type="varchar(15)"not-null="true"index="idx_name"/></property>通过HibernateAPI操纵数据库Hibernate对JDBC进行了封装,提供了更加面向对象的API。以下两图对比了直接通过JDBCAPI以及通过HibernateAPI来访问数据库的两种方式。以下示例的BusinessService类演示了通过HibernateAPI对Customer对象进行持久化的操作。packageimport.*;importimportimport.*;importimportimport.*;publicclassBusinessService{publicstaticSessionFactorysessionFactory;/**初始化Hibernate,创建SessionFactory实例*/static{try{publicvoidsaveCustomer(Customercustomer)throwsException{……}/**按照OID加载一个Customer对象,然后修改它的属性*/publicvoidloadAndUpdateCustomer(Longcustomer_id,Stringaddress)throwsException{……}/**删除所有的Customer对象*/publicvoiddeleteAllCustomers()throwsException{Sessionsession=();Transactiontx=null;try{tx=();("fromCustomerasc");();}catch(Exceptione){if(tx!=null){();}throwe;}finally{();}}/**选择向控制台还是动态网页输出Customer对象的信息*/privatevoidprintCustomer(ServletContextcontext,OutputStreamout,Customercustomer)throwsException{if(outinstanceofServletOutputStream)printCustomer(context,(ServletOutputStream)out,customer);elseprintCustomer((PrintStream)out,customer);}/**把Customer对象的信息输出到控制台,如DOS控制台*/privatevoidprintCustomer(PrintStreamout,Customercustomer)throwsException{……}/**把Customer对象的信息输出到动态网页*/privatevoidprintCustomer(ServletContextcontext,ServletOutputStreamout,Customercustomer)throwsException{……}publicvoidtest(ServletContextcontext,OutputStreamout)throwsException{Customercustomer=newCustomer();("Tom");");("("1234");();("Shanghai");('M');("Iamveryhonest.");etResourceAsStream("");byte[]buffer=newbyte[()];(buffer);(buffer);1980-05-06Beijing();}}以上例子演示了通过HibernateAPI访问数据库的一般流程。首先应该在应用的启动阶段对Hibernate进行初始化,然后就可以通过Hibernate的Session接口来访问数据库。Hibernate的初始化BusinessService类的静态代码块负责Hibernate的初始化工作,如读取Hibernate的配置信息以及对象-关系映射信息,最后创建SessionFactory实例。当JVM(Java虚拟机)加载BusinessService类时,会执行该静态代码块。初始化过程包括如下步骤。(1)创建一个Configuration类的实例,Configuration类的构造方法把默认文件路径下的配置文件中的配置信息读入到内存:Configurationconfig=newConfiguration();(2)调用Configuration类的addClass方法:;该方法把默认文件路径下的文件中的映射信息读入到内存中。(3)调用Configuration类的buildSessionFactory()方法:sessionFactory=();该方法创建一个SessionFactory实例,并把Configuration对象包含的所有配置信息拷贝到SessionFactory对象的缓存中。SessionFactory代表一个数据库存储源,如果应用只有一个数据库存储源,那么只需创建一个SessionFactory实例。当SessionFactory对象创建后,该对象不和Configuration对象关联。因此如果再修改Configuration对象包含的配置信息,不会对SessionFactory对象有任何影响。访问Hibernate的Session接口初始化过程结束后,就可以调用SessionFactory实例的openSession()方法来获得Session实例,然后通过它执行访问数据库的操作。Session接口提供了操纵数据库的各种方法,如:save()方法:把Java对象保存数据库中。update()方法:更新数据库中的Java对象。delete()方法:把Java对象从数据库中删除。load()方法:从数据库中加载Java对象。find()方法:从数据库中查询Java对象。Session是一个轻量级对象。通常将每一个Session实例和一个数据库事务绑定,也就是说,每执行一个数据库事务,都应该先创建一个新的Session实例。如果事务执行中出现异常,应该撤销事务。不论事务执行成功与否,最后都应该调用Session的close()方法,从而释放Session实例占用的资源。以下代码演示了用Session来执行事务的流程,其中Transaction类用来控制事务。Sessionsession=();Transactiontx;try{.Shanghai,values(1,'Tom',','1980-05-06',null)在test()方法中并没有设置Customer对象的id属性,Hibernate会根据映射文件的配置,采用increment标识符生成器自动以递增的方式为OID赋值。在文件中相关的映射代码如下:<idname="id"column="ID"type="long"><generatorclass="increment"/></id>在test()方法中也没有设置Customer对象的registeredTime属性,因此在以上insert语句中,REGISTERED_TIME字段的值为null。但由于REGISTERED_TIME字段的SQL类型为TIMESTAMP类型,如果insert语句没有为TIMESTAMP类型的字段赋值,底层数据库会自动把当前的系统时间赋值给TIMESTAMP类型的字段。因此,执行完以上insert语句后,REGISTERED_TIME字段的值并不为null,而是插入该记录时的系统时间。2.findAllCustomers()方法该方法调用Session的find()方法,查询所有的Customer对象。tx=();Listcustomers=("fromCustomerascorderbyasc");for(Iteratorit=();();){printCustomer(context,out,(Customer)());}();Session的find()方法有好几种重载形式,本例中传递的是字符串参数“fromCustomerascorderbyasc”,它使用的是Hibernate查询语言。运行()方法时,Hibernate执行以下SQL语句:select*fromCUSTOMERSorderbyNAMEasc;3.loadAndUpdateCustomer()方法该方法调用Session的load()方法,加载Customer对象,然后再修改Customer对象的属性。tx=();Customerc=(Customer),customer_id);(address);();以上代码先调用Session的load()方法,它按照参数指定的OID从数据库中检索出匹配的Customer对象,Hibernate会执行以下SQL语句:select*fromCUSTOMERSwhereID=1;loadAndUpdateCustomer()方法接着修改Customer对象的address属性。那么,Hibernate会不会同步更新数据库中相应的CUSTOMERS表的记录呢答案是肯定的。Hibernate采用脏检查机制,按照内存中的Customer对象的状态的变化,来同步更新数据库中相关的数据,Hibernate会执行以下SQL语句:updateCUSTOMERSsetNAME="Tom",EMAIL=""…ADDRESS="Beijing"…尽管只有Customer对象的address属性发生了变化,但是Hibernate执行的update语句中会包含所有的字段。在BusinessService类的test()方法中按如下方式调用loadAndUpdateCustomer()方法:saveCustomer(customer);loadAndUpdateCustomer(),"Beijing");以上代码并没有直接给customer对象的id属性赋值,当执行saveCustomer(customer)方法时,Session的save()方法把customer对象持久化到数据库中,并自动为id属性赋值。4.printCustome

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论