hibernate的持久化配置和操作(hbm实体映射文件配置)
1、 PO (Persistence Object ) 持久化对象 = POJO + hbm映射
编写规则
1) public 无参数构造方法
2) private 属性,提供getter和setter
3) 提供一个标识属性,映射数据表主键字段 例如 Customer类 id
4) 定义PO类时,不要使用基本数据类型,都用包装类型 , 例如 不用int 用Interger
5) 不要用final修饰(无法使用延迟加载策略进行优化 )
根据id 查询数据 get/load 区别? (面试题)
方法使用完全相同,都是根据id查询对应数据但是get 方法采用立即加载策略,查询customer直接返回 Customer类对象,包含数据 。load 方法 采用延迟加载策略, 返回Customer 类 子类对象 (代理对象),默认不会执行查询,当访问代理对象中数据时,再去查询
2 、OID 概念
持久化对象 PO ,提供一个属性映射到数据表注解列,该属性被称为OID ,Hibernate内部通过OID 进行数据管理
3、 区别自然主键和代理主键
主键特性: 非空 ,唯一, 不变
使用有业务相关的数据列,作为主键 ------ 自然主键 (比如 身份证号码)
与业务无关的数据列,作为主键(常见自增) ---- 代理主键 (比如 UUID )
现阶段企业开发 大多使用代理主键
4、 是使用基本数据类型还是包装类型 的区别
使用基本类型无法区分 null 和 0
使用包装类,正确区分 null 和 0 , 如果不赋值,数据库会保存 null
5、 hbm常见配置
<class name="类名" table="表名" catalog="数据库名" > catalog可以省略,如果省略,使用jdbcutils中数据库
<id> 主键映射 <generator class="native"> 主键生成策略
<property name="类中属性名" column="列名" type="类型"> 普通属性映射
在配置 <id> <property> 元素时, column属性和 type属性都可以省略,不写将按照类中属性类型, 列名和属性名一致
最简单的配置方式
<classname="cn.itcast.domain.Customer" table="customer" >
<idname="id">
<generatorclass="native"></generator>
</id>
<propertyname="name" />
<propertyname="age" />
<propertyname="city" />
</class>
6、 主键生成策略
<id> 元素内部 提供 <generator> 元素, 有class属性,指定数据表主键生成策略
第一种 : increment 代理主键 流水号, 流水号自增由 hibernate框架完成 ,原理 selectmax(id) , +1 作为新插入记录的id
优点 : 跨数据库 ,与数据库无关
缺点 : 存在线程问题
生成数据表,内部没有对 id 自增,自增完全由Hibernate框架实现
第二种 : identity 使用底层数据主键自增机制完成, mysql auto_increment, oracle 没有
第三种 : sequence 使用底层数据库序列机制 , mysql 不支持序列, oracle 支持
配置 <generatorclass="sequence">orders_seq</generator> ,Hibernate调用 orders_seq序列完成自增
第四种:native,根据数据库能力,自动选择采用哪种自增策略,如果mysql是identity ,oracle是sequence
第五种:uuid ,采用随机32位字符串 作为数据表主键值
第六种:assigned ,是一种自然主键,需要在程序中 指定设置 主键的列的值
第七种:复合主键 (联合主键),是一种特殊的自然主键,定义Person类数据由firstname和secondname 共同作为主键
注:使用复合主键,PO类必须实现 java.io.Serializable 接口
7 、 其它内容(了解)
1) <property> 配置时,提供access属性 ,指定Hibernate框架对PO类对象 属性访问方式
默认值 access="property" ,通过get和set 方法 去访问数据
access="field" , 通过 反射直接访问 PO类属性
2) 配置 <property> 属性时,和PO类get 和 set 方法对应,不是和属性对应
public class Customer{
private String name;
public voidsetCname(String cname){
name =cname;
}
public StringgetCname(){
returnname;
}
}
<propertyname="cname" /> 和Customer类getCname 和 setCname方法对应
3) 派生属性使用
类中存在一个属性,在数据表中没有对应列,通过SQL语句执行,为属性进行赋值叫做派生属性
public final class Customer {
// 总客户数
private inttotalcount;
// 提供 get和set
}
<propertyname="totalcount" formula="(select count(*) fromcustomer)"></property>
格式 formula="(sql)"
4) 设置哪些属性 不被 insert 或者update
<property> 提供 insert 属性和 update 属性, 控制当前属性值是否参与 插入和更新
例:
<propertyname="city" column="city" type="string"insert="false"></property> 设置city 不参与插入
<propertyname="city" column="city" type="string"update="false"></property> 设置city不参与更新
作用:timestamp 时间戳
5)特殊字符的处理
<propertyname="name" column="customer name"type="java.lang.String" access="field"></property>
Customer的name属性 生成 customername字段 ,空格是非法字符
使用转义字符键盘左上角 `` (~ 键上 )
<property name="name"column="`customer name`" type="java.lang.String"access="field"></property>