Hibernate学习

Hibernate

什么是orm:
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
(将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。
因此ORM的目的是为了方便开发人员以面向对象的思想来实现对数据库的操作。)
优点:
提高开发效率,降低开发成本 
使开发更加对象化 
可移植 
可以很方便地引入数据缓存之类的附加功能
缺点:
消耗系统性能


hibernate和mybatis区别:
Hibernate理念不错,完全的ORMapping,MyBatis只是个SQL Mapper
Hibernate需要写hql语句,不需要写sql,多表关联查询复杂,优化不方便,
获取数据库会话session:SessionFactory -> Session
Mybatis自己写sql语句,可操作性强,小巧,数据库优化更方便
获取数据库会话SqlSession:SqlSessionFactoryBuilder -> SqlSessionFactory -> SqlSession 


Hibernate学习:
Hibernate 是传统 Java 对象和数据库服务器之间的桥梁,用来处理基于 O/R 映射机制和模式的那些对象。
Hibernate 将 Java 类映射到数据库表中,从 Java 数据类型中映射到 SQL 数据类型中,并把开发人员从 95% 的公共数据持续性编程工作中解放出来。


Hibernate 应用程序架构所涉及的每一个类对象:
配置对象
配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造。它代表了 Hibernate 所需一个配置或属性文件。配置对象提供了两种基础组件。
数据库连接:由 Hibernate 支持的一个或多个配置文件处理。这些文件是 hibernate.properties 和 hibernate.cfg.xml。
类映射设置:这个组件创造了 Java 类和数据库表格之间的联系。
SessionFactory 对象
配置对象被用于创造一个 SessionFactory 对象,使用提供的配置文件为应用程序依次配置 Hibernate,并允许实例化一个会话对象。SessionFactory 是一个线程安全对象并由应用程序所有的线程所使用。
SessionFactory 是一个重量级对象所以通常它都是在应用程序启动时创造然后留存为以后使用。每个数据库需要一个 SessionFactory 对象使用一个单独的配置文件。所以如果你使用多种数据库那么你要创造多种 SessionFactory 对象。
Session 对象
一个会话被用于与数据库的物理连接。Session 对象是轻量级的,并被设计为每次实例化都需要与数据库的交互。持久对象通过 Session 对象保存和检索。
Session 对象不应该长时间保持开启状态因为它们通常情况下并非线程安全,并且它们应该按照所需创造和销毁。
Transaction 对象
一个事务代表了与数据库工作的一个单元并且大部分 RDBMS 支持事务功能。在 Hibernate 中事务由底层事务管理器和事务(来自 JDBC 或者 JTA)处理。
这是一个选择性对象,Hibernate 应用程序可能不选择使用这个接口,而是在自己应用程序代码中管理事务。
Query 对象
Query 对象使用 SQL 或者 Hibernate 查询语言(HQL)字符串在数据库中来检索数据并创造对象。一个查询的实例被用于连结查询参数,限制由查询返回的结果数量,并最终执行查询。
Criteria 对象
Criteria 对象被用于创造和执行面向规则查询的对象来检索对象。


Hibernate会话:
Session 用于获取与数据库的物理连接。 Session 对象是轻量级的,并且设计为在每次需要与数据库进行交互时被实例化。持久态对象被保存,并通过 Session 对象检索找回。
该 Session 对象不应该长时间保持开放状态,因为它们通常不能保证线程安全,而应该根据需求被创建和销毁。Session 的主要功能是为映射实体类的实例提供创建,读取和删除操作。
这些实例可能在给定时间点时存在于以下三种状态之一:
瞬时状态: 刚创建的对象还没有被Session持久化、缓存中不存在这个对象的数据并且数据库中没有这个对象对应的数据为瞬时状态这个时候是没有OID。
持久状态:对象经过Session持久化操作,缓存中存在这个对象的数据为持久状态并且数据库中存在这个对象对应的数据为持久状态这个时候有OID。
脱管状态:一当Session关闭,缓存中不存在这个对象数据而数据库中有这个对象的数据并且有OID为游离状态。
如果 Session 引发异常,则事务必须被回滚,该 session 必须被丢弃。


