首先,上图...
![](https://img.haomeiwen.com/i3722442/f5c41dd683192051.png)
上面的是hibernate中经常用到的知识点,我们一个一个看.
一 工作流程
- 读取并解析配置文件
- 读取并解析映射信息,创建SessionFactory
- 打开Sesssion
- 创建事务Transation
- 持久化操作
- 提交事务
- 关闭Session
- 关闭SesstionFactory
jdbc 流程:
- 加载驱动mysql
- 获取连接
- 预编译
- 执行sql
- 将数据存入结果集
- 关闭数据库
jdbc和hibernate区别:
jdbc优点:
SQL应用灵活
数据库移植
jdbc缺点:
不便于维 代码繁琐 护 效率低
hibernate 框架 优点:
真正基于ORM模型
脱离java代码 降低耦合度
操作简单,易用
缺点:
不便于操作表结构复杂的sql
不便于数据库移植(跨数据库移植)
代替了jdbc技术,是一个全封装的框架,不便于调试bug
什么时候用hibernate框架
表数量少 结构不复杂,快速应用它来开发
hibernate中的缓存技术:
1.只是一次连接数据库,多次使用
- 数据是存在缓存区里的,操作:session.get() session.save(),session.delete().
3.分为二级缓存:
一级缓存:session 存在 内存的缓存区中
清理一级缓存的方式:
clear() 方法清理缓存直接从硬盘中的数据库读取
evict(对象) 执行的是数据库中的查询,第一次查询会失效
二级缓存:sessionFactort 存在 硬盘中
Hibernate 缓存执行顺序
当 Hibernate 根据 ID 访问数据对象时,首先会从一级缓存 Session 中查找。若查 不到且配置了二级缓存,则会从二级.
缓存中查找;若还查不到,就会查询数据库,把结 果按照 ID 放入到缓存中。执行增、删、改操作时,会同步更新缓存。
二级缓存内容分类
根据缓存内容的不同,可以将 Hibernate 二级缓存分为三类: (1)类缓存:缓存对象为实体类对象 (2)集合缓存:缓存对象为集合类对象 (3)查询缓存:缓存对象为查询结果
hibernate框架中get方法和load方法获取对象的方式有什么不同:
get和load方法都是根据id去获得对应数据的,但是获得机制不同:如果使用get方法,hibernate会去确认该id对应的数据是否存在,它首先会去session中去查询(session缓存其实就hibernate的一级缓存),如果没有,再去二级缓存中去查询,如果再没有,就去数据库中查询,仍然没有找到的话,就返回null
而使用load方法的话,hibernate会认定该id对应的数据一定存在,它也会先去session缓存中去查找,如果没有找到,hibernate会根据lazy属性值来确定是否使用延迟加载。如果lazy=‘true’ ,就使用延迟加载,返回该代理对象,等到真正访问到该对象的属性时才会去二级缓存中查询,如果没有,再去数据库中查询,如果还没有,就抛出org.hibernate.ObjectNotFoundException异常。如果lazy='false' 则不使用延迟加载,这是load的访问机制就和get一样了。
事物的特性:
1.原子性(不许分割)
2.一致性(两个事物可以有添加和减少)
3.隔离性(两个事物在执行过程中,相互不影响)
4.持久性: (两个事物执行完毕后,影响一直有效)
hibernate对象的状态
1.对象的临时状态 Emp e = new Emp("hah", 1000.0, 21, date);
2.对象的持久化状态 session.save(e);
st.commit();
3.对象的游离状态session.close();
事物是连接java代码和数据库的桥梁
hibernate框架中表之间的关系:
一对多
hibernate中级联删除:更改级联关系为 cascade="delect";
删除班级,删除学生 有外键
直接删除:班级信息置为null 学生信息不变
:更改级联关系为 cascade="delect" 根据外键,删除当前表及其有关系的其他表,删除有外键有关系的表
一对多
在进行解除关系或者删除的时候 One-to-many比较简单,执行的效率高 其他操作的时候many_to-one效率高
One-to-many 类和集合的关系
many-to-one 类和对象的关系
多对一(双向)
以Student-classes表为例 一个班级有更多学生同样更多学生在一个班级
建立 Student 和Classes的实体类
//Classes表中的属性 注意学生集合
private Integer c_id;
private String c_name;
private Set<Student> stus;
//student表中的属性
private Integer s_id;
private String s_name;
//建立关系: 多个学生 一个班级
private Classes cls;
//classes表的映射文件
<hibernate-mapping>
<class name="cn.lanou3g.vo.Classes" >
<id name="c_id">
<generator class="increment" />
</id>
<property name="c_name"/>
<!-- 搭建一对多的关系 inverse是否维系关系 默认false
cascade 级联关系 save-update 保存或更新的时候维系关系
delete 级联删除-->
<set name="stus" inverse="false" cascade="save-update">
<!--从表的外键 -->
<key column="c_id"></key>
<!-- 指定对应关系 它是stus对应的实体类-->
<one-to-many class="cn.lanou3g.vo.Student"/>
</set>
</class>
</hibernate-mapping>
//Student的映射文件
<hibernate-mapping>
<class name="cn.lanou3g.vo.Student">
<id name="s_id">
<generator class="increment"/>
</id>
<property name="s_name"/>
<!-- 建立关系 cls 多对一 cascade 级联关系-->
<many-to-one name="cls" class="cn.lanou3g.vo.Classes" cascade="save-update">
<!-- 这里的外键,要与one-to-many对应的外键一致 -->
<!-- column 指定从表的外键-->
<column name="c_id"></column>
</many-to-one>
</class>
</hibernate-mapping>
public class TextCon {
Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
@Test
public void textConn(){
//新建配置对象 目的是自动加载配置文件
Configuration cfg = new Configuration();
cfg.configure();//自动加载主配置文件
//开启session工厂
SessionFactory sf=cfg.buildSessionFactory();
}
//保存学生 保存班级
//@Test
public void textaddStuandcls(){
//新增班级
Student stu = new Student();
stu.setS_name("momo");
//新增班级
Classes cls = new Classes();
cls.setC_name("java");
//通过学生保存班级
stu.setCls(cls);
session.save(stu);
ts.commit();
}
//更新学生 级联保存班级
//@Test
public void textupdateStuandcls(){
Student stu = (Student)session.get(Student.class, 1);
stu.setS_name("lida");
session.save(stu);
ts.commit();
}
//给学生赋班级
//@Test
public void testUpdateStu(){
Student stu = (Student)session.get(Student.class, 2);
Classes cls = (Classes)session.get(Classes.class, 1);
stu.setCls(cls);
session.save(stu);
ts.commit();
}
//解除一个班级和所有学生之间的关系(注意保存班级)
// delect() 两表都删除
//update 外键为null
@Test
public void testdelStuandcla(){
Classes cls = (Classes)session.get(Classes.class, 1);
//Student stu = (Student)session.get(Student.class, 1);
//cls.setStus(null);//级联关系改为null
session.update(cls);
ts.commit();
}
}
多对多:
以course-student表为例 很多课程被很多学生选择
//student表中的属性
private Integer s_id;
private String s_name;
private Set<Course> cours;
//coutse表中的属性
private Integer c_id;
private String c_name;
//建立联系 多对多 多个课程被多了学生选择
private Set<Student> stus;
//Course表中映射文件
<hibernate-mapping>
<class name="cn.lanou3g.vo.Student">
<id name="s_id">
<generator class="increment"/>
</id>
<property name="s_name"/>
<!-- 建立关系 cls 多对一 cascade 级联关系-->
<set name="cours" table="student_course" cascade="all">
<key column="s_id"/>
<many-to-many class="cn.lanou3g.vo.Course" column="c_id"/>
</set>
</class>
</hibernate-mapping>
//student的映射文件
<hibernate-mapping>
<class name="cn.lanou3g.vo.Course">
<id name="c_id">
<generator class="increment"/>
</id>
<property name="c_name"/>
<!-- 建立关系 cls 多对一 cascade 级联关系-->
<set name="stus" table="student_course" cascade="all">
<key column="c_id"/>
<many-to-many class="cn.lanou3g.vo.Student" column="s_id"/>
</set>
</class>
</hibernate-mapping>
public class TextCon {
Session session=HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
@Test
public void textConn(){
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory sf = cfg.buildSessionFactory();
}
//添加一个新课程 添加一个新学生
//先保存主表 在保存从表
//@Test
public void textinsert(){
Student stu = new Student();
Course cours =new Course();
stu.setS_name("box");
cours.setC_name("java");
Set<Student> stus = new HashSet<Student>();
stus.add(stu);
cours.setStus(stus);
session.save(cours);
ts.commit();
}
//获取学生 修改学生姓名 课程中添加修改后的学生姓名
//@Test
public void textUpdatestu(){
Student stu = (Student)session.get(Student.class, 1);
stu.setS_name("灿烈");
Course cours = (Course)session.get(Course.class, 1);
Set<Student> stus = new HashSet<Student>();
stus.add(stu);
cours.setStus(stus);
session.save(cours);
ts.commit();
}
//解除课程1和所有学生的关系
//解除课程1和所欲学生之间的关系
//多对多关系的删除,只影响中间表,其他关联表不动
//设置学生为null
//@Test
public void textdel(){
Course cours = (Course)session.get(Course.class, 1);
cours.setStus(null);
session.save(cours);
ts.commit();
}
//删除课程1下编号为1 的人
//解除一个学生和一个课程的关系(值删除中间表)
//多对多中单条删除用集合中的remove()进行删除
@Test
public void textdelmid(){
Course cours = (Course)session.get(Course.class, 2);
Student stu = (Student)session.get(Student.class, 2);
Set<Course> c = stu.getCours();
c.remove(cours);
session.save(cours);
ts.commit();
}
}
一对一
以person-card为例 一个人只有一个身份证
//card的属性
private Integer c_id;
private String c_name;
private Person c_p;
//person的属性
private Integer p_id;//主键
private String p_name;
private Card p_c;
//card的映射文件
<hibernate-mapping>
<!-- 引入实体类的全类名 -->
<class name="cn.lanou3g.entity.Card">
<!-- 主键字段 -->
<id name="c_id">
<generator class="increment"/>
</id>
<!--普通字段 -->
<property name="c_name"/>
<!-- 直接指定对应关系
name 在当前类中存在的类类型
class name属性对应的全类型
cascade 对当前表的操作crud
constrained="false"代表当前表是主表-->
<one-to-one name="c_p" class="cn.lanou3g.entity.Person" cascade="all" constrained="true"/>
</class>
//Person的映射文件
<hibernate-mapping>
<!-- 引入实体类的全类名 -->
<class name="cn.lanou3g.entity.Person">
<!-- 主键字段 -->
<id name="p_id">
<generator class="increment"/>
</id>
<!--普通字段 -->
<property name="p_name"/>
<!-- 直接指定对应关系
name 在当前类中存在的类类型
class name属性对应的全类型
cascade 对当前表的操作crud
constrained="false"代表当前表是主表
true 代表从表-->
<one-to-one name="p_c" class="cn.lanou3g.entity.Card" cascade="all" constrained="false"/>
</class>
</hibernate-mapping>
public class text {
Session session = HibernateSessionFactory.getSession();
Transaction ts=session.beginTransaction();
//自动建表
@Test
public void textConn(){
//新建配置对象 目的是自动加载配置文件
Configuration cfg = new Configuration();
cfg.configure();//自动加载主配置文件
//开启session工厂
SessionFactory sf=cfg.buildSessionFactory();
}
// 同时添加人(主表)和身份证
// @Test
public void textInser(){
Person p = new Person("梁靖");
Card c = new Card("152727199603111025");
//先保存从表中的关联字段
c.setC_p(p);
// p.setP_c(c);
//保存从表
session.save(c);
ts.commit();
}
//修改id为1的姓名
// @Test
public void textUpdate(){
Person p = (Person)session.get(Person.class, 2);
p.setP_name("梁敏");
session.save(p);
ts.commit();
}
//删除用户 删除身份证 从主表中删除 从表的也删除
//思路:通过主表获取关联字段
//关联字段放入主表
// 删除主表
// @Test
public void textdelect(){
Person p = (Person)session.get(Person.class, 2);
// Card p_c =p.getP_c();
// p.setP_c(p_c);
session.delete(p);
ts.commit();
}
}
懒加载
映射文件中加入属性lazy="true"
为什么用它:
防止内存溢出,递归调出方法
- 解决:
1.去掉任何一方的toString()
2.在不需要查询的一方的配置文件中加入lazy="true"
HQL语句:
- 是指hibernate sql
- 查询全部
- 查询某一个字段
- 按条件查询0
//分页
Query q = session.createQuery("from User");
//起始位置
q.setFirstResult(0);
//一次展示多少条
q.setMaxResults(5);
//把查询到的结果放入list集合
List list = q.list();
System.out.println(list);//遍历并且输出集合
网友评论