hibernate学习笔记

来源:互联网 发布:sop16 单片机 编辑:程序博客网 时间:2024/06/07 21:05
框架介绍
hibernate介绍:hibernate是一个对象关系映射框架,对jdbc进行了封装,是一个全自动的orm框架
orm介绍:Object Relation Mapping(对象关系映射),用于实现面向对象编程语言里不同类型系统的数据之间的转换
hibernate优势
1). 对JDBC进行了封装,大大简化了访问数据库的繁琐代码
2). 优秀的orm框架,简化编程工作,使操作数据库更加面向对象
快速入门
依赖的jar包:lib/required中的所有的jar都是必须的 , 以及数据库驱动包,日志jar包
配置文件
核心配置文件(hibernate.cfg.xml):配置连接数据库的相关信息,以及hibernate框架所需要的一些配置数据
映射文件(类名.hbm.xml):与实体类在同一包下 , 定义数据库表及字段与实体类的映射关系
工作原理
1). 通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件。
2). 由hibernate.cfg.xml中的<mappingresource="xx/xx/xxx.hbm.xml"/>读取解析映射信息。
3). 通过config.buildSessionFactory();//得到sessionFactory。
4). sessionFactory.openSession();//得到session。
5). session.beginTransaction();//开启事务。
6). 调用具体操作数据库的API操作
7). session.getTransaction().commit();//提交事务
8). 关闭session;
9). 关闭sessionFactory;
配置详解
核心配置(hibernate.cfg.xml   主流配置方式hibernate.properties)
位置: 一般都放在src下, 默认加载该路径下的配置文件
相关属性配置
<property name="">...</property>
可以参考: hibernate/project/etc/hibernate.properties
hibernate.connection.driver_class: 数据库驱动名称
hibernate.connection.url: 数据库访问的url
hibernate.connection.username: 数据库用户名
hibernate.connection.password: 数据库密码
hibernate.show_sql:是否输出sql语句
hibernate.format_sql: 是否格式化输出的sql
hibernate.dialect: 配置数据库方言
hibernate.hbm2ddl.auto 数据库表的创建策略
Create-drop :每次都会创建一个新的表,执行完成后删除。一般在测试中使用
Create :  每次都会创建一个新的表, 如果存在,先删除,后创建,一般是在测试中使用
update :如果数据库中有表,不创建,没有表创建,如果映射不匹配,会自动更新表结构(只能添加)
validate : 只会使用存在的表,并且会对映射关系进行校验.
加载映射文件:<mapping resource="cn/itcast/xxx/xxx.hbm.xml"/>
配置指定的连接池
1). 需要指定参数(连接提供者) :<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>(具体的配置项,参考hibernate.properties)
2). 属性配置
最大连接数: <property name="hibernate.c3p0.max_size">20</property>
最小连接数: <property name="hibernate.c3p0.min_size">5</property>
连接超时时间 : <property name="hibernate.c3p0.timeout">3000</property>
连接空闲时间: <property name="hibernate.c3p0.idle_test_period">5000</property>
映射配置(类名.hbm.xml)
位置:一般存放在对应的实体类所在的包下,默认根据类名在该路径下扫描该配置文件
标签
<hibernate-mapping package="...">: 统一声明包名, 这样就可在class中不需要写全类名
<class name=....>
name : 类的名称
table: 表的名称,可以省略,这时表的名称就与类名一致
catalog:数据库名称可以省略.如果省略,参考核心配置文件中url路径中的库名称
<id> 必须存在
name :类中的属性名称
column: 表中的主键名称  column它也可以省略,这时列名就与类中属性名称一致
length :字段长度
type:属性指定类型, 可以是java中的数据类型, 可以是hibernate数据类型, 也可以是sql的数据类型
<generator> :主键的生成策略
<property>: 描述类中的属性与表中的非主键的映射关系

