第三四五六章文档.docx
- 文档编号:5011753
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:21
- 大小:43.92KB
第三四五六章文档.docx
《第三四五六章文档.docx》由会员分享,可在线阅读,更多相关《第三四五六章文档.docx(21页珍藏版)》请在冰豆网上搜索。
第三四五六章文档
第1、2章回顾
●软件分层分为物理分层和逻辑分层,通常我说的分层是软件分层
●ORM对象关系映射(Object-RelationMapping)模式指的是在单个组件中负责所有实体域对象的持久化,封装数据访问细节.是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中,hibernate就是采用这种映射方式,hibernate本身也是一种中间件
●软件模型:
概念模型、域模型、关系模型
●Hibernate配置文件、持久化类、对象---映射文件他们之前的关系
●SesssionFactory、Configuration、Session关系
●映射文件的主档类型定义(DTD)
第3章hbm2java和hbm2ddl工具
hbm2java:
根据映射文件自动生成Java源文件
Hbm2ddl:
根据映射文件自动生成数据库Schema
Xdicket:
根据带有XDoclet标记的Java源文件生成映射文件
Middlegen:
根据数据库Schema自动生成映射文件
本章的主要介绍内容是:
hbm2java:
和Hbm2ddl
3.1创建对象牙塔–关系映射文件
3.1.1定制持久化类
(1)
Representsasinglecustomer.
@authorLindaSun
由于结点属性attribute值为class-description,所以这里面结点值主要是POJO的注释内容.对应代码如下:
/**
*Representsasinglecustomer.
*@authorLindaSun
*
*/
(2)
Mypack.BusinessObject
由于结点属性attribute值为extends,所以这里面结点值主要是POJO的继承的Class.对应代码如下:
PublicclassCustomerextendsmypack.BusinessObjectimplementsSerializable
(3)
由于结点属性attribute值为field-description,表示给married的getMarried()方法添加注释,注释内容为Isthecustomermarried.代码如下:
/**
*Isthecustomermarried
*/
PublicBooleangetMarried(){
Returnthis.married;
}
(4)
由于结点属性attribute值为scope-set,表示给id的setId()方法类型定义为protected.代码如下:
protectvoidsetId(Integerid){
this.id=id;
}
属性
描述
class-description
指定描述类的JavaDoc
field-description
指定描述类的属性的JavaDoc
interface
如果为true,表示生成接口而非类,默认为false
implements
指定类所实现的接口
extends
指定类继承的父类名
generated-class
重先指定生成的类名
scope-class
指定类的修饰符,默认为public
scope-set
指定set方法的修饰符,默认为public
scope-get
指定get方法的修饰符,默认为public
scope-field
指定类的属性的修饰符,默认为private
use-in-toString
如果为true,表示在toString()方法中包含此属性
gen-property
如果为false,不会在Java类中生成此属性,默认为true
Finder-method
指定find方法名,参见本章3.3节
(5)
……………….
在整个配置文件开头加载结点并指定属性attribute=”extends”,这时所有的类都会扩展mypack.BusinessObject类
如果只希望紧靠着结点的第一个类扩展父类,那么只要给结点增加属,inherit,属性值为true,如下:
Inherit=”true”>mypack.BusinessObject 具体指定某一个类扩展其他类,可以结点嵌套在 … (6) 以上结果实质是下面意思: protectedStringfield1; protectedStringfield2; publicStringfield3; 由于在class结点开头嵌入了结点,并且属性attribute值为scope-field,结点值为protected,所以class所有属性应该都protected,但name属性值为field3的结点property有一个子结点,且子结点值为public,属性attribute值为scope-field,相当作了一个补充,说明CLASS对应的当前属性field3的类型为public.这里也就是说对于同一类属子结点内部说明优先级高于整体说明. 3.1.2定制数据库表 (unique=”true”代表是唯一约束,不晓得oracle有没有这种功能? ) date”/> 对当前字段,生成一个索引,索引名为IDX_REGISTERED_TIME,sql-type=” date”指的是当前字段在数据库中的类型,如果不指定这个类型,hbm2ddl工具会自动进行匹配,建议不指定,这样跨平台或数库移值时比较方便 CreatetableCUTOMERS( NAMEVARCHAR(15)NOTNULL, TIMEDATE ) CreateindexIDX_REGISTERED_TIMEonCUSTOMERS(TIME); 以下 属性 描述 name 设定字段的名字 length 设定字段的长度过 not-null 如果为true,指明字段不允许为null,默认为false unique 如果为true,指明字段有唯一约束,默认为false index 给一个或多个字段建产索引 Unique-key 给多个字段设定唯一约束 Foreign-key 为外键约束命名,在 Sql-type 设定字段的SQL类型 check 设定SQL的检查约束 第4章对象-关系映射基础 本章主要内容如下: ●持久化类的属性没有相关的getXXX()和setXXX()方法. ●持久化类的属性在数据库表中没有对应的字段,或者数据库表中的字段在持久化类中没有对应的属性 ●控制Hibernate生成的insert和update语句 ●设置从持久化类映射到数据库表,以及持久化类的属性映射到数据库表的字段的命名策略 4.1持久化类的属性及访问方法 持久化类使用的javaBean的风格,为需要被访问的属性提供持久化方法;setXXX()和getXXX(); 例如: publicStringname和privateStringname其中任何一种方式都无法定义属性name的只读权限.只有下面的持久化方法可以 publicStringgetName(){ returnthis.name; } privateStringsetName(Stringnme){ returnthis.name=name; } ●Java应用程序通过getXXX()来读取Test1对象并把信息输出,通过setXXX()把信息写到Test1对象 ●Hibernate: 调用Test1对象getXXX()方法取Test1信息,并保存到数据库,调用setXXX()方法把从数据库取得的信息写入到Test1对象.(见示例) 4.1.1java对应的8种基本类型,byte、short、char、int、long、float、double和boolean都有对应的包装类型(类),对于映射文件,类和对应基本类型是相同的 然而包装类型默认值为null,而基本类型无法表达null,比如整型默认值为0,而实现运用过程中,0通常会代表某种业务含义(上一次谈到这个问题),所以推荐使用包装类型(类). 在hibernate中,hibernate会根据OID(OID在第5章会提到,实质是对象的标识,这里面通常指是的关系数据库中的主键)值是否为null来判断当前对象是临时状态还是游离状态,持久化该对象: 如果OID为null,则为临时状态,这时保存时调用saveOrUpdate()方法实质调用是save()方法(插入);如果有值则为游离状态,这时保存时调用saveOrUpdate()方法实质调用是update()方法(修改).(这一点会在第7章讲到).而基本类型无法做到使变量值为null,从而使对象一直处理游离状态. 4.1.2Hibernate访问持久化类属性的策略 ●默认情况下,hibernate通常通过getXXX()和setXXX()来访问类的对象的属性信息与库表信息对应(存取) ●Hibernate还可以通过反射机构直接类的对象的属性信息与库表进对应(存取),采用这种机制对应时,映射文件对属性配置如下: 4.1.3在持久化类的访问方法中加入程序逻辑 1.在持久化方法中加入程序逻辑 publicclassTest1implementsjava.io.Serializable{ ……………………………………………………………….. privateStringtestNameA; privateStringtestNameB; publicStringgetTestName(){ returnthis.testNameA+"连接"+this.testNameB; } publicvoidsetTestName(StringtestName){ StringTokenizert=newStringTokenizer(testName); this.testNameA=t.nextToken(); this.testNameB=t.nextToken(); } } 如上面例子,只要映射文件,加了 这种情况下,由于类中没有testName属性,如果在映射文件 在写HQL时,只映射文件有的字段才在HQL中直接拼写.如: testNameB在映射文件没有,这时如果写上: session.find(“fromTest1ascwherec.testNameB=”xhtan””),这时运行会抛出异常,因为映射文件没有加载testNameB. 2.在类的子成员中对应的setObj()方法中加入程序逻辑 publicclassZCustomerimplementsjava.io.Serializable{ …………………………………………… privateSetZOrders=newHashSet(0); privatedoubleavgPrice;这个属性不需要在映射文件中加载 privatevoidsetAvgPrice(doubleavgPrice){ this.avgPrice=avgPrice; } publicSetgetZOrders(){ calculatePrice(); returnthis.ZOrders; } publicvoidsetZOrders(SetZOrders){ this.ZOrders=ZOrders; } PrivatevoidcalculatePrice(){ doubleavgPrice=0.0; doubletotalPrice=0.0; intcount=0; if(getZOrder()! =null){ Iteratoriter=getZOrders().iterator(); while(iter.hasNext()){ DoubleorderPrice=((Order)iter.next()).getPrice(); totalPrice+=orderPrice; count++; } } } 上面是一个顾客与订单的关系,一个顾客有多个订单,每个订单有一自已钱数,而平均钱数,对于顾客表(ZCUSTOMER)没有存放平均钱数的字段,而且也没必要持久,如果为平均钱数单独再加个字段,这样数据在库中冗余,但有顾客又想查看自已平均消费情况,这时就可以把这个平均钱数avgPrice作ZCustomer一个属性,而对应映射文件不须加这个属性 3.在Test1类的setXXX()方法中加数据验证逻辑. 调用setXXX()地方有两个,一个是我们写的应用程序,另一个是hibernate.有时在应该程中调用类的setXXX()方法时,想在setXXX()中加上数据进行验证功能,而hibernate调用setXXX()方法时,注入的数据都从数据库取出来的,肯定正确,如果如前面说的setXXX()有个验证,这时验证就是冗余的.这时虽有验证我们可以通过在映射文件加 4.1.4设置派生属性 上面例中提到一个平均价格实质说的就一个派生属性,这种运行过程通过计算才能得出值的持久化类的这种属性叫派生属性.除了上面说的计算派生属生的方法,还有另外一种,就是在映射文件指明这种属性的计算方法,如有属性totalPrice代表总钱数.: 4.1.5控制insert和update语句 Hibernate在初始化阶段,就会根据映射文件的映射信息,为所有的持久化类预定义以下SQL语句: ●Insert: insertintoZORDERS(ID,ORDER_NUMBER,PRICE,CUSTOMER_ID)values(? ? ? ? ) ●Update: updateZORDERSsetORDER_NUMBER=? PRICE=? CUSTOMER_ID=? WhereID=? . ●Delete: deletefromZORDERSwhereID=? ●Select: selectID,ORDER_NUMBER,PRICE,CUSTOMER_IDfromZORDERSwhereID=? 以上SQL文都存放在SessionFactory的缓存中,在调用save(),update(),delete(),load()方法时会找到相应的预定义的SQL语句,然后绑定参数.hibernate就是这样在动态的生成SQL语句,这些开销很小。 但是如果关系数据库中的当前表字段比较多时运行这些SQL就比较耗时了,因为这些SQL文都对某数据所有字段的访问,对数据库会开销比较大,这时就可以通过映射文件来精简动态SQL.例如下面设置: 中由于加了update=”false”表明update语句不会包含TEST_NAME字段。 如下表是有这方面具体的规范: 映射属性 作用 如果为false,在insert语句中不包含该字段,表时该字段永运不能插入。 默认为true 如果为false,在update语句中不包含该字段,表时该字段永运不能被修改。 默认为true 如果为false,等价于所有的 默认为true 如果为true,表示当保存一个对象时,会动态生成insert语句,只有这个字段取值不为null,才会把他包含到insert语句中.默认为false 如果为true,表示当更新一个对象时,会动态生成update语句,只有这个字段取值有变化,才会把他包含到update语句中.默认为false 如果为true,等价所有 如果为true,等价所有 4.2处理sql引用标识符 实际上主要针对ORACLE等关系数据库中,命名时不支持特殊字字符时处理方法的介绍,例如oracle中,selectTES_--T2fromtest_123,这种写法就不对了,当执行这个SQL文时会有异常,这时应该改写成select‘TES_--T2’fromtest_123 或者select“TES_--T2”fromtest_123,对映表在hibernate映射文件的写法为: 4.3创建命名策略 创建命策略,实质主要影响是hibernate的缓存中初化SQL文,与我编程没有影响(个人理解),本章讲的自定义命名策略主要是通过实现接口MyNamingStrategy,并系统启动时加载这个已实现的接口,从而实现创建命名策略 packagemypack; importnet.sf.hibernate.cfg.NamingStrategy; importnet.sf.hibernate.util.StringHelper; publicclassMyNamingStrategy
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第三 四五 文档