Hibernate 学习(二)
一、Hibernate 核心 API
1、Configuration 对象(配置)
配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造。它代表了 Hibernate 所需一个配置或属性文件。配置对象提供了两种基础组件。
- 数据库连接:由 Hibernate 支持的一个或多个配置文件处理。这些文件是 hibernate.properties 和 hibernate.cfg.xml。
- 类映射设置:这个组件创造了 Java 类和数据库表格之间的联系。
2、SessionFactory 对象
配置对象被用于创造一个 SessionFactory 对象,使用提供的配置文件为应用程序依次配置 Hibernate,并允许实例化一个会话对象。
SessionFactory 是一个线程安全对象并由应用程序所有的线程所使用。
SessionFactory 是一个重量级对象所以通常它都是在应用程序启动时创造然后留存为以后使用。每个数据库需要一个 SessionFactory 对象使用一个单独的配置文件。所以如果你使用多种数据库那么你要创造多种 SessionFactory 对象。
主要作用:负责创建 Session 对象。
概念:SessionFactory 对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory 还负责维护 Hibernate 的二级缓存,查询缓存。
注意:
1、SessionFactory 对象的创建会有较大的开销,因为 SessionFactory 内部采取了线程安全的设计方式,因此在实际中 SessionFactory 对象可以尽量的共享,在大多数情况下,一个应用中针对一个数据库可以共享一个 SessionFactory 实例。
2、一个请求:一个 Session 对象(包含一个连接对象,一个事务对象,一个一级缓存)。
重要的方法:
1、openSession,这个方法代表,开启一个全新的Session
- 全新的连接
- 全新的事务
- 全新的一级缓存
2、getCurrentSession:得到当前上下文中的session
- 如果当前上下文中存在 session,则使用该session;
- 如果当前上下文中不存在 session,则使用opensession创建一个新的 session ;放到当前线程
- 要使用 getCurrentSessoin,必须在hibernate.cfg.xml中配置 thread <property name="current_session_context_class">thread</property>
- getCurrentSession得到的session是和事务绑定的;
- 无论是 DML (数据操作语言)还是 DQL (数据查询语言) ,都必须开启事务
- 提交事务的时候就是关闭 session
所以可以把创建 SessionFactory 对象提取为一个工具类,使用静态单例模式:
package com.hibernate.util; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; /**
* @author zt1994 2018/3/7 10:13
*/
public class HibernateUtil {
private static SessionFactory sessionFactory; static {
try {
//1.读取并解析配置文件
Configuration configuration = new Configuration();
//2.加载配置文件,如果不设置加载默认配置文件hibernate.cfg.xml
configuration.configure("hibernate.cfg.xml");
//3.生成会话工厂
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e){
e.printStackTrace();
}
} public static Session getSession(){
//4.获取session
return sessionFactory.openSession();
}
}
3、Session 对象
一个被用于获取与数据库的物理连接的会话。Session 对象是轻量级的,被设计为每次实例化都需要与数据库交互。使用最广泛,也被称为持久化管理器,它提供和持久化相关的操作。增、删、改、查等。
Session 对象不应该长时间保持开启状态因为它们不是线程安全,它们应该按照所需创造和销毁,因为Session 对象是轻量级的,所以创建和销毁不需要消耗太多资源。
因此,一个 Session 对象只可以由一个线程使用。避免多个线程共享。
主要功能:Session 的主要功能是为映射实体类的实例提供创建,读取和删除操作。
1、一级缓存
Session中有一个缓存,称为一级缓存。存放当前工作单元加载的对象。
测试一级缓存:
/**
* 测试缓存
*/
@Test
public void testCache(){
//1.获取session
Session session = HibernateUtil.getSession();
Transaction transaction = null;
try {
//2.开启事务
transaction = session.getTransaction();
transaction.begin();
//3.操作CRUD
Product product1 = (Product) session.get(Product.class, 70);
System.out.println(product1.hashCode());
Product product2 = (Product) session.get(Product.class, 70);
System.out.println(product2.hashCode());
Product product3 = (Product) session.get(Product.class, 71);
System.out.println(product3.hashCode());
transaction.commit();
} catch (Exception e) {
if (transaction != null) transaction.rollback(); //回滚
e.printStackTrace();
} finally {
//4.关闭资源
session.close();
}
}
输出:
结论:先从一级缓存取,取不到,发出sql获取,放入一级缓存
一级缓存命中:只会发出一条sql
一级缓存命中条件:同一个 session 的OID是否相同
一级缓存内部的结构:
OID:Object ID,hibernate 里面定义
操作的持久对象全限定类名+"#"+数据库主键的值
com.hibernate.day01.model.LoginUser#1
存放在 Map<String,Object> cacheMap
2、Hibernate 状态:
瞬时状态(transient):瞬时状态刚刚用 new 语句创建,没有和 session 发生关系没有被持久化,不处于 session 中。该对象成为瞬时对象。
持久化状态(persistent):托管状态和 session 发生关系已经被持久化,加入到 session 的一级缓存中。该状态的对象为持久化对象。
游离状态(detached):脱管状态已经被持久化,但不处于 session 中。该状态的对象为游离对象。
删除状态(removed):从jpa出现,才有的状态只有调用了session.delete(domain 对象)方法对象有关联的ID,并且在 Session 管理下,但是已经被计划删除(真正删除是提交事务的时候)。
3、把持久状态的对象变成游离状态
session.close():把一级缓存清空,并关闭。
session.clear():把一级缓存清空。
session.evict(object持久对象):清空一级缓存里面指定的持久对象。
4、Transaction 对象
一个事务代表了与数据库工作的一个单元并且大部分 RDBMS 支持事务功能。在 Hibernate 中事务由底层事务管理器和事务(来自 JDBC 或者 JTA)处理。这是一个选择性对象,Hibernate 应用程序可能不选择使用这个接口,而是在自己应用程序代码中管理事务。
5、Query 对象
Query 对象使用 SQL 或者 Hibernate 查询语言(HQL)字符串在数据库中来检索数据并创造对象。一个查询的实例被用于连结查询参数,限制由查询返回的结果数量,并最终执行查询。
6、Criteria 对象
Criteria 对象被用于创造和执行面向规则查询的对象来检索对象。
二、脏数据更新
一个持久状态对象在事务管理内,一但改变原来的数据(非主键)(出现脏数据),事务提交的时候自动发出update去修改。
/**
* 测试脏读
* 原因:
* 1、通过Session拿到的对象是持久化对象,这个对象会放到一级缓存里面;
* Hibernate会为当前对象准备一个快照(备份);
* 2、提交事务时,会把快照和现在的对象进行对比,
* 如果相同,就不需要修改,也不会发生SQL语句;
* 如果不同,Hibernate就会认为现在这个数据是脏数据,会把它进行数据库同步(发生SQL语句)
*/
@Test
public void test1(){
//1.获取session
Session session = HibernateUtil.getSession();
Transaction transaction = null;
try {
//2.开启事务
transaction = session.getTransaction();
transaction.begin();
//3.操作CRUD
Product product = (Product) session.get(Product.class, 70);
product.setName("脏读测试");
//4.提交事务
transaction.commit();
} catch (Exception e) {
if (transaction != null) transaction.rollback(); //回滚
e.printStackTrace();
} finally {
//5.关闭资源
session.close();
}
}
输出:
可以从输出结果看出,自动调用了 update 方法进行数据库同步。
三、延迟加载
延迟加载(懒加载):真正需要非主键属性,才发出sql,获取非主键属性值提高性能,但是如果把 session 提前关闭,会出现(延迟加载)延迟初始化异常。
注意:
1、没有对应主键,报错
2、提前关闭session,报错
/**
* 测试延迟加载
*/
@Test
public void testLoad(){
//1.获取session
Session session = HibernateUtil.getSession();
Transaction transaction = null;
try {
//2.开启事务
transaction = session.getTransaction();
transaction.begin();
//3.操作CRUD
Product product = (Product) session.load(Product.class, 1); //只是生成SQL,并没有发送
System.out.println(product.getName()); //在这里才发送SQL语句
//4.提交事务
transaction.commit();
} catch (Exception e) {
if (transaction != null) transaction.rollback(); //回滚
e.printStackTrace();
} finally {
//5.关闭资源
session.close();
}
}
get、load 的区别:
Hibernate 学习(二)的更多相关文章
- Hibernate学习(二)关系映射----基于外键的单向一对一
事实上,单向1-1与N-1的实质是相同的,1-1是N-1的特例,单向1-1与N-1的映射配置也非常相似.只需要将原来的many-to-one元素增加unique="true"属性, ...
- hibernate学习二(HelloWorld)
一.建立hibernate配置文件 在工程Hibernate_01_HelloWorld下的src上建立hibernate.cfg.xml,打开hibernate-release-4.3.11.Fin ...
- hibernate学习(二)
hibernate 单向一对多映射 一.数据表设计 数据库名:hibernate5 数据表: ①表名:CUSTOMERS 字段: CUSTOMER_ID CUSTOMER_NAME ②表名:ORDE ...
- hibernate学习二 基本用法
一 映射文件User.hbm.xml 定义了持久化类实例是如何存储和加载的,这个文件定义了持久化类和表的映射. 根据映射文件,Hibernate可以生成足够的信息以产生所有的SQL语句,也就是类的实 ...
- Hibernate学习二----------hibernate简介
© 版权声明:本文为博主原创文章,转载请注明出处 1.hibernate.cfg.xml常用配置 - hibernate.show_sql:是否把Hibernate运行时的SQL语句输出到控制台,编码 ...
- Hibernate学习(二补充)关系映射----基于外键的双向一对一
刚刚写的是基于外键的单向一对一. 那么双向一对一就是在单向一对一的基础上稍微改动就可以了. account.java和account.hbm.xml都不用变动 只要我们小小的变动address.j ...
- Hibernate学习笔记(二)
2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...
- 我的hibernate学习记录(二)
通过上一篇文章我的hibernate学习记录(一)基本上的入门了hibernate,但是,里面还有还多东西是通过迷迷糊糊的记忆,或者说copy直接弄进去的,所以这篇文章就需要对上篇的一些文件.对象进行 ...
- Hibernate学习之——搭建log4j日志环境
昨天讲了Hibernate开发环境的搭建以及实现一个Hibernate的基础示例,但是你会发现运行输出只有sql语句,很多输出信息都看不见.这是因为用到的是slf4j-nop-1.6.1.jar的实现 ...
- Hibernate 学习教程
第1课 课程内容. 6 第2课Hibernate UML图. 6 第3课 风格. 7 第4课 资源. 7 第5课 环境准备. 7 第6课 第一个演示样例HibernateHelloWorld 7 第7 ...
随机推荐
- html的<a>标签,表单,内嵌框架
一. <a>标签 0. 用图片当链接,就是把图片当成链接文字即可 <a href="http://www.baidu.com/" title="跳 ...
- Hibernate入门教程
Hibernate 随心所欲的使用面向对象思想操纵数据库. Table of contents 介绍 搭建开发环境 半sql半面向对象写法 完全的sql写法 完全的面向对象写法 Hibernate H ...
- 27.Next Permutation(下一个字典序列)
Level: Medium 题目描述: Implement next permutation, which rearranges numbers into the lexicographicall ...
- 记新人从 excel 文件中读取字典数据踩的一个坑
原本是打算今天分享一下最近学习接口自动化的心得体会,然而在我写模板的时候,却被一个坑拦我大半天,心得体会不得不 延期再分享了.在我无数次调试无数次看log,终于发现并解决这个问题了.下面记录一下踩的坑 ...
- Excel2007使用SQL语句
Excel2007使用SQL语句 假如金三导出表格如下:[入库查询dddd.xls] 第1步 第2步 第3步 找到[入库查询dddd.xls] 比如 SELECT 纳税人名称, sum(实缴金额) F ...
- zookeeper 数据节点的增删改查
1.连接服务端 [root@localhost bin]# ./zkCli.sh -server 127.0.0.1:2181 Connecting to 127.0.0.1:2181 2018-05 ...
- 2016424王启元 Exp2 后门原理与实践
一.实验准备 1.在实验前关闭或退出了防火墙.360杀毒软件.电脑卫士等所有的电脑保护软件,避免在实验过程中攻击时被拒绝. 2.使用Windows获linux shell (1)在Wind ...
- Oracle 客户端管理软件安装
1.首先,先说明下为什么要安装Oracle客户端管理工具? 因为Oracle服务端过大,而且消耗的资源过多,大部分公司会把服务端装在公司的服务器上,而不会装在员工的电脑上,所以这个时候就需要使用Ora ...
- Zookeeper概念学习系列之分布式事务
不多说,直接上干货! 初学者来说,肯定会有这么一个疑问.为什么会在zookeeper里牵扯到分布式事务? zookeeper到底是什么? zookeeper实际上是yahoo开发的,用于分布式中一致性 ...
- Jquery jqXHR对象的属性和方法
在 jQuery 1.4 之前(包括1.4),$.ajax() 方法返回的是浏览器原生的 XMLHttpRequest 对象. 从 jQuery 1.5 开始,$.ajax() 方法返回 jQuery ...