常用API
Configuration
1). 概述:用于加载hibernate配置
2). 加载hibernate.properties:Configuration configuration = new Configuration()
3). 主要加载hibernate.cfg.xml: Configuration configuration = new Configuration().configure()
4). 加载指定名称核心配置:Configuration configuration = new Configuration().configure(hibernate.cfg.xml)
5). 手动加载映射文件
configuration.addResource("cn/itcast/domain/Customer.hbm.xml")
configuration.addClass(Customer.class)
SessionFactory
1). 概述:负责初始化Hibernate ,它充当数据存储源的代理,并负责创建Session对象
2). 特点:SessionFactory是重量级的对象,通常一个项目每个数据库对应一个SessionFactory
3). 获取: config.buildSessionFactory()
4). 获取Session: sessionFactory.openSession()
5). 获取与线程绑定的session:sessionFactory.getCurrentSession()
Session
1). 概述: Session接口负责执行被持久化对象的CRUD操作
2).save : 保存对象
3).update : 修改操作
4).delete:删除
5).get/load: 根据id进行查询
6).saveOrUpdate:执行save或update操作
7).createQuery:获取一个Query对象
8).CreateSQLQUery: 获取一个可以操作sql的SQLQuery对象
9).createCriteria: 获取一个Criteria它可以完成条件查询
Transaction
1). 概述: Transaction接口主要用于管理事务,它是hibernate的事务接口,对底层的事务进行了封装
2). 开启事务:session.beginTransaction()
3). 事务提交:commit();
4). 事务回滚: rollback();
5). 事务自动提交配置:<property name="hibernate.connection.autocommit">true</property>(默认值为 false)
Query
1). 概述:对数据库及持久对象进行查询,它可以有两种表达方式:HQL语言或本地数据库的SQL语句
2). 获取Query对象: Query query=Session.createQuery(hql)
3). 列出全部查询结果 含有多个结果: list() 确定只包含一个结果:uniqueResult()
4). 返回结果
如果查询返回所有的列,则自动回封装为model对象
如果查询指定的列,默认返回的是数组
如果需要返回model对象类型,需要在为model对象提供包含对应属性的构造方法,无参的构造一定也得提供。
HQL语句改写如下: select new Customer(name , address)  from Customer
5). 分页查询
设置查询的起始条数:setFirstResult(...)
设置每页显示记录数:setMaxResults(...)
6). 传递参数
无名称参数 HQL写法: ... where name = ?
参数赋值  query.setParameter(0, "value")  query.setString(0,"value")
有名称参数 HQL写法:where name =:myname  参数赋值  query.setParameter("myname", "value") query.setString("myname","myvalue")
SqlQuery
1). 概述:对数据库及持久对象进行查询,表达方式:本地数据库的SQL语句
2). 获取SqlQuery: SQLQuerysqlQuery=session.createSqlQuery(sql)
3). 返回结果 返回的结果默认类型为Object[] 封装为model对象:sqlQuery.addEntity(Customer.class)
4). 传递参数   SQL写法: ... where name = ? 参数赋值  query.setParameter(0, "value")  query.setString(0,"value")
Criteria
1). 概述: Criteria接口与Query接口非常类似,允许创建并执行面向对象的标准化查询
2). 获取Creteria对象: Criteria criteria=Session.createCriteria(...)
3). 条件查询
添加查询条件: criteria.add(Restrictions.eq(“name”,”xxxx”));
or条件连接: criteria.add(Restrictions.or(Restricitons.eq(),Restrictions.list()…..))
分页   setFirstResult(...)  setMaxResults(...)
Restrictions eq: 等于 like: 模糊查询   le: 小于等于ge:大于等于 lt:小于  gt:大于  ne:不等于  or:或者  and: 并且  between: 在两者之间
查询的方法   list()  uniqueResult()
持久化类介绍
1). 必须提供一个无参数的public构造方法
2). 所有属性要private ,对外提供public 的get/set方法
3). 在PO类必须提供一个标识属性,让它与数据库中的主键对应,我们管这个属性叫OID
4). PO类中的属性尽量使用基本数据类型的包装类.
5). PO类它不能使用final修饰符
get/load方法的区别
相同: 都是根据OID来加载数据
不同
1). load方法是延迟加载 , 只有查询OID之外的属性时, 才会查询 ; get方法立即查询, 则直接查询全部字段返回
2). 查询的数据不存在时 , load方法抛异常 , 而get方法返回 null
3). load加载的是代理对象(模型不能被final修饰) , 而get加载的是pojo
主键生成策略
increment:代理主键, 由hibernate维护一个变量,每次生成主键自动递增。每次插入之前需要先查询一次
identity:代理主键,由底层数据库生成标识符,自动增长。需要数据库支持主键自动增长, mysql的auto_increment
sequence:代理主键,hibernate根据底层数据库序列生成标识,实现主键自增。 需要数据库支持序列, oracle的sequence
native:代理主键,根据底层数据库对自动来选择identity , sequence ,hilo。
uuid:代理主键, hibernate采用128位的UUID算法来生成标识符(32位), 该算法可以生成唯一的字符串标识符。
assign:自然主键, 由java程序负责生成标识符
持久化对象状态
瞬时态: 也叫临时态或自由态。 指新new出来的对象, 不存在OID, 与session无关联, 数据库中无记录
持久态:有OID,由session管理
托管态:也叫游离态或离线态。 存在OID , 与session失去关联
转换 TO : Object  PO : Object + OID + Session  DO : Object + OID
一级缓存
概述: Hibernate的一级缓存是session范围内的缓存, 为了减少对数据库的访问
结构: actionQueue , persistenceContext 。 session中定义了很多的集合来存储数据,他们构成了session缓存
特点
1). 一级缓存是session级别的缓存 , 多个session之间不可以共享数据
2). 当hibernate的session执行 save , update , delete , get , load , Query , Creteria , SQLQuery 等操作时, 操作的数据都会进入到一级缓存中
3). 从一级缓存中获取数据, 只可以通过OID进行查询, 也就是通过get , load 方法进行查询
3). 当调用session的close方法时 , session缓存清空
常用API
clear: 清空一级缓存
evict:清空一级缓存中的指定的一个对象
refresh:重新查询数据库, 用数据库中信息来更新一级缓存与快照
Session常用API补充
udpate  主要是针对于脱管对象,持久对象具有自动更新能力
问题  如果在session中出现相同的oid两个对象,会产生异常  脱管对象的oid如果在数据表中不存在,会报异常
saveOrUpdate  如果对象是一个瞬时对象 -------- 执行save操作   如果对象是一个脱管对象 --------- 执行update
delete : 如果执行delete操作,先删除一级缓存,在删除数据库中的数据
数据对象三种关系映射
一对一  1). 唯一外键对应:在任意一方添加外键来描述对应关系  2). 主键对应:一方的主键作为另一方的主键
一对多(多对一): 在多的一方添加外键来描述关联关系
多对多: 通过一张中间表来描述其对应关系
一对多关系映射
实体类定义  多的一方: 在其中定义一的一方属性  一的一方: 在其中定义多的一方的集合属性
映射文件  多的一方: many-to-one 标签描述关系  一的一方: set 标签描述集合信息
单向关联保存: 需要在保存的对象对应的映射文件中, 添加级联保存配置  (cascade="save-update")
双向关联保存
1). 通过inverse的值, 来决定由哪一方来维护外键; inverse的值表示是否放弃维护主键,由对方来维护主键。
2). 外键在哪一个表中,我们就让哪一方来维护外键
级联删除
1). cascade = "delete" : 级联删除操作
2 ). cascade = "delete-orphan" (孤儿删除): 删除与当前对象解除关系的对象
cascade操作
none : 这是一个默认值
save-update : 当我们配置它时,底层使用save update或save-update完成操作,级联保存临时对象,如果是游离对象,会执行update.
delete: 级联删除
delete-orphan: 删除与当前对象解除关系的对象。
all : 它包含了save-update  delete操作
all-delete-orphan: 它包信了delete-orphan与all操作
注解开发
PO类注解配置
@Entity : 声明一个实体 , 作用在PO类上
@Table: 来描述类与表对应 , 作用在PO类上
@Id : 来声明一个主键
@GenerateValue:用它来声明一个主键生成策略(@GeneratedValue(strategy=GenerationType.IDENTITY))
@Column:来定义列    columnDefinition : 定义列信息 , 如 columnDefinition(double(10,2))  length : 限制长度
@Temporal: 来声明日期类型  TemporalType.DATE只有年月日  TemporalType.TIME只有小时分钟秒  TemporalType.TIMESTAMP有年月日小时分钟秒
@Transient : 设定PO类的属性不参与数据库表的映射
主键生成策略使用UUID   1). GenericGenerator(name="xxx",strategy="uuid")  2). GeneratedValue(generator="xxx")
一对多
一方
@OneToMany
targetEntity=Order.class : 指定关联方的目标实体类型
mappedBy="c" : 相当于配置inverse=true , 放弃关系维护权
orphanRemoval=true : 孤儿删除的属性
cascade=CascadeType.SAVE_UPDATE : 级联操作的属性配置
多方
@ManyToOne
targetEntity = Customer.class : 指定关联方的目标实体类型
cascade=CascadeType.SAVE_UPDATE : 级联操作配置
@JoinColumn : 通过name属性指定外键列
级联操作配置
1). @OneToMany , @ManyToOne 中的cascade属性
2). @Cascade 注解
多对多
@ManyToMany来配置多对多,只需要在一端配置中间表,另一端使用mappedBy表示放置外键维护权
1). 其中一方放弃关系的维护权
@ManyToMany(targetEntity = Student.class, mappedBy = "teachers")
2). 另一方配置中间表的关系
@JoinTable
name = "xxx" : 配置中间表的表名
joinColumns = {@JoinColumn(name = "c_student_id", referencedColumnName = "id") } : 配置本方在中间表的关联字段
inverseJoinColumns = {@JoinColumn(name = "c_teacher_id", referencedColumnName = "id") } : 配置对方在中间表的关联字段
3). 注意 : 多对多配置级联删除时 , 不要双方都配置级联删除, 否则会造成灾难性后果
一对一
任意一方添加外键 
@OneToOne 定义关联对象的实体模型类 , 以及是否维护关系
@JoinColumn 定义外键的列信息
主键映射(了解)
在一方中设置主键生成策略, 而在另一方中主键使用对方的外键策略
@Id
@GenericGenerator(name = "myForeignKey",strategy = "foreign", parameters = {
@Parameter(name = "property", value = "wife") })
@GeneratedValue(generator = "myForeignKey")
private String id;
@PrimaryKeyJoinColumn  : 说明一对一的模型之间使用主键映射
检索方式
导航对象图 : 通过对象的属性(pojo)信息加载数据, Customer c=session.get(Customer.class,2);  c.getOrders();
OID检索  get(class,OID)  load(class,OID)
HQL检索
基本检索 
1). from Customer ;
2). 查询的结果封装 为Customer
排序检索 : from Customer order by fieldname asc/desc ;
条件检索
参数传递索引 
HQL : from BookModel where price > ? and name = ?
参数设置: query.setParameter(index , value);
参数传递索引, 指定类型
HQL : from BookModel where price > ? and name = ?
参数设置: query.setDouble(index , value);
可变参数, 类型不明确
HQL : from BookModel where price > :price and name = :name
参数设置: query.setParameter("price" , value);
可变参数, 类型明确
HQL : from BookModel where price > :price and name = :name
参数设置: query.setDouble("price" , value);
分页检索
query.setFirstResult(int) : 设定查询的第一条数据编号
q.setMaxResults(int) : 设定查询的数据总量
分组统计检索
count : select count(*) from Order ; 返回的结果是一个, 可以使用uniqueResult();
sum : select sum(money) from Order group by c
min 
max
avg
投影检索
1). 只查询一个属性 , 返回的List中的泛型就是属性的类型
2). 如果查询两个及以上属性, 则返回的是一个Object[]
3). 使用投影将查询的结果封装到对象   1). select new Customer(id,name) from Customer ;2). Customer中提供对应的构造方法
命名检索
hbm.xml 配置
1). 配置 : <query name="queryCustomerHql">from Customer</query>
2). 调用 : session.getNamedQuery("queryCustomerHql")
注解配置  1). 配置 : @NamedQuery(name = "myHql", query = "from Customer")  2). 调用 : session.getNamedQuery("myHql")
QBC检索
基本检索
1). 概述: Criteria接口与Query接口非常类似,允许创建并执行面向对象的标准化查询
2). 获取Creteria对象: Criteria criteria=Session.createCriteria(...)
排序检索
1). criteria.addOrder(org.hibernate.criterion.Order.asc('...')):
2). criteria.addOrder(org.hibernate.criterion.Order.desc('...')):
条件检索
Restrictions  eq: 等于  like: 模糊查询  le: 小于等于 ge:大于等于  lt:小于  gt:大于 ne:不等于 or:或者  and: 并且  between: 在两者之间
分页检索
1). criteria.setFirstResult(...);
2). criteria.setMaxResults(...);
分组统计检索
count(*) : Projection condition = Projections.rowCount();
count(...) : CountProjection projection = Projections.count("name");
min : Projection conditionMax = Projections.min("price")
max : Projection conditionMin = Projections.max(“price");
sum :Projection conditionAvg = Projections.sum("age");
avg : Projection conditionAvg = Projections.avg("age");
投影查询 . 
单一属性投影
1). Criteria c = c.createCriteris(Customer.class)
2). c.setProjection(Projections.property("name"))
3). List<String> list =  c.list();
多属性投影
1). Criteria c = c.createCriteris(Customer.class)
2). ProjectionList pList = Projections.projectionList();
3). pList.add(Projections.property("name")) .... 
4). c.setProjection(pList)
5). List<Object[]> list = c.list()
离线条件检索
1). DetachedCriteria dc = DetachedCriteria.forClass(Customer.class)
2). Criteria criteria = dc.getExecutableCriteria(session);
SQL检索
1). SQLQuery sqlQuery = session.createSQLQuery("sql");
命名检索 
hbm.xml 配置   1). 配置 : <sql-query name="queryCustomerSql">SQL语句</sql-query>  2). 调用 : session.getNamedQuery("queryCustomerSql")
注解配置
1). 配置 : @NamedNativeQuery(name = "findCustomer", query = "select * from t_customer", resultSetMapping = "customerSetMapping")
2). 配置@SqlResultSetMapping 结果映射
@SqlResultSetMapping(name = "customerSetMapping", 
entities = { @EntityResult(entityClass = Customer.class, 
fields = {
@FieldResult(name = "id", column = "id"),
@FieldResult(name = "name", column = "name") 
}

})
多表操作HQL
连接类型介绍
交叉连接
内连接  显示内连接  隐式内连接  迫切内连接
外连接  左外连接  迫切左外连接  右外连接
显式内连接
1). from Order as o  inner join o.c
2). from Customer c inner join c.orders with c.id=3
3). from Customer c inner join c.orders where c.id=3
隐式内连接 : from Order o where o.c.id=3
迫切内连接 
1). 语法 : from Customer c inner join fetch c.orders
2). 特点 : 迫切, 就是立即加载的意思
外链接
1). 左外链接
语法 : from Customer c left outer join c.orders
返回 : List<Object[ ]>
2). 迫切左外连接
语法 : select distinct c from Customer c left outer join fetch c.orders where c.id=3
返回 : List<Customer>
迫切连接 与 非迫切连接的区别
1) . 对象封装
迫切连接 : 一个对象, 主表对象
非迫切连接 : 包含双方的数据,是两个对象(主表对象, 从表对象)
2) . 查询时机
迫切连接 : 立即加载
非迫切连接 : 延迟加载
线程绑定session
1). 配置 :  <property name="hibernate.current_session_context_class">thread</property>
2). 获取session : sessionFactory.getCurrentSession()
3). 特点 : 当执行transaction.commit() 方法时, 会自动的关闭session .
优化方案
HQL优化
使用参数绑定 : 提高效率 , 避免SQL注入
尽量少使用NOT : 索引失效
尽量使用where替换having : having是先分组后过滤 , where是先过滤后分组
减少对表的查询
使用表的别名
实体的更新与删除 : hql的update , delete 操作可以批量操作, 使用query的executeUpdate方法
一级缓存优化 : 可以使用clear , evict 方法清除一级缓存中的数据, 避免耗费内存空间
延迟代理对象初始化 : Hibernate.initialize(c1);
延迟加载
类级别检索
配置文件 : <class name="..." lazy="true"/>
注解 : @Proxy(lazy=true)
默认值 : true
延迟代理对象初始化: Hibernate.initialize(...)
关联级别检索
set的一方
lazy 控制的是关联数据的加载策略
XML配置  lazy=false : 立即加载  lazy=true : 延迟加载 , 按需执行SQL语句(全信息)  lazy=extra : 超级延迟加载 , 按需执行SQL语句(求count数量时, count统计查询 ; 求全信息时, 全信息查询)