持久化类:
Hibernate 的完整概念是提取 Java 类属性中的值,并且将它们保存到数据库表单中。映射文件能够帮助 Hibernate 确定如何从该类中提取值,并将它们映射在表格和相关域中。
在 Hibernate 中,其对象或实例将会被存储在数据库表单中的 Java 类被称为持久化类。若该类遵循一些简单的规则或者被大家所熟知的 Plain Old Java Object (POJO) 编程模型,Hibernate 将会处于其最佳运行状态。以下所列就是持久化类的主要规则,然而,在这些规则中,没有一条是硬性要求。
所有将被持久化的 Java 类都需要一个默认的构造函数。
为了使对象能够在 Hibernate 和数据库中容易识别,所有类都需要包含一个 ID。此属性映射到数据库表的主键列。
所有将被持久化的属性都应该声明为 private,并具有由 JavaBean 风格定义的 getXXX 和 setXXX 方法。
Hibernate 的一个重要特征为代理,它取决于该持久化类是处于非 final 的,还是处于一个所有方法都声明为 public 的接口。
所有的类是不可扩展或按 EJB 要求实现的一些特殊的类和接口。
POJO 的名称用于强调一个给定的对象是普通的 Java 对象,而不是特殊的对象,尤其不是一个 Enterprise JavaBean。


Hibernate映射文件:
一个对象/关系型映射一般定义在 XML 文件中。映射文件指示 Hibernate 如何将已经定义的类或类组与数据库中的表对应起来。使用注解形式


Hibernate注释:
@Entity 注释
EJB 3 标准的注释包含在 javax.persistence 包,所以我们第一步需要导入这个包。第二步我们对 Employee 类使用 @Entity 注释,标志着这个类为一个实体 bean,所以它必须含有一个没有参数的构造函数并且在可保护范围是可见的。
@Table 注释
@table 注释允许您明确表的详细信息保证实体在数据库中持续存在。
@table 注释提供了四个属性,允许您覆盖的表的名称,目录及其模式,在表中可以对列制定独特的约束。现在我们使用的是表名为 EMPLOYEE。
@Id 和 @GeneratedValue 注释
每一个实体 bean 都有一个主键,你在类中可以用 @Id 来进行注释。主键可以是一个字段或者是多个字段的组合,这取决于你的表的结构。
默认情况下,@Id 注释将自动确定最合适的主键生成策略,但是你可以通过使用 @GeneratedValue 注释来覆盖掉它。strategy 和 generator 这两个参数我不打算在这里讨论,所以我们只使用默认键生成策略。让 Hibernate 确定使用哪些生成器类型来使代码移植于不同的数据库之间。
@Column Annotation
@Column 注释用于指定某一列与某一个字段或是属性映射的细节信息。您可以使用下列注释的最常用的属性:
name 属性允许显式地指定列的名称。
length 属性为用于映射一个值,特别为一个字符串值的列的大小。
nullable 属性允许当生成模式时,一个列可以被标记为非空。
unique 属性允许列中只能含有唯一的内容


Hibernate API:
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session = factory.openSession();
//在不使用PoJo类和O/R Mapping的情况下,arg0(EntityName)是必填的,因为没有了ORM关系,
//根据Object无法找到它对应的Class名称,更不用说数据库表名称了。
//arg0(EntityName)这个参数暂时可以不用,它是预留的!在实体与数据库无映射关系时
session.save(String arg0, Object arg1);
//返回值是一个序列化对象,就是实体主键id
int ObjectId = (Integer)session.save(Object arg0);
//删除操作 无返回值
session.delete(Object arg0);
//修改操作 无返回值
session.update(Object arg0);
//查询操作 根据id取得一个记录
session.get(Class arg0, Serializable ObjectId);
//懒加载(lazy),简单说就是延时、延迟加载。 load有懒加载特性,get没有
session.load(Class arg0, Serializable ObjectId);


