Comnoponent映射
component映射
在hibernate中,component是某个实体的逻辑组成部分,它与实体的根本区别是没有oid,
component可以成为是值对象(DDD)
采用component映射的好处:它实现了对象模型的细粒度划分,层次会更分明,复用率会更高,实际映射成的数据库字段还是老样子
现在我们假设下面的场景
有一个User和Employee类,两者都有完全相同的一些字段保存联系方式,比如email,phone,address等。这个时候,为了在对象模型使类结构看起来更清晰,我们可以把这些公共的字段单端创建一个联系方式类:Contract类,定义User和Employee类的时候引用上这个Contact就可以了
下面是实例代码
User
public class User {
private int id;
private String name;
注意这个引用字段
private Contact contact;
}
Contact类
public class Contact {
private String email;
private String address;
private String zipCode;
private String contactTel;
}
这么做数据库中还是把一切数据保存在User表中,不会创建一个Contact表,但是这么做使得我们的对象模型更清晰
下面是具体的映射文件
<hibernate-mapping>
<class name="com.itcast.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
这里映射那个关联Contact类中的字段
<component name="contact">
<property name="email"/>
<property name="address"/>
<property name="zipCode"/>
<property name="contactTel"/>
</component>
</class>
</hibernate-mapping>
复合主键映射
这里假设一种情况:一个公司财务核算,核算日期由两个数字确定:年份和月份
这个时候我们就遇到一个问题:一个表有两个主键联合约束
对于这种符合主键,我们在设计实体类的时候把复合主键单独放在一个类中,由对应的实体类去引用它。但是这个保存主键的类在设计的时候需要注意一下两点
此类必须实现序列化接口(Serializable)。
因为当一个类可能会跨jvm使用的时候,就必须实现序列化接口
实现Serializable以后这个类的对象就可以远程传输或者保存到硬盘上。
覆写hashcode和equals方法。
下面是这个类的具体设计
首先是保存主键的类
注意这里实现Serializable
public class FiscalYearPeriodPK implements Serializable {
//核算年
private int fiscalYear;
//核算月
private int fiscalPeriod;
注意要覆盖hashCode和equals方法
@Override
public int hashCode() {
}
@Override
public boolean equals(Object obj) {
}
}
下面是实体类的设计
public class FiscalYearPeriod {
在实体类中引用了刚才定义的主键类
private FiscalYearPeriodPK fiscalYearPeriodPK;
//开始日期
private Date beginDate;
//结束日期
private Date endDate;
}
下面是映射文件的写法
<hibernate-mapping>
<class name="com.itcast.hibernate.FiscalYearPeriod" table="t_fiscal_year_period">
<composite-id name="fiscalYearPeriodPK">
<key-property name="fiscalYear"/>
<key-property name="fiscalPeriod"/>
</composite-id>
<property name="beginDate"/>
<property name="endDate"/>
<property name="periodSts"/>
</class>
</hibernate-mapping>
这样做,我们在对象模型上看到一个两个类,但是在数据库表还是一个表
各种集合关系的映射
对下面四种集合进行分析
1.set
2.list
3.array
4.map
实体类实际如下
public class CollectionMapping {
private int id;
private String name;
private Set setValue;
private List listValue;
private String[] arrayValue;
private Map mapValue;
}
对于集合类的映射,都是通过附加一个关联表来进行的
主表:
CollectionMapping
id name
Set表
由于set内部是无序的,所以这里只要其主键是以主表主键为外键就可以了
setid setValue
List表
由于List内部是有序的,所以表生成的时候需要加上一个index序号标记
listId listValue index
Map表
由于其内部是key-value结构,所以表中也要同时保存key和value
mapId mapKey mapValue
其具体一身方式
Set
<hibernate-mapping>
<class name="com.itcast.hibernate.CollectionMapping" table="t_CollectionMapping">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="setValue" table="t_set_value">
这个key 表示t_set_value的主键是以当前父表的主键为外键的
<key column="set_id"/>
string是数据库中属性,会自动保存为varchar
<element type="string" column="set_value"/>
</set>
<list name="listValue" table="t_list_value">
<key column="list_id"/>
<list-index column="list_index"/>
<element type="string" column="list_value"/>
</list>
<array name="arrayValue" table="t_array_value">
<key column="array_id"/>
<list-index column="array_index"/>
<element type="string" column="array_value"/>
</array>
<map name="mapValue" table="t_map_value">
<key column="map_id"/>
<map-key type="string" column="map_key"/>
<element type="string" column="map_value"/>
</map>
</class>
</hibernate-mapping>
hibernate查询语言hql
由于自己对hql比较熟悉,这里就不再举例子了。只进行总结
在hql中关键字不区分大小写,但是属性和类名区分大小写
1、简单属性查询
单一属性查询,返回结果集属性列表,元素类型和实体类中相应的属性类型一致
多个属性查询,返回的集合元素是对象数组,数组元素的类型和对应的属性在实体类中的类型一致
数组的长度取决与select中属性的个数
如果认为返回数组不够对象化,可以采用hql动态实例化Student对象
2、实体对象查询【重要】
N + 1问题,在默认情况下,使用query.iterate查询,有可以能出现N+1问题
所谓的N+1是在查询的时候发出了N+1条sql语句
1: 首先发出一条查询对象id列表的sql
N: 根据id列表到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句
list和iterate的区别?
list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据
iterate:在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题
为什么出现N+1问题?
因为iterate是使用缓存的,当我们执行这个hql的时候,它会先去数据库中查处满足条件的记录的id列表,然后根据这个id列表中的一个个id,先去缓存中去查找是否有满足这个id记录,如果有就直接用,如果没有就发出select from where id=?的这么一个slq。所有如果我们查询的数据在缓存中没有,那么有多少个满足条件的id,就会发出多少条sql。
3、条件查询
可以采用拼字符串的方式传递参数
可以采用 ?来传递参数(索引从0开始)
可以采用 :参数名 来传递参数
如果传递多个参数,可以采用setParamterList方法
在hql中可以使用数据库的函数,如:date_format
本文介绍了Hibernate中组件映射(component mapping)、复合主键(composite primary key)及集合关系(set, list, array, map)的映射方法,并探讨了Hibernate查询语言(HQL)的应用技巧。
3272

被折叠的 条评论
为什么被折叠?