注解配置  @LazyCollection(LazyCollectionOption.TRUE)  @LazyCollection(LazyCollectionOption.EXTRA)  @LazyCollection(LazyCollectionOption.FALSE)

fetch  控制关联数据的加载对应的SQL语句
XML配置 fetch=select : 普通的SQL语句  fetch=subselect : 使用子查询的SQL语句  
fetch=join  1). 如果使用Query查询那么fetch=join等同于fetch=select , 此时lazy失效  2). 如果使用OID查询,那么fetch=join生成迫切左外连接查询,此时lazy属性失效
注解配置  @Fetch(FetchMode.SELECT)  @Fetch(FetchMode.JOIN)  @Fetch(FetchMode.SUBSELECT)

one 的一方
lazy 控制的是关联数据的加载策略
lazy=false : 立即加载
lazy=proxy : 交由被关联数据自身进行加载控制,参看当前关联数据对应的模型的(class标签的子元素)的lazy设置值
lazy=no-proxy
fetch  控制关联数据的加载对应的SQL语句
fetch=select : 普通的SQL语句
fetch=join
1). 如果使用Query查询那么fetch=join等同于fetch=select , lazy失效
2). 如果使用OID查询,那么fetch=join采用迫切左外连接查询, lazy失效
批量抓取
概述 : 我们在查询多个对象的关联对象时,可以采用批量抓取方式来对程序进行优化
xml 配置 : batch-size=...
注解配置 : @BatchSize(size=...) , 可以作用在集合上 , 可以作用在类上

原创粉丝点击