hibernate学习笔记(三)

本文详细介绍了Hibernate中的一级缓存与二级缓存机制,包括缓存的工作原理及应用场景,并深入探讨了不同类型的查询如何利用缓存提高效率。此外,还详细解释了Hibernate中的对象生命周期状态以及在一对多、多对多关系中的映射配置。
摘要由CSDN通过智能技术生成
1.hibernate中一级缓存指session级别的缓存,一个session做了一个查询操作,它会把这个操作的结果放到一级缓存中,如果这个session(一定要同一个session)又做了当从数据库查询数据时会先从一级缓存中去找,找不到再从数据库查。一级缓存会在session关闭时清除。

二级缓存为Sessionfactory级别的缓存,如果同一个sessionFactory创建的某个session执行了相同的操作,hibernate就会从二级缓存中查结果,而不会连接数据库,需要配置。

2.缓存中存放的是键值对,而通过list查询的结果会放入二级缓存,但list本身查询时不会使用二级缓存,因为list里边没有id

缓存会将对象以key-value存储起来,key为完整类名 + # + id,如

com.bjsxt.po.User#3
3.在一对多中,经常出现1+N问题,这表示一个sql语句查询引起N个sql语句执行。解决方案为懒加载或使用二级缓存。懒加载可为

@OneToMany(mappedBy="grade",fetch=FetchType.LAZY)
4.List和iterator区别
①list仅仅会填充二级缓存,却不能利用二级缓存
②iterator可以读二级缓存,对于一条查询语句,它会先从数据库中查找出符合所有条件的记录的id,然后根据id去缓存中找,若缓存中没有,再去数据库找。

5.hibernate对象生命周期经历三种状态,以程序来说明
①transient(游离态),它在内存中是自由存在的,与数据库没有任何关系

//创建一个Transient对象
User user = new User();
user.setName("username");
user.setPwd("password");
//此时user为游离态,没有与任何数据库的记录相关联,也与session没有任何关系
②persistent(持久态),与session和数据库都有关系

//创建一个Transient对象
User user = new User();
user.setName("username");
user.setPwd("password");
//此时user为游离态,没有与任何数据库的记录相关联,也与session没有任何关系

Session session = sessionFactory.openSession();
Transaction tx1 = session.beginTransaction();
//此时的user仍为一个transient(游离态)对象

session.save(user);//此时的user为persistent(持久态)对象
tx1.commit();//提交后向数据库加入一条记录
Transaction tx2 = session.beginTransaction();
uesr.setPwd("abc");
tx2.commit();
//虽然在这个事务中没有调用Session的save方法来保存save对象,但由于user
//对象处于persistent状态,所以对user所做的任何修改都将被持久化到数据库
//所以这时数据库的密码已经修改为abc
③detached(游离态),有影响。游离态实体对象在数据库中有相应的记录(从持久态遗留下来的),如果没有被其它事务删除。但对对象所做的任何操作不再会对数据库
//创建一个Transient对象
User user = new User();
user.setName("username");
user.setPwd("password");
//此时user为游离态,没有与任何数据库的记录相关联,也与session没有任何关系

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//此时的user仍为一个transient(游离态)对象

session.save(user);//此时的user为persistent(持久态)对象
tx.commit();//提交后向数据库加入一条记录
session.close();
//此时的user为detached(游离态),此时对user所进行的任何操作,都不会对数据库有任何影响
6.在配置hibernate的映射文件时,有generator class="native",表示设置主键自增

<id name="gid">
	<generator class="native"></generator><!-- 表示设置主键自增 -->
</id>
在类似于<one-to-many>等中,当前表对象对应前者,class数据对应后者。如在Department-Employee的一对多关系中,在Employee.hbm.xml是这么写

<many-to-one column="did" class="Department">
<!--class对应的即为one的一方-->

<property name="ename" column="name"></property>
<property name="eid"></property>
<!-- column="name"对应数据库中的字段名,要是不写,那么默认对应的即为属性名。如此时数据库中字段为name,eid -->
7.下面说说映射文件如何配置
①在多对一中one-to-many
如User与Grade,User为多的一方,则在User.hbm.xml可如下

<hibernate-mapping package="com.bjsxt.po">
	<class name="User" table="t_user">
		<id name="id">
			<generator class="native"></generator>
		</id>
		<property name="name" ></property>
		<property name="tel" ></property>
		<!--关键还是看下边这配置-->
		<many-to-one name="grade" class="Grade"><!-- class处该为com.bjsxt.po.Grade,但前边已加了包名,所以可以省略 -->
			<column name="grade_id"></column><!--grade_id是自己写的,Grade里没有该属性-->
			<!--grade_id与Grade.hbm.xml中的key column值相同,否则会出现多个外键  -->
		</many-to-one>
	</class>
</hibernate-mapping>

Grade.hbm.xml如下

<hibernate-mapping package="com.bjsxt.po">
	<class name="Grade" table="t_grade">
		<id name="gid">
			<generator class="native"></generator><!-- 设置主键自增 -->
		</id>
		<property name="gname" ></property>
		
		<set name="setUser">
			<key column="grade_id"></key><!--此时grade_id也是自己所设,Grade没有该属性-->
			<!--key column是指在多的一方,即User添加一个名为 grade_id的字段,
			配置的值为当前配置文件中主键的值,即gid。这实现了主外键关联 -->
			<one-to-many class="User" />
		</set>
	</class>
</hibernate-mapping>

②在多对多many-to-many中,需要产生一个中间表,方便查找。
如选课时,User与Course为多对多,那么User.hbm.xml可如下

<hibernate-mapping package="com.bjsxt.po">
	<class  name="User"  table="t_user" >
		<id  name="uid"  >
			<generator class="native"></generator>		
		</id>
		<property name="name" ></property>
		
		<set name="courses"  table="user_course" ><!--user_course即为中间表-->
			<key>
				<column name="user_id"></column><!--设置user_id为中间表主键,中间表可有多个主键-->
			</key>
			<many-to-many  class="Course"  column="course_id" ></many-to-many>
		</set>
	</class>
</hibernate-mapping>
这个<set>集合可以这么理解,在User.hbm.xml中,set集合中存的是课程,所以在<key>中的column name="user_id"表示一门课程由哪些学生(根据id查找)来选,底下的column="course_id",表示一个学生选了哪些课(根据course_id来找)。下边的都类似



而Course.hbm.xml如下

<hibernate-mapping package="com.bjsxt.po">
	<class  name="Course"  table="t_course" >
		<id  name="cid"  >
			<generator class="native"></generator>		
		</id>
		<property name="cname"    ></property>
		
		<set name="users"  table="user_course" ><!--中间表-->
			<key>
				<column name="course_id"></column><!--中间表的另一个主键-->
			</key>
			<many-to-many  class="User"  column="user_id"></many-to-many>
		</set>
	</class>
</hibernate-mapping>


产生的中间表如下:

可以看到,在映射表<set>中设置了中间表的主键,主键可以有多个。

下边给出一张总结性的图:

8.若在一个jsp下拉框想获取数据库的值,在页面载入时就展示出这些值,可以用s标签的action,比用继承监听器要简单。

<s:action name="departmentAction!findAll" namespace="/"  var="dep"  ></s:action>

<SELECT  name="employee.department.id"  >
	<s:iterator  value="#dep.list"  var="obj"  >
		<option value="${obj.id }" >${obj.dname }</option>
	</s:iterator>	
</SELECT>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值