Hibernate学习(13-18)

第十三节  关联映射之单向多对多
 

Func.hbm.xml

<hibernate-mapping>
<class name="cn.sxt.pojo.Func" table="t_func">
<id name="id" column="id">
<generator class="native">
</generator>
</id>
<property name="name"/>
<property name="url"/>
</class>
</hibernate-mapping>

Role.hbm.xml
 

<hibernate-mapping>
<class name="cn.sxt.pojo.Role" table="t_role">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name"/>
<set name="funcs" table="t_role_func">
<!-- 是当前类在关联表中的外键列名 -->
<key column="rid"></key>
<!-- 当前类所对应的类 在关联表中的外键列名 -->
<many-to-many column="fid" class="cn.sxt.pojo.Func"/>
</set>
</class>
</hibernate-mapping>

 

 

1、 cascade 级联操作:表示当操作一个对象时,是否级联操作与之关联的对象。在 many-to-one
的映射中, 不建议使用 cascade=”delete”;如果 cascade 的值不为 none 时, 操作对象需要关联
对象的数据时, 会先操作关联对象。 在 one-to-many 中使用 cascade=”save-update”将会多出
更新 sql 语句;效率比较低, 不建议使用。
Many-to-one

<hibernate-mapping>
<!-- class 配置类 name 指类名 table 指定表名 如果不写, 默认类名
为表名-->
<class name="cn.sxt.pojo.User" table="t_user">
<id name="id" column="id">
<generator class="identity">
</generator>
</id>
<!-- property 是配置类的属性 name 指属性名 -->
<property name="name" length="40"/>
<property name="age" />
<!--
cascade 表示级联操作
none 默认值 不级联
save-update 保存更新时级联
delete 删除时级联
all 所有动作都级联
-->
<many-to-one name="role" column="roleId" cascade="all"/>
</class>
</hibernate-mapping>

 Inverse 是(集合端)的一个属性表示由谁来管理关系(在双向映射)。
Inverse=”true”表示由关联关系的另一端来管理关系;inverse 管理的是关联关系, cascade
管理的级联关系。 建议管理关联关系由多的一端来关联。

HQL: hibernate query language; hibernate 查询语言; 是一个面向对象的查询;
Hql 对关键字大小写不敏感
 

public class HibernateTest {
//hql 查询
//from
@Test
public void testFrom(){
Session session = HibernateUtil.getSession();
//相当于 select * from t_role
String hql="from cn.sxt.pojo.Role";
//创建 Query 对象
Query query = session.createQuery(hql);
//查询
List<Role> list = query.list();
for(Role r:list){
System.out.println("角色名: "+r.getName());
}
}/
/设置别名 可以使用 as 关键字 也可以 在类名后加 空格 和别名
@Test
public void testFrom1(){
Session session = HibernateUtil.getSession();
//相当于 select * from t_role
String hql="from cn.sxt.pojo.Role r";
//创建 Query 对象
Query query = session.createQuery(hql);
//查询
List<Role> list = query.list();
for(Role r:list){
System.out.println("角色名: "+r.getName());
}
}/
/where 语句
@Test
public void testWhere(){
Session session = HibernateUtil.getSession();
//根据 id 查询时 使用 get/load 会更好
String hql="from Role where id=1";
List<Role> list = session.createQuery(hql).list();
for(Role r:list){
System.out.println("角色名: "+r.getName());
}
}

加载策略: 即时加载和延迟加载
即时加载: 指当查询数据时直接将该数据从数据库中查询(get)
延迟加载(懒加载) : 当真正使用数据时, 才从数据库中查询数据(load)
 

public class HibernateTest {
@Test
public void testGet(){
Session session = HibernateUtil.getSession();
//即时加载
User u = (User)session.get(User.class, 1);
System.out.println("id="+u.getId());
System.out.println("----------");
System.out.println("name="+u.getName());
}@
Test
public void testLoad(){
Session session = HibernateUtil.getSession();
//延迟加载
User u = (User)session.load(User.class, 1);
System.out.println("id="+u.getId());
System.out.println("----------");
System.out.println("name="+u.getName());
}
}

2
、 lazy 属性---指定是否启动懒加载
对应 class 来说, 默认是懒加载的。
Property 的 lazy 默认是即时加载的。 当属性是大对象的时候使用延迟加载。
Many-to-one:false--不使用懒加载;当取多的一端数据时会将一的取出来
no-proxy:属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)
(需要运行时字节码的增强) 。
Proxy(默认) :使用代理来实现懒加载
Set 的 lazy:true(默认) 使用懒加载
False:不使用懒加载
extra:一种比较聪明的懒加载策略, 即调用集合的 size/contains 等方法的时候, hibernate
并不会去加载整个集合的数据, 而是发出一条聪明的 SQL 语句, 以便获得需要的值, 只有在真正需要用到
这些集合元素对象数据的时候, 才去发出查询语句加载所有对象的数据
3、 抓取策略: select/join
Select 抓取: 表示查询关联对象时, 使用 select 语句。 (在 select 抓取下, 可以用 lazy)
Join 抓取: 查询关联对象时, 使用 join 连接语句。 Lazy 没有意义(没有作用) 。
subselect 抓取: 如果要查询关联集合的内容。 会查询之前已经查出的对象的所有关联集
合。 (Category 对应了多个 Book)如果查询了(”文学”,”历史”) ; 那么在使用(lazy=true) ”
文学”或”历史”的集合对象(”所对应的书籍信息”) .会将(“文学”和”历史”)的书籍信息一起查
询。 如果 lazy=false; 在查询“多个分类时” 会将所有分类的书籍信息一起查询。
 

 

 

