第三四五六章文档Word文件下载.docx
《第三四五六章文档Word文件下载.docx》由会员分享,可在线阅读,更多相关《第三四五六章文档Word文件下载.docx(21页珍藏版)》请在冰豆网上搜索。
![第三四五六章文档Word文件下载.docx](https://file1.bdocx.com/fileroot1/2022-12/12/4e7afd63-c087-4343-b5e1-690fb140d0dd/4e7afd63-c087-4343-b5e1-690fb140d0dd1.gif)
metaattribute="
class-description"
>
Representsasinglecustomer.
@authorLindaSun
/meta>
由于<
meta>
结点属性attribute值为class-description,所以这里面<
结点值主要是POJO的注释内容.对应代码如下:
/**
*Representsasinglecustomer.
*@authorLindaSun
*
*/
(2)<
extends"
Mypack.BusinessObject
结点属性attribute值为extends,所以这里面<
结点值主要是POJO的继承的Class.对应代码如下:
PublicclassCustomerextendsmypack.BusinessObjectimplementsSerializable
(3)<
propertyname="
married"
type="
boolean"
column=”IS_MARRIED”>
<
field-description"
Isthecustomermarried<
<
/property>
结点属性attribute值为field-description,表示给married的getMarried()方法添加注释,注释内容为Isthecustomermarried.代码如下:
*Isthecustomermarried
PublicBooleangetMarried(){
Returnthis.married;
}
(4)<
idname="
id"
int"
<
scope-set"
protected<
generatorclass="
native"
/>
/id>
结点属性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)<
hibernate-mapping>
metaattribute=”extends”>
mypack.BusinessObject<
class>
……<
/class>
……………….
/hibernate-mapping>
在整个配置文件开头加载结点<
并指定属性attribute=”extends”,这时所有的类都会扩展mypack.BusinessObject类
如果只希望紧靠着<
结点的第一个类扩展父类,那么只要给<
结点增加属,inherit,属性值为true,如下:
metaattribute=”extends”
Inherit=”true”>
具体指定某一个类扩展其他类,可以<
结点嵌套在<
结点,以仅仅指定当前类扩展某一个类,如下
…<
(6)<
classname=”mypack.MyClass1”>
metaattribute=”scope-field”>
propertyname=”field1”type=”string”/>
propertyname=”field2”type=”string”/>
propertyname=”field3”type=”string”>
public<
以上结果实质是下面意思:
protectedStringfield1;
protectedStringfield2;
publicStringfield3;
由于在class结点开头嵌入了<
结点,并且<
属性attribute值为scope-field,<
结点值为protected,所以class所有属性应该都protected,但name属性值为field3的结点property有一个子结点<
且子结点<
值为public,属性attribute值为scope-field,相当作了一个补充,说明CLASS对应的当前属性field3的类型为public.这里也就是说对于同一类属子结点内部说明优先级高于整体说明.
3.1.2定制数据库表
propertyname=”name”type=”string”>
metaattribute=”usesr-in-tostring”>
true<
columnname=”NAME”length=”55”not-null=”true”unique=”true”/>
(unique=”true”代表是唯一约束,不晓得oracle有没有这种功能?
)
propertyname=”time”type=”string”>
columnname=”TIME”index=”IDX_REGISTERED_TIME”sql-type=”
date”/>
对当前字段,生成一个索引,索引名为IDX_REGISTERED_TIME,sql-type=”
date”指的是当前字段在数据库中的类型,如果不指定这个类型,hbm2ddl工具会自动进行匹配,建议不指定,这样跨平台或数库移值时比较方便
CreatetableCUTOMERS(
NAMEVARCHAR(15)NOTNULL,
TIMEDATE
CreateindexIDX_REGISTERED_TIMEonCUSTOMERS(TIME);
以下<
column>
结点各个属性的说明
name
设定字段的名字
length
设定字段的长度过
not-null
如果为true,指明字段不允许为null,默认为false
unique
如果为true,指明字段有唯一约束,默认为false
index
给一个或多个字段建产索引
Unique-key
给多个字段设定唯一约束
Foreign-key
为外键约束命名,在<
many–to-one>
one-to-one>
key>
和<
manly-to-many>
元素中包含foreign-key属性,.如果没有设定此属性,hbm2ddl工具会自动外键约束随机生成唯一的名字.在双向关联中,inverse属性为true的一端不能设置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还可以通过反射机构直接类的对象的属性信息与库表进对应(存取),采用这种机制对应时,映射文件对属性配置如下:
propertyname=”name”access=”field”
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();
如上面例子,只要映射文件,加了<
propertyname=”testName”>
即可,类中无须加testName属性,hibernate并不会直接访问name属性,而是调用getTestName()和setTestName()方法,实际上建产了Test1类中属性testNameA和testNameB与表TEST1中字段TEST_NAME的映射.注意:
这种情况下,由于类中没有testName属性,如果在映射文件<
propertyname=”testName”access=”field”>
程序运行就会抛出异常,因为类中不存在testName属性,而这时access=”field”说明hibernate会直接访问Test1属性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一个属性,而对应映射文件不须加这个属性<
property>
结点,这样每次顾客订单发生变化时,平均钱数就计算一次,如上面.
3.在Test1类的setXXX()方法中加数据验证逻辑.
调用setXXX()地方有两个,一个是我们写的应用程序,另一个是hibernate.有时在应该程中调用类的setXXX()方法时,想在setXXX()中加上数据进行验证功能,而hibernate调用setXXX()方法时,注入的数据都从数据库取出来的,肯定正确,如果如前面说的setXXX()有个验证,这时验证就是冗余的.这时虽有验证我们可以通过在映射文件加<
使hibernate直接访问属性从而避开调用setXXX()方法避开冗余验证.
4.1.4设置派生属性
上面例中提到一个平均价格实质说的就一个派生属性,这种运行过程通过计算才能得出值的持久化类的这种属性叫派生属性.除了上面说的计算派生属生的方法,还有另外一种,就是在映射文件指明这种属性的计算方法,如有属性totalPrice代表总钱数.:
propertyname=”totalPrice”formula=”(selectsum(o.PRICE)fromZORDERSwhereo.CUSTOMER_ID=ID)”>
这时持久化类中,totalPrice属性类型最好时是转换类型而不是基本类型,因为如果上面SQL文结为空就是null,这时基本类型是表达不了,程序在这种情况下会抛出异常.
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.例如下面设置:
propertyname=”testName”update=”false”column=”TEST_NAME”/>
中由于加了update=”false”表明update语句不会包含TEST_NAME字段。
如下表是有这方面具体的规范:
映射属性
作用
元素的insert属性
如果为false,在insert语句中不包含该字段,表时该字段永运不能插入。
默认为true
元素的update属性
如果为false,在update语句中不包含该字段,表时该字段永运不能被修改。
元素的mutable属性
如果为false,等价于所有的<
元素的update属性为false,表示整个实例不能被更新。
元素的dymic-insert属性
如果为true,表示当保存一个对象时,会动态生成insert语句,只有这个字段取值不为null,才会把他包含到insert语句中.默认为false
元素的dymic-update属性
如果为true,表示当更新一个对象时,会动态生成update语句,只有这个字段取值有变化,才会把他包含到update语句中.默认为false
如果为true,等价所有<
元素的dymic-insert属性为true,表示当保存一个对象时,会动态生成insert语句,insert语句中仅包含所有取值不为null的字段.默认为false
元素的dymic-update属性为true,表示当更新一个对象时,会动态生成update语句,update语句中仅包含所有取值被修改的字段.默认为false
4.2处理sql引用标识符
实际上主要针对ORACLE等关系数据库中,命名时不支持特殊字字符时处理方法的介绍,例如oracle中,selectTES_--T2fromtest_123,这种写法就不对了,当执行这个SQL文时会有异常,这时应该改写成select‘TES_--T2’fromtest_123
或者select“TES_--T2”fromtest_123,对映表在hibernate映射文件的写法为:
propertyname=”test”column=”’TES_--T2’”>
4.3创建命名策略
创建命策略,实质主要影响是hibernate的缓存中初化SQL文,与我编程没有影响(个人理解),本章讲的自定义命名策略主要是通过实现接口MyNamingStrategy,并系统启动时加载这个已实现的接口,从而实现创建命名策略
packagemypack;
importnet.sf.hibernate.cfg.NamingStrategy;
importnet.sf.hibernate.util.StringHelper;
publicclassMyNamingStrategy