get和load区别:
1.get方法会在调用之后立即向数据库发出sql语句(不考虑缓存的情况下),返回持久化对象;
load方法会在调用后返回一个代理对象,该代理对象只保存了实体对象的id,直到使用对象的非主键属 性时才会发出sql语句。
2.查询数据库中不存在的数据时,get方法返回null,load方法抛出异常: org.hibernate.ObjectNotFoundException。
lazy懒加载(延迟加载):就是在查询某一条数据的时候并不会直接将这条数据以指定对象的形式来返回,而是在你真正需要使用该对象里面的一些属性的时候才会去数据库访问并得到数据。他的好处就是可以减少程序本身因为与数据库频繁的交互造成的处理速度缓慢。 
注意:
hibernate3以后默认启用了延迟加载:lazy="true",get方法不使用延迟加载机制,首先查找Session缓存,然后查找二级缓存,然后查询数据库(hibernate3以前会跳过二级缓存,直接查询数据库)。load方法首先查找Session缓存,然后查找二级缓存,若找不到则返回代理对象,延迟到真正使用对象非主键属性时才发出sql语句加载对象。=
若设置lazy="false",load返回代理对象之后会发出sql语句,若找不到符合条件的记录,依然会抛出ObjectNotFoundException异常


Hibernate 查询语言(HQL)
查询语言
Hibernate 查询语言(HQL)是一种面向对象的查询语言,类似于 SQL,但不是去对表和列进行操作,而是面向对象和它们的属性。 HQL 查询被 Hibernate 翻译为传统的 SQL 查询从而对数据库进行操作。
尽管你能直接使用本地 SQL 语句,但我还是建议你尽可能的使用 HQL 语句,以避免数据库关于可移植性的麻烦,并且体现了 Hibernate 的 SQL 生成和缓存策略。
在 HQL 中一些关键字比如 SELECT ,FROM 和 WHERE 等,是不区分大小写的,但是一些属性比如表名和列名是区分大小写的。


Hibernate 标准查询
Hibernate 提供了操纵对象和相应的 RDBMS 表中可用的数据的替代方法。一种方法是标准的 API,它允许你建立一个标准的可编程查询对象来应用过滤规则和逻辑条件。
Hibernate Session 接口提供了 createCriteria() 方法,可用于创建一个 Criteria 对象,使当您的应用程序执行一个标准查询时返回一个持久化对象的类的实例。
Restrictions查询用法:
Restrictions.eq() =
Restrictions.ne() <> 


Hibernate 原生 SQL
如果你想使用数据库特定的功能如查询提示或 Oracle 中的 CONNECT 关键字的话,你可以使用原生 SQL 数据库来表达查询。Hibernate 3.x 允许您为所有的创建,更新,删除,和加载操作指定手写 SQL ,包括存储过程。
您的应用程序会在会话界面用 createSQLQuery() 方法创建一个原生 SQL 查询
String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List results = query.list();
标量查询
最基本的 SQL 查询是从一个或多个列表中获取一个标量(值)列表。以下是使用原生 SQL 进行获取标 量的值的语法:
String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP或者 Transformers.ALIAS_TO_ENTITY_MAP);返回一个list<map>
List results = query.list();
实体查询
以上的查询都是关于返回标量值的查询,只是基础性地返回结果集中的“原始”值。以下是从原生 SQL 查询中通过 addEntity() 方法获取实体对象整体的语法:
String sql = "SELECT * FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
List results = query.list(); 
指定 SQL 查询
以下是从原生 SQL 查询中通过 addEntity() 方法和使用指定 SQL 查询来获取实体对象整体的语法:
String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
query.setParameter("employee_id", 10);
List results = query.list(); 
Transformers.ALIAS_TO_ENTITY_MAP //把输出结果转换成map 
Transformers.TO_LIST //把结果按顺序排进List 
Transformers.aliasToBean(target) //把结果通过setter方法注入到指定的对像属性中


Hibernate 缓存:
什么是缓存?
  缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从 而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读 写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。  
