就业班_JavaEE_day39_42_Hibernate
一 概述
封装jdbc;dao层;orm框架;
orm 对象关系映射 类 -- 表 属性 -- 字段 对象---记录
用面向对象的思想来操作数据库
二 快速入门
1 导包
required
jpa--适配器jar包
驱动包
3个日志包
如果用到c3p0 导入c3p0包
2 配置文件
src下 hibernate.cfg.xml
domain 下 xx.hbm.xml
都可以在解压包中的project中找到。
3创建数据库
4 创建domain类
5 configuration -- sessionfactory -- session -- transaction -- save update delete get/load -- commit -- 释放资源
三 二个配置文件
hibernate.cfg.xml
<hibernate-configuration>
<!-- 1 必选 数据库连接4要素 -- >
<property name="">xxxxxx</property>
driverClass
url
username
password
<!-- 2 可选 hibernate参数配置 -- >
dialect
show_sql
美化sql
hbm2ddl update
//如果用到sesssion.getcurrentsession. 需要添加current_session_context_class配置。
<!-- 3 必选 映射文件引入 -- >
<mapping resource="" />
</hibernate-configuration>
补充:hibernate默认内置了一个连接池,如果要使用c3p0 则要添加c3p0的相关配置
<!-- 设置连接提供者 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- c3p0连接池的配置 -->
<property name="hibernate.c3p0.max_size">20</property> <!-- 最大连接数 -->
<property name="hibernate.c3p0.min_size">5</property> <!-- 最小连接数 -->
<property name="hibernate.c3p0.timeout">120</property> <!-- 超时 -->
<property name="hibernate.c3p0.idle_test_period">3000</property> <!-- 空闲连接 -->
可以从projects/etc/hibernate.properties 拷贝
xxx.hbm.xml 映射文件
<hibernate-mapping>
<class name="domain类全路径" table="表名">
<id name="类属性" column="表字段">
<generator >
通常采用二种 native 智能匹配 uuid
</generator>
</id>
<property name="类属性" column="表字段">
</property>
</class>
//还可以配置query
</hibernate-mapping>
四常用API
configuration 加载hibernate.cfg.xml
sessionfatory sesison工厂 一个项目创建一个 后续spring进行管理 服务器启动就创建
session 类似于jdbc中的connection opensession getcurrentsesison save update delete get/load saveorupdate
补充:opensesion getcurrentsession 区别
1 opensesion每次都打开一个新的session getcurrentsession则在第一次调用时打开一个新的,后续调用使用同一个。
2 opensession需要手动close getcurrentsesion 不需要手动close 事务提交或者回滚会自动close
如果使用getcurrentsession 则要在cfg中添加如下设置,来指定contextclass
<!-- 设置seesion和线程绑定 需要配合SessionFactory的getCurrentSession()使用 -->
<property name="hibernate.current_session_context_class">thread</property>
使用getcurrentsession必须开启事务。
transaction 做增删改操作必须开启事务。
五 持久化类
1 po javabean+hbm
2 编写规范:
1 属性不要用基本类型
2 private 属性 并提供给 public getset方法
3 无参数构造
4 定义与数据库对应的主键属性 比如oid
5 po类不要用final修饰 因为hibernate中会通过cglib来产生子类代理,如果定位为final则表示该类不能别继承
3 主键生成策略
xxx.hbm.xml中配置主键生成策略
mysql identity
oracle sequence
native 智能匹配
uuid 32位字符串
4 po类的三种状态
瞬时态 --- > 持久态 --->游离态
new 瞬时态 --->save,saveorupdate 持久态 ---> 从一级缓存中移除,session.close() clear() evict() 游离态
get load find query 持久态
六 缓存
一级缓存 session
优化,减少访问数据库的次数。 Map key=持久化类对象 value=快照(快照特点,产生后将不会发生改变)
一级缓存的API
session.clear() 清空缓存
session.evict(obj) 清除缓存中指定对象
session.refresh(obj) 重新查询数据库,覆盖缓存中的key和value
二级缓存 sessionfatory 不用
持久化类具有更新数据库的能力。
七关系映射
一对一
表 1 唯一外键 2 主键也作为外键指向另外一方的主键。
java类 互相持有对方的引用
一对多
表 多的一方添加外键
java类
一方 添加set集合
多方 添加一方对象引用
多对多
表 中间表 二个一对多
java类 二边添加set集合
一对多hbm.xml中的配置和级联操作
一方customer
<set name="orders">
<key column="customer_id"></key> //外键
<one-to-many class="Order全路径"></one-to-many>
</set>
多方Order
<many-to-one name="customer" class="Cutomer全路径" column="customer_id"></many-to-one>
级联操作
在一方的set中添加 cascade属性
save-update 级联保存
eg:
Customer customer = new Customer();
Order order1 = new Order();
Order order2 = new Order();
customer.getOrders().add(order1);
customer.getOrders().add(order2);
order1.setCustomer(customer);
order2.setCustomer(customer);
session.save(customer);
注意 双向关联时 如果没有添加inverse=true。则一方也会维护外键,针对每条order记录进行update操作,这样会影响性能。所以在一方添加inverse=true
当做级联保存时,要添加双向关联,否则添加一方时,多方外键将为null。
delete 级联删除
eg:
Customer customer = session.get(Customer.class,1);
session.delete(customer);
delete-orphan 删除孤儿 不使用delete,而是将多的一方从set集合中移除。
eg:
Customer customer = session.get(Customer.class,1);
Order order1 = session.get(Order.class,1);
customer.getOrders().remove(order1);
all = save-update+delete
all-delete-orphan = all+ delete-orphan
八 注解开发
1po基本配置
类
@Entity
@Table(name="表名")
属性
主键
@Id
@generatedValue(strategy) 不配置strategy默认是native 也可以指定strategy=generationType.identity
@column 普通列 也可以不写
@Temporal(TemporalType.timestamp) 可以用来给date属性添加注解 data time datetime 与mysql类似。
@Transient 属性不出现表字段中
所有的注解配置,在hibernate.cfg.xml中都需要通过mapping class 来引入类。
2 一对多配置
一方
@onetomany targetentity= mapedby= orphra=true 指定删除孤儿的cascade
@cascade
多方
@manytoone targetclass=
@joincolumn 指定外键
3 多对多配置
A方
假设A方放弃外键维护
@mangtomany(targetclass B方class mappedby 另一方对本方的引用)
@cascade(只能指定save-update)
B方
维护外键
@manytomany(tragetclass 一方的class )
@jointable(name=“中间表名”joincolumns={本方在中间表的外键} inversejoincolumn={对方在中间表的外键})
4 一对一配置 唯一外键方式 可以想象成一对多
A方
假设A方放弃外键维护
@onetoone(targetclass=B方class mappedby=B方对本方的引用)
@cascade() 用hibernate的cascade 。 cascade添加在一方。
B方
@onetoone(targetclass=A方class)
@joincolumn(指定外键)
九 5种查询
oid get() 立即查询 load() 延迟查询
hql
1 查询所有 from Student list
2 分页查询 from Student setfirstresult begin记录索引从0开始 setmaxresults 设置每页显示多少行。 list
3 条件查询
A from Student where name=? setParameter(0,xxx) 索引从0开始 与jdbc的preparestement不同jdbc中从1开始。 list
B from Student where name=:name setParameter("name",xxx) list
如果能确定返回一条记录。 则可以不使用list 而使用uniqueResult
排序
分组
4查询指定列(投影查询)
1 在student类中给出Student(name)构造和无参数构造;
2 select new Student(name) from Student
3 list
5 命名查询
在hbm.xml中添加query
<query name="">
hql
</query>
session.getnamedquery(query的名字)
qbc
1 查询所有 createcriteria(Student.class) list
2 分页查询 createcriteria(Student.class) setfirstresult begin记录索引从0开始 setmaxresults 设置每页显示多少行。 list
3 条件查询
> createcriteria(Student.class) add(Restrictions.eq("name","zhangshan")) list
Restrictions.and(Restrictions.eq(),Restrictions.eq())
排序 criteria.addOrder(Order.desc("xxxx"));
分组 criteria.setProjection(Projections.projectlist().add(Projections.sum("money")).add(Projections.groupproperty("c")));
如果能确定返回一条记录。 则可以不使用list 而使用uniqueResult
4 离线查询
在action中创建detachedcriteria
detachedcriteria dc = DetachedCriteria.forclass(Student.class);
//添加条件
在dao中动态获取
Criteria c = dc.getExecutableCriteria(session)
对象导航
本地sql
createsqlquery(String sql) addEntity(Student.class)
十 多表查询及hibernate优化
1 sql中多表查询复习
2 hql中多表查询
迫切内连接 select distinct c from Customer c inner join fetch c.orders where xx
迫切左外连接 select distinct c from Customer c left join fetch c.orders where xx
迫切连接查询的出的是已经封装好的对象 , 同时如果查询的是一方数据需要注意去重。
3 事务的复习
4 hibernate中通过getcurrentsession来保证session是同一个对象,用于事务操作。底层通过threadlocal来实现。
5 hibernate优化
一级缓存优化
批量操作时,手动清除缓存
查询策略(用默认的就行,默认都是延迟加载和单表查询)
A 类级别上的
@Proxy(lazy=false/true) 默认是true即延迟加载 比如load 延迟加载返回的是一个cglib生成的代理对象,只有主键标识,其它数据都为null。
通过hibernate.initalize(xxx) 来初始化一个代理对象 在spring中通过OpenSessionInViewFilter来解决延迟加载问题
B 关联级别
查询到某个对象,获得其关联的对象或属性,这种称为关联级别检索。
在一方的set集合上配置
@fetch(select,subselect,join) 表示关联查询的sql语句形式。 默认是select
@lazycollection(true,false,extra) extra表示及其懒惰 默认是true
在多方的一方对象引用上配置
@fetch(select,join) 默认select
@lazytoone(false,proxy ) proxy 默认值 是否采用延迟,需要另一方的类级别延迟策略来决定
n+1问题
|