1、 缓存分类:
一级缓存
二级缓存
查询缓存
2、 一级缓存: 又称为 Session 缓存, 由 Session 来管理; 和 Session 的生命周期相同。 是事
务级别的缓存(线程);
3、 get 方法去查询数据时, 首先检查缓存中是否有该数据。 如果缓存中有该数据, 直接取缓
存中的数据。 如果缓存中没有, 则查询数据库; 并且将该数据写入 Session 缓存中。
 

4、 load 方法: 查询数据, 首先检查是否必须查询对象的属性。 如果需要查询, 那么检查缓
存中是否有, 如果缓存中有该对象, 则取缓存中的数据。 如果缓存中没有, 那么取数据中数
据; 并且将该数据写入缓存;
 

5、 list 方法: 查询数据, 不会检查 Session 缓存中是否有数据, 当从数据库中查询数据以后,
会将对象写入 Session 缓存。
 

6、 n+1 和 1 的问题: iterate()方法--首先查询所有的 Id, 当使用对象时, 再根据 id 到数据库
中查询该对象。 所以如果查询所有数据, 那么将执行 n+1 条 sql 语句。 而 list 查询所有数据
只执行 1 条 sql 语句。 因此, 当查询所有对象时应该使用 list,而如果查询的是部分数据, 那
么使用 iterate
 

7、 iterate 方法首先会查询所有 id,根据 id 查询数据时, 首先检查缓存是否有该对象, 如果有,
则取缓存中的数据, 如果没有则到数据库中查询, 并且将查询结果写入 Session 缓存中。
 

8、 一级缓存的管理
clear 方法: 清空缓存中的所有数据; 清空以后当再次查询数据时会从数据库中重新查

flush 方法: 将缓存中的数据与数据库中的数据同步
 

evict 方法:清除缓存中指定的对象
close 方法: 关闭 session 对象, 释放缓存;
9、 二级缓存: SessionFactory 缓存; 和 SessionFactory 生命周期相同; 是进程级别的缓存;
使用第三方提供的二级缓存插件
10、 二缓存的实现步骤:
a): 导入 jar 包
ehcache-core-2.4.3.jar
hibernate-ehcache-4.3.10.Final.jar
slf4j-api-1.6.1.jar
b): 导入 ehcache.xml 配置文件 放入 src 下---hibernate-release-4.3.10.Final\project\etc
c): 配置 hibernate.cfg.xml
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值