一.一对多的关系映射 1.配置文件中的配置:
<set name="linkmans" table="cst_linkman">
<key column="lkm_cust_id"></key>
<one-to-many class="CstLinkMan"/>
</set>
2.元素
*set元素: 作用:用于映射集合属性
属性:name:指定集合属性的名称 table:指定集合中元素对应的表
*key元素:作用:用于映射外键的,一般只出现在set元素的内部
属性:column:指定表中外键字段的名称
*one-to-many元素: 作用:指定当前实体类与目标实体类的映射关系
属性:class:指定目标实体类的名称
二.多对一关系映射
1.配置文件中的配置:
<many-to-one name="customer"class="CstCustomer" column="lkm_cust_id"/>
2.元素:
*<many-to-one />:作用:当前映射实体和实体中的引用之间的关系
属性:name:指定关系对象引用类型的名称
class:引用对象的类型
column:指定多的一方中外键的字段
三.关系映射的级联配置
1.set元素里面的属性配置(一对多)
cascade:级联操作
取值:save-update:级联保存操作
delete:级联删除
<set name="linkmans" table="cst_linkman" cascade="save-update,delete">
<key column="lkm_cust_id"></key>
<one-to-many class="CstLinkMan"/>
</set>
2.多对一关系映射
<many-to-one>中元素的属性:
cascade:级联操作
取值:save-update:级联保存更新
<many-to-one name="customer"class="CstCustomer" column="lkm_cust_id" cascade="save-update"/>
3.一对多双向关系映射放弃维护权利
set元素的属性:inverse:是否放弃维护的权利
取值:true:放弃 false:不放弃(默认值)
注意:在一对多关系映射上,inverse属性永远配置在set元素上
<set name="linkmans" table="cst_linkman" cascade="save-update" inverse="true">
<key column="lkm_cust_id"></key>
<one-to-many class="CstLinkMan"/>
</set>
4.多对多关系映射
set元素:映射集合元素;
属性:name:指定集合属性的名称 table:指定的是中间表的名称
key元素:用于指定外键
属性: column:指定当前实体类在中间表的外键
many-to-many元素:指定当前实体类与集合属性的关系
属性:class:指定集合中元素的类型 column:指定的是集合属性元素在中间表的外键名称
<set name="roles" table="sys_user_role">
<key column="user_id"></key>
<many-to-many class="SysRole" column="role_id"></many-to-many>
</set>
四.知识点
1.HQL:Hibernate Query Language
2.query对象:Query query = session.createQuery("from CRMCustomer");
3.关于缓存
*什么时候用缓存:非敏感数据/不经常修改的数据/出现的一些小错误是在允许的范围之内
*与一级缓存有关的方法:
*flush() --它的出现,表明手动执行快照机制
*refresh() --是用数据库中的数据去修改缓存的数据,同时也会修改内存对象
*evict(Object entity) --清除一级缓存中指定的对象
*close() --关闭session,证明session已经不能用了
*clear() --清除session中的所有的一级缓存
4.hibernate对象状态的判断依据:是否有OID ,是否和session有关系
5.merge(Object entity) --把两个具有相同OID的对象进行合并
6.一对多关系映射中出现的问题(单向关联关系)
*先保存联系人,在保存客户时,会多一条update的语句
解决:先保存客户,再保存联系人
*修改一个联系人,为其重新分配一个客户时,就会报错,因为一个持久态或者脱管态对象关联了一个临时态对象
解决:在映射文件中配置级联更新:cascade="save-update"
6.一对多关系映射中出现的问题(双向关联关系)
*先保存联系人,在保存客户时,会多一条update的语句
解决:让有集合的一方的集合放弃维护关联关系的权利:inverse="true"
*修改一个联系人,为其重新分配一个客户时,就会报错,因为一个持久态或者脱管态对象关联了一个临时态对象
解决:在映射文件中配置级联更新:cascade="save-update"
五.Hibernate的检索方式(五种)
1.OID检索
get(Customer.class,1l)或者load(Customer.class,2l)
2.对象导航检索
根据条件查找对象实体类,然后根据实体类关联的对象进行对象检索
3.HQL(Hibernate Query Language) 检索
*基本查询:
Query query = session.createQuery("from Customer");
List<Customer> list = query.list();
*排序查询:
Query query = session.createQuery("from Customer order by cust_id desc");
*条件查询:
*按照位置绑定参数:
Query query = session.createQuery(from Customer where cust_id=?);
query.setString(0,2l);
或者:query.setParameter(0,2l);
*按照名称绑定参数:
Query query = session.createQuery("from Customer where name=:name");
query.setParameter("name","");
*分页查询:
Query query = session.createQuery("from Customer order by cust_id");
query.setFirstResult(0);
query.setMaxResults(3);
*统计查询:
Query query = session.createQuery("select count(*) from Customer");
Long num = (Long)query.uniqueResult();
*投影查询:
要求:实体类必须要有对应参数的构造方式
List<Customer> customers = session.createQuery("select new Customer(cust_id,cust_name) from Customer ").list();
4.QBC(Query By Criteria)检索
*简单查询:
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> customers = criteria.list();
*条件查询:
Criteria criteria = session .createCriteria(Customer.class)
criteria.add(Restrictions.eq("custName",""))
criteria.add(Restrictions.gt("custId",1l));
criteria.add(Restrictions.like("cusName","%小%"))
*分页查询:
Criteria criteria = session.createCriteria(Customer.class);
criteria.setFirstResult(0);
criteria.setMaxResult(4);
*排序查询:
Criteria criteria = session.createCriteria(Customer.class)
criteria.addOrder(Order.desc("custId"))
*投影查询:
Criteria criteria = session.createCriteria(Customer.class);
criteria.setProjection(
Projections.projectionlist()
.add(Projections.property("custName"))
.add(Projections.property("custId"))
);
*离线条件查询:(DetachedCriteria---SSH整合经常使用,可以脱离session进行参数设置)
publicvoid test05(){
//获得一个离线条件查询的对象
DetachedCriteria dc =DetachedCriteria.forClass(CRMCustomer.class);
dc.add(Restrictions.eq("custId",2l));
Session session =HibernateUtils.getCurrentSession();
Transaction ts = session.beginTransaction();
//离线条件查询对象与session绑定
List<CRMCustomer> list = dc.getExecutableCriteria(session).list();
for(CRMCustomer cust : list){
System.out.println(cust);
}
ts.commit();
}
5.SQL检索
*就是一般的SQL语句
六.HQL的连接查询:
*内连接:
*隐式内连接:select * from customer c,linkman l where c.id=l.id
*显式内连接:select * from customer c inner join linkman l on c.id=l.id
*迫切内连接:select distinct c from customer c inner join fetch c.linkman
*内连接与迫切内连接的区别:
*内连接:发送的就是内连接的语句,封装的时候将每条记录封装到一个Object[]数组中,最后得到一个List<Object[]>
*迫切内连接:发送的也是内连接的语句,在join后添加了fetch关键字,Hibernate会将每条数据封装到对象中(需要去掉重复值)
七.Hibernate的抓取策略(提升性能手段)
*检索策略:当使用某种检索策略时,所带来的好处
1.类级别检索策略
*查询的时机:
立即加载:不管用不用,只要查询一个实体,就把当前实体中的所有字段数据查询出来
延迟加载:如果只用当前实体类的OID,则不会发起查询,当需要实体类中其他字段时,才会发起查询
*明确:类级别的检索策略,只涉及当前类的字段数据,不涉及关联对象的数据
*涉及的方法
*get:永远都是立即加载,不管用不用对象中的其他数据,都查出来
*load:默认情况下是延迟加载,可以通过修改配置文件,改为立即加载
配置属性中修改class的属性lazy,默认值是true,改为false就是立即加载
*query.list():永远都是立即加载
2.关联级别的检索策略
*根据少的一方获取多的一方(一对多,多对多)
*配置:修改配置文件都是针对 set元素中的属性
*lazy属性:查询的时机
*fetch属性:查询的方式
序号
lazy的取值
fetch的取值
说明(都是以客户联系人一对多为例)
1
true(默认值)
select(默认值)
时机:用时才真正去查询联系人。
语句形式:多条SQL语句
Batch-size:设置批量检索的深度。(建议3~10之间)
2
false
select(默认值)
时机:不管用不用,查询客户时都立即查询联系人。
语句形式:有1条查询客户的和多条查询联系人的select语句。
Batch-size:设置批量检索的深度。(建议3~10之间)
3
extra
select(默认值)
时机:用什么信息,查什么信息。只查询必要的。
语句形式:有1条查询客户的和多条查询联系人的select语句。
batch-size:设置批量检索的深度。(建议3~10之间)
4
true
subselect
时机:用时才真正去查询联系人。
语句形式:子查询
batch-size:无效
5
false
subselect
时机:不管用不用联系人,查询客户时都立即查询联系人。
语句形式:子查询
batch-size:无效
6
extra
subselect
时机:用什么信息,查什么信息。只查询必要的。
语句形式:子查询
batch-size:无效
7
true|false|extra
join(当join有效时,根本不看lazy属性)
时机:无效。因为连接查询,一次就是两张表及以上。
语句:left outer join
batch-size:无效
注意:Query查询会忽略join的存在。当join无效时,lazy就有效了。
*使用原则:延迟加载
*根据多的一方获取少的一方(多对一,一对一)
*配置:在<many-to-one>元素中配置lazy属性和fetch属性
*配置说明
序号
lazy
fetch
说明(用的是客户和联系人的一对多关系)
1
proxy
select
时机:
对象类级别的策略:true。延迟加载。得到的是代理对象。
对象类级别的策略:false。立即加载。得到就是类对象。
语句:
多条SQL语句
2
false
select
时机:立即加载。与对象类级别的策略无关。
语句:多条SQL语句。
3
true|false|extra
join(当join有效时,根本不看lazy属性)
时机:无效。因为连接查询,一次就是两张表及以上。
语句:left outer join
*使用原则:立即加载
八.Hibernate中使用c3p0数据源
1.copy必要的jar包
2.在hibernate主配置文件中配置
<property name="hibernate.connection.provider_class">
org.hibernate.connection.C3P0ConnectionProvider
</property>
3.验证数据源是否配置成功
@Test
publicvoid test(){
Session s =HibernateUtils.getSession();
s.doWork(newWork(){
@Override
publicvoid execute(Connection conn)throwsSQLException{
System.out.println(conn.getClass().getName());
conn.close();
}
});
}
九.hibernate中的二级缓存
1.hibernate中的缓存结构
2.二级缓存的数据被多线程共享,就必须有一定的事务访问策略
3.适合放入二级缓存中的数据
*很少被修改
*不是很重要的数据,允许出现偶尔的并发问题
4.类缓冲区:里面存的是对象中的数据,而不是对象
*get和load都可以存和取二级缓存中的数据
*Query.list("from CstCustomer")只能存不能取,因为是动态查询
5.集合缓冲区
*一对多关系映射中,操作多的一方就是集合.对应的实体类也要开启缓存配置
6.更新时间戳:当我们修改以及缓存中的数据时,会自动同步二级缓存中的数据,用的是时间戳原理
7.查询缓存区
*解决的问题:Query查询只能查不能取,因为语句是动态的
*解决办法:按照语句进行存储,使用Map<String,Object>,key是sql语句,value是查询的结果集,这个map就是查询缓存区,默认是关闭的
*使用:在hibernate.cfg.xml中配置
<property name="hibernate.cache.use_query_cache">true</property>
dao层设置:query.setCacheable(true)
0 0