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 ...
随机推荐
- ArrayList中的一些小细节@JDK8
ArrayList中的一些小细节@JDK8 protected transient int modCount = 0; 该变量用于记录ArrayList的版本号,不可被序列化,每次对ArrayList ...
- const 与define 创建符号常量的 用法与区别
一.define 的用法: 在c语言中我经常会看到 :#define PI 12 ,这是创建了一个符号常量,这里面要注意没有那个等于号“=”: 二.const 的用法: 1.const 也可以来创 ...
- 微信小程序的onLaunch()方法和onShow()方法
在app.js里面你会发现一个onLaunch()方法,这个方法是当小程序加载完毕后就执行的方法,此外,还有一个onShow()方法,先看下面的代码 app.js //app.js App({ onL ...
- 洛谷P5245 【模板】多项式快速幂
题面 传送门 题解 话说现在还用数组写多项式的似乎没几个了-- \[B(x)=A^k(x)\] \[\ln B(x)=k\ln A(x)\] 求个\(\ln\),乘个\(k\),\(\exp\)回去就 ...
- 2019.2.14 t2 程序调试
代码: #include <cstdio> #include <iostream> #include <cstring> #include <algorith ...
- 达人篇:5)公差的正态分布与CPK与制程能力(重要)
本章目的:明确公差分布(Tolerance Distribution)也有自己的形状,了解CPK概念. 1.正态分布(常态分布)normal distribution的概念 统计分析常基于这样的假设: ...
- Ntp客户端
function parseMsg (buffer) { if (buffer.length !== 48) return; const pkt = {}, now = new Date().getT ...
- java多线程-ReadWriteLock
大纲: ReadWriteLock接口 ReentrantReadWriteLock ReentrantReadWriteLock使用 一.ReadWriteLock public interface ...
- Linux C代码 获取IP地址
Ubuntu 16.04下,可编译通过: #include <stdio.h> #include <ifaddrs.h> #include <arpa/inet.h> ...
- Oracle PL/SQL编程之基础
1.简介:pl/sql块由三个部分组成:定义部分.执行部分.例外处理部分,如下所示: declare: /*定义部分---定义常量.变量.游标.例外.复杂数据类型 begin /*执行部分---要执行 ...