持久化框架
五、关联关系
1.多对一
在多方配置和一方的关联关系,实体类中和映射文件中。
Student类:
public class Student {
private Integer sid;
private String sname;
private Date birthday;
private School school; //依赖School
//省略 getter setter
}
对应的映射文件:
<class name="com.wdzl.entity.Student" table="student">
<id name="sid" column="sid">
<generator class="native"></generator>
</id>
<property name="sname">
<column name="sname"></column>
</property>
<property name="birthday" column="birthday"/>
<!--********多对一**********-->
<many-to-one name="school" class="com.wdzl.entity.School">
<column name="scid"></column>
</many-to-one>
</class>
2. 一对多
实体类 School 中:声明 Set 结合存放多方 Student 对象:
public class School {
private Integer scid;
private String scname;
private String address;
// 关联 student
private Set<Student> students = new HashSet<>();
//省略 getter setter
}
对应的映射文件:
<class name="com.wdzl.entity.School" table="school">
<id name="scid" column="scid">
<!--主键生成策略:
assigned:程序给定主键
native:数据库本地负责主键
-->
<generator class="native"></generator>
</id>
<property name="scname" column="scname"></property>
<property name="address" column="address"></property>
<!--***********一对多**************-->
<set name="students">
<key><column name="scid"></column></key>
<one-to-many class="com.wdzl.entity.Student"></one-to-many>
</set>
</class>
使用关联关系
查询
a) 在多方关联查询一方:
public void manyToOne(){
Student student = session.get(Student.class, 1);
String sname = student.getSname();
//关联查询一方学校对象
School school = student.getSchool();
System.out.println(sname+"=="+school.getScname());
System.out.println(school.getScid());
session.close();
}
b) 在一方关联查询多方:
public void oneToMany(){
School school = session.get(School.class, 1);
System.out.println("学校名:"+school.getScname());
System.out.println("学校下的所有学生:");
Set<Student> students = school.getStudents();
for (Student student : students) {
System.out.println(">>>="+student.getSname());
}
}
保存
级联保存:通过多方级联保存一方对象入库,先在多方增加级联属性 cascade=“save-update”
<many-to-one name="school" cascade="save-update" class="com.wdzl.entity.School">
<column name="scid"></column>
</many-to-one>
代码: 在多方对象中设置一方对方,进行关联依赖。
public void saveStudent2(){
Transaction transaction = session.beginTransaction();
//先查询学校对象
School school = new School();
// school.setScid(3);
school.setScname("西安二中");
school.setAddress("西安经九路");
Student student = new Student();
student.setSname("诸葛亮");
student.setBirthday(new Date());
//给学员分配一个新的学校
student.setSchool(school);
//通过学生 级联保存学校
session.save(student);
transaction.commit();
}
3.级联删除
案例:通过一方学校,级联删除学生。
会有两种情况:
a.
先解除关系,然后删除多方,最后删除一方
b.
直接删除多方,最后删除一方。
4.延时加载 lazy
<many-to-one name="school" fetch="join" lazy="proxy" cascade="save-update" class="com.wdzl.entity.School">
<column name="scid"></column>
</many-to-one>
<set name="students" lazy="true" inverse="true" cascade="delete">
<key><column name="scid"></column></key>
<one-to-many class="com.wdzl.entity.Student"></one-to-many>
</set>
5. 抓取策略
在多方的节点上<many-to-one fetch=“join|select” ,默认select 。
在一方的节点上
六、HQL
HQL: Hibernate Query Language
HQL :
a. 支持对象查询、update修改、delete删除
b. 支持分组group by,having ,聚合函数 count(*),avg(),sum(),max(),min()
c. 支持排序 order by ,条件 where, 子查询,distinct
d . 不支持 select * ,insert into
e. 支持分页
1. 返回元素类型
查询全部:
from Student
或
select student from Student student
返回结果:List 中元素为 Student 对象
查询多列:
select sid,sname from Student
返回结果:List 中元素为 Object[]
查询单个属性(列):
select sid from Student
返回结果:List 中元素为所查属性的类型
2.命名参数查询
String hql = "from Student where sname=:sname and sid=:sid";
Query query = session.createQuery(hql);
query.setParameter("sname","xxxx");
query.setParameter("sid",8);
//给问号占位符赋值
List<Student> list = query.list();
for (Student student : list) {
System.out.println(student.getSname());
}
3. 聚合函数
String hql = "select avg(sid),count(*),sum(sid),max(sid),min(sid) from Student";
Query query = session.createQuery(hql);
Object[] res = (Object[]) query.uniqueResult(); //唯一结果
System.out.println(res[0]+"=="+res[1]);
4. 修改和删除
Transaction transaction = session.beginTransaction();
// String hql = "update Student set sname='AAA' where sid>9";
String hql = "delete from Student where sid>9";
Query query = session.createQuery(hql);
int i = query.executeUpdate();
System.out.println(i);
transaction.commit();
5. 分页
public void page(){
int rowsPerPage = 2;
int pageNo = 2;
String hql = "from Student";
Query query = session.createQuery(hql);
//每页记录数
query.setMaxResults(rowsPerPage);
int start = (pageNo-1)*rowsPerPage;
//设置开始位置
query.setFirstResult(start);
List<Student> list = query.list();
for (Student o : list) {
System.out.println(o.getSname());
}
}
6. 子查询
查询年龄大于平均年龄的学生
public void subselect(){
String hql = "from Student where age > (select avg(age) from Student)";
Query query = session.createQuery(hql);
List<Student> list = query.list();
for (Student student : list) {
System.out.println(student.getSname()+"=="+student.getAge());
}
}
七、缓存
1. 三态
/**
* hibernate 三态:瞬时态、游离态、持久态
* 缓存 数据库
* 瞬时 没 没
* 游离 没 有
* 持久 有 有
*/
2. Session 常用方法
session.get() : 根据ID获取对象
session.evit(obj): 将对象从缓存中移除
session.contains(obj) : 缓存中是否包含对象
session.clear() : 清空缓存
session.close() : 关闭session
session.refresh(obj): 刷新同步,内存中瞬时对象和数据库同步,session同步和管理对象。
3.二级缓存配置
a. 下载jar ,Hibernate5 需要三个:ehcache-2.10.6.jar、hibernate-ehcache-5.4.3.Final.jar、slf4j-api-1.7.25.jar
在Hibernate官方API中查找,位置: hibernate-release-5.4.3.Final\lib\optional\ehcache
b. 开启二级缓存 在hibernate.cfg.xml中
<property name="cache.use_second_level_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property>
true 开启二级缓存
指定提供二级缓存的类:
org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
c. 在映射文件中配置缓存策略 隔离级别
<cache usage="read-only"></cache>