1.hibernate中一级缓存指session级别的缓存,一个session做了一个查询操作,它会把这个操作的结果放到一级缓存中,如果这个session(一定要同一个session)又做了当从数据库查询数据时会先从一级缓存中去找,找不到再从数据库查。一级缓存会在session关闭时清除。
①list仅仅会填充二级缓存,却不能利用二级缓存
②iterator可以读二级缓存,对于一条查询语句,它会先从数据库中查找出符合所有条件的记录的id,然后根据id去缓存中找,若缓存中没有,再去数据库找。
①在多对一中one-to-many
如User与Grade,User为多的一方,则在User.hbm.xml可如下
二级缓存为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>