缓存有什么好处?
缓存的好处是降低了数据库的访问次数,提高应用性能,减少了读写数据的时间
什么时候适合用缓存?
  程序中经常用到一些不变的数据内容,从数据库查出来以后不会去经常修改它而又经常要用到的就 可以考虑做一个缓存,以后读取就从缓存来读取,而不必每次都去查询数据库。因为硬盘的速度比内存 的速度慢的多。从而提高了程序的性能,缓存的出现就会为了解决这个问题


一级缓存(Session缓存):Session 的缓存被称为hibernate的第一级缓存。
二级缓存(SessionFactory缓存):SessionFactory的外置缓存称为hibernate 的二级缓存。 
这两个缓存都位于持久层,它们存放的都是数据库数据的拷贝。SessionFactory的内置缓存 存放元数 据和预定义SQL, SessionFactory的内置缓存是只读缓存。
查询缓存(Query Cache):hibernate的查询缓存是主要是针对普通属性结果集的缓存, 而对于实体对象的结果集只缓存id。


在一级缓存,二级缓存和查询缓存都打开的情况下作查询操作时这样的:
查询普通属性,会先到查询缓存中取,如果没有,则查询数据库;查询实体,会先到查询缓存中取id,如果有,则根据id到缓存(一级/二级)中取实体,如果缓存中取不到实体,再查询数据库。


Session 缓存的三大作用:
1,减少数据库的访问频率,提高访问性能。
2,保证缓存中的对象与数据库同步,位于缓存中的对象称为持久化对象。
3,当持久化对象之间存在关联时,Session 保证不出现对象图的死锁。


Session 如何判断持久化对象的状态的改变呢?
Session 加载对象后会为对象值类型的属性复制一份快照。当Session 清理缓存时,比较当前对象和它 的快照就可以知道那些属性发生了变化。


Session 什么时候清理缓存?
1,commit() 方法被调用时
2,查询时会清理缓存,保证查询结果能反映对象的最新状态。
3,显示的调用session 的 flush方法。


缓存详解:https://www.cnblogs.com/hcl22/p/6100191.html
缓存问题解决方案:https://www.w3cschool.cn/hibernate/xrvi1iee.html


hibernate批量处理数据:
https://blog.csdn.net/chenssy/article/details/7721622
https://blog.csdn.net/JIESA/article/details/48711563
1 session.flush()的作用就是将session的缓存中的数据与数据库同步。
fiush作用:       
      1、flush()方法进行清理缓存的操作,执行一系列的SQL语句,但不会提交事务;commit()方法会先调用flush()方法,然后提交事务. 提交事务意味着对数据库所做的更新会永久保持下来   所谓清理,是指Hibernate 按照持久化象的状态来同步更新数据库   
       2、Flush()后只是将Hibernate缓存中的数据提交到数据库,如果这时数据库处在一个事物当中,则数据库将这些SQL语句缓存起来,当Hibernate进行commit时,会告诉数据库,你可以真正提交了,这时数据才会永久保存下来,也就是被持久化了.    
       3、commit针对事物的,flush针对缓存的, 数据同步到数据库中后只要没有commit还是可以rollback的。
2 session.clear()的作用就是清除session中的缓存数据(不管缓存与数据库的同步)。
clear作用:Hibernate的Session持有一个必选的一级缓存,所有的User实例都会Session级别的缓存区进行缓存的缘故:总是会抛出OutOfMemoryException内存溢出异常。
hibernate中的session.flush()和commit()的区别:
https://blog.csdn.net/zmx729618/article/details/51455051
 
hibernate拦截器
Hibernate中的事件监听机制可以对Session对象的动作进行监听,一旦发生了特殊的事件,Hibernate就会执行监听器中的事件处理方法。
在某些功能的设计中,我们即可以使用Hibernate的拦截器实现,也可以使用Hibernate的事件监听来实现 。
hibernate拦截器可以拦截大多数动作,比如事务开始之后(afterTransactionBegin)、事务完成之前(beginTransactionCompletion)、事务完成之后(afterTransactionCompletion)、持久化对象之前(onSave),一个拦截器必须实现org.hibernate.Interceptor借口,hibernate提供了一个实现该借口的类EmptyInterceptor类


拦截器详解:https://www.cnblogs.com/otomedaybreak/archive/2012/01/23/2328980.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值