1.对象间的基本关系
首先我简要阐明一下对象之间的基本关系,在这以后UML的课程中也会深入的学习。对象具有的四种基本关系:
关联关系:关联关系在设计模式中是被提倡优先使用于继承关系的。关联关系就是将一个对象做为别一个对象的成员,是一种包含的关系。
依赖关系:对与对象之间的方法的调用,不存在包含的关系。
聚集关系:这个关系比较有趣,比如人的手和身体。如果身体不存在了,手也就不存在了。是一种整个与部分的关系。
一般关系:就是继承关系。
上边的这四种关系是对前一天的补充。对象-关系的映射基础没有涉及这些,而是单一对象通过hibernate与数据库的映射关系。
2.持久化类的属性及访问方法
首先回顾一下持久化,我们知道持久化层是从业务逻辑层中分离出来的专门用于数据库操作的这些部分。持久化层中的持久化类,便是我们之前早已学习的domain类。
1).持久化类的访问者有两个,一是JAVA应用程序,二是hibernate。
写:Java应用程序通过setter设置持久化对象的属性,hibernate通过getter获取持久化对象的属性并生成相应的SQL语句对表格进行操作。
读:hibernate通过setter设置持久化对象的属性,Java应用程序通过getter获取持久化对象的属性。
2).基本数据类型和包装类型
我们知道关联对象的属性与表格的字段是通过property元素节点设置的:
<property name="gender" column="gender" type="integer" /> |
double prD=1;
//把double基本类型转换成Double包装类型
Double wrD=new Double(prD);
//把Double包装类型转换成double基本类型
prD=wrD.doubleValue();
基本的type是hibernate的类型,我们在持久化类中定义的gender属性为int。定义为int类型会有什么弊端?比如,我们有个学生成绩表。如果某个学生没有参加某一学科的考试,但我们却使用了int类型,它的默认值为0,当查看学生成绩时,他到底是考了0分还是没有考试?所以最好将持久化类中的gender属性定义为Integer,它的默认值为null。查询成绩时看到的是null,那么他肯定是没参加考试哦!(注意:数据库中的对应字段应该为字符型)
3).hibernate访问持久化类属性的策略
Hibernate通过name指定的值访问持久化对象。Hibernate通过name值,反射持久化对象的对方法。比如,name的值为gender。Hibernate会直接反射持久化对象的getGender和setGender方法。所以我们必须保证持久化对象中有对应的方法。这是因为property有一个access属性,它的默认值为property。
如果指定access的值为field,则hibernate直接根据name值反射持久化对象的属性。此时,我们必须保证持久化对象中有对应的属性。
access=property时,Hibernate通过相应的get,set 来访问相应的属性;
access=field时,Hibernate通过Java反射机制直接访问类的属性。
即,<property name=“age” column=“age” access=“property”>情况下,Hibernate通过持久化类的getAge(),setAge()访问age属性;
<property name=“age” column=“age” access=“field”>情况下,Hibernate直接访问持久化类的age属性。user.age;
4).在持久化类的方法中加入程序逻辑
通过3)我们知道,如果access的值为property,hibernate直接反射持久化对象的方法。在这个方法中我们就可以加入程序逻辑。比如Customer类中有firstname和lastname两个属性。但我们只想让hibernate通过getName方法获得一个firstname+lastname的字符串,此时我们就可以在getName方法中将firstname与lastname两个属性值合并为一个中间使用 “.”连接的字符串返回。
使用hibernate获取数据表中的数据时,hibernate会调用持久化对象的setName方法。我们在这个方法中将传递进来的参数使用“.”分隔,然后分别设置到firestname和lastname属性中。
public String getName(){
return firstname+ " "+lastname;
}
public void setName(String name){
StringTokenizer t=new StringTokenizer(name);
firstname=t.nextToken();
lastname=t.nextToken();
}
5).hibernate的hql语句
我们在使用JDBC、DBUtil时使用的都是SQL语句。但hibernate比较特殊,它使用的是自己的一套东西叫hql语句。比如我们调用session.find方法,传递的hql语句为:
"from customer as c where c.name='itcast'" |
其中的customer指向持久化对象的映射文件,name指向持久化对象的映射文件中的property元素的name属性。此时需要注意access属性的值。
6).设置派生属性
Property元素中,有一个formula属性。它的值是一个sql表达式,hibernate将根据此表达式计算的值设置到持久化对象的属性上。比如,我们要统计订单表中的总计:
<property name="totalprice" formula="(select sum(o.PRICE) from ORDERS o where o.CUSTOMER_ID=ID)" /> |
十分方便!
7).控制insert和update属性
映射属性 | 作用 |
<property>: insert属性 | 若为false,在insert语句中不包含该字段,该字段永远不能被插入。默认值true。 |
<property>: update属性 | 若为false,update语句不包含该字段,该字段永远不能被更新。默认值为true。 |
<class>:mutable属性 | 若为false,等价于所有的<property>元素的update属性为false,整个实例不能被更新。默认为true。 |
<class>:dynamic-insert属性 | 若为true,等价于所有的<property>元素的dynamic-insert为true,保存一个对象时,动态生成insert语句,语句中仅包含取值不为null的字段。默认false。 |
<class>:dynamic-update属性 | 若为true,等价于所有的<property>元素的dynamic-update为true,更新一个对象时,动态生成update语句,语句中仅包含取值被改变的字段。默认false。 |
8).处理SQL引用表示符
在SQL语法中,表示符是指用于为数据库表、视图、字段或索引等名字的字符串,常规表示符不包括空格,也不包含特殊字符,因此无需使用引用符号。如果数据库表名或列名包含特殊字符,可以使用引用表示符。如:
<property name="name" column="’CUSTOMER NAME’" /> |
此时的column的指定的字段名,必须使用’与括起来。
9).设置类的包名
在映射文件中包含了多个类,而这些类又在同一个包中。此时我们可以不在class属性的name属性中指定类的完整名称。首先我们在hibernate-mapping元素中添加一个package属性,之后的所有class子元素的name属性直接指定类名即可。
<hibernate-mapping package="cn.itcast.cc.hibernate"> |