Hibernate介绍
- Hibernate介绍
- 是什么
- 是一个持久层框架(与数据库保持同步数据的 jdbc mybatis)
- 基于orm思想的框架
- 是对jdbc 的非常轻量级封装
- 有什么特性(与jdbc对比)
- jdbc 加载驱动 获取连接 写sql 执行sql 把获取的数据手动封装起来
- hibernate
- 怎么融进项目
ORM(Object/Relation Mapping): 对象/关系映射
ORM 主要解决对象-关系的映射
ORM的思想:将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。
ORM 采用元数据来描述对象-关系映射细节, 元数据通常采用 XML 格式, 并且存放在专门的对象-关系映射文件中.
-
Hibernate两个配置文件
- hibernate.cfg.xml;
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration><!-- configuration配置 --> <session-factory><!-- factory 工厂 --><!-- connection ==session --> <!-- 加载驱动 获取连接 用户名 密码 方言 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql:///1804</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 选填项 显示sql 格式化sql 反向生成表--> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <!-- create-drop 先创建,再删除 create 先删除,再创建 validate 验证存在,不存在报错 update:存在则操作,不存在则创建 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 引进映射文件 --> <mapping resource="com/mr/hibernate/pojo/User.hbm.xml"/> <mapping resource="com/mr/hibernate/pojo/Order.hbm.xml"/> <mapping resource="com/mr/hibernate/pojo/Customer.hbm.xml"/> </session-factory> </hibernate-configuration> |
什么是Hibernate方言?
Hibernate方言是用来告诉Hibernte如何对指定的数据库生成相应的SQL语句。
尽管做了很多尝试去使SQL语句标准化,但是不同的数据库支持的SQL语句还是有很多不同的地方。
所以Hibernate使用方言来辅助生成正确的SQL语句。
MySQL5Dialect与MySQL5InnoDBDialect有什么区别?
他们最大的区别是,在使用Hibernate创建表时MySQL5InnoDBDialect会在生成的建表SQL语句最后加上"ENGINE=InnoDB"。
InnoDB是一种MySQL数据库引擎.MySQL5.5及之后使用它做为默认引擎。它提供了ACID兼容的事务(Transaction)功能,并提供外键支持。
MySQLDialect与MySQL5Dialect有什么区别?
MySQLDialect是针对MySQL5之前的版本。主要变化还是在于建表SQL语句。
MySQL由于4到5还是有不小的变化。比如varchar在4及之前版本最大长度限制为255,5及之后版本最大长度限制为65535。
MySQLInnoDBDialect会在生成的建表SQL语句最后加上"TYPE=InnoDB"。
- *.hbm.xml文件;
创建实体
package com.mr.hibernate.pojo; import java.util.Date; public class User { public User(String userName, Date userBir) { super(); this.userName = userName; this.userBir = userBir; } private Integer userId; private String userName; private Date userBir; public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Date getUserBir() { return userBir; } public void setUserBir(Date userBir) { this.userBir = userBir; } @Override public String toString() { return "User [userId=" + userId + ", userName=" + userName + ", userBir=" + userBir + "]"; } public User(Integer userId, String userName, Date userBir) { super(); this.userId = userId; this.userName = userName; this.userBir = userBir; } public User() { super(); } public User(String userName) { super(); this.userName = userName; } } |
创建映射文件:充分体现orm思想 把对象和表关系通过映射的方式联系起来
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2018-6-15 10:32:56 by Hibernate Tools 3.5.0.Final --> <hibernate-mapping> <class name="com.mr.hibernate.pojo.User" table="t_user"> <!-- 主键 --> <id name="userId" column="USER_ID"> <!-- name :属性 column :字段 generator:主键生成策略 native:本地 identity:自增 increment:最大加1 sequence:序列 foreign:外键 uuid:32位的字符串 --> <generator class="native"></generator> </id> <!-- property:普通属性 :name:属性 column:表字段 --> <property name="userName" column="USER_NAME"></property> <property name="userBir" column="USER_BIR"></property> </class> </hibernate-mapping> |
Configuration类:加载配置文件的类
SessionFactory:会话工厂用来创建session
Session:会话 用来连接数据库,相当于jdbc中的connection
Transaction:事务,用来开启和提交回滚事务
Query:查询,用来查询数据
1.sequence 标识符生成器利用底层数据库提供的序列来生成标识符.
由于 sequence 生成标识符的机制依赖于底层数据库系统的序列, 因此, 要求底层数据库系统必须支持序列. 支持序列的数据库包括: DB2, Oracle 等
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常
2. increment 每次从数据库中查询出最大的 id 然后 +1
由于 increment 生存标识符机制不依赖于底层数据库系统, 因此它适合所有的数据库系统,适用于只有单个 Hibernate 应用进程访问同一个数据库的场合, 在集群环境下不推荐使用它,OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常
3. native ( 本地的 ) 把主键生成策略交给数据库管理 不同的数据库有不同的主键生成策略
适用与 mysql 和 oracle 数据库 mysql 在使用时 必须设定主键自增策略,oracle 在使用时 如果不指定具体的 sequence ,会使用 Hibernate 默认的序列 Hibernate_seq
- uuid
生成一个 32 位的随机字符串 该字符串基本不会出现重复,机器码 + 纳秒 + 生成一个唯一不重复的字符串
5.foreign
一般用于一对一对应关系 ,子表没有自己的 id ,子表使用主表的 id
6 identity mysql 主键自增
由于 identity 生成标识符的机制依赖于底层数据库系统, 因此, 要求底层数据库系统必须支持自动增长字段类型. 支持自动增长字段类型的数据库包括: DB2, Mysql, MSSQLServer, Sybase 等
OID 必须为 long, int 或 short 类型, 如果把 OID 定义为 byte 类型, 在运行时会抛出异常
- 常用方法
1.保存对象到数据库 session.save(Object user);
2.返回值为生成的主键id。
3.数据更新,session.update(Object user);update
4.更新或者保存,session.saveOrUpdate(Object user); 有id则更新,没有id,则保存
5.删除操作,session.delete(Object user);
6.查询操作,session.get(Class clazz, Serializable id);
7.查询操作,session.load(Class theClass, Serializable id);
8.强制同步数据到数据库,session.flush();
9.同步数据库中数据到java对象,session.refresh(Object user);
10.查询 createQuery("from User");
11.查询 createSqlQuery("select * from t_user");
12.关闭 close();
13.ession中get() load()区别
- get与load区别
get() 为立即加载,调用方法就会打印查询sql语句;
load() 为懒加载 ,调用方法时不会打印 sql语句,只有在调用的时候,才会打印;
b)从查询结果对比
get()查询不到数据,返回null ;
load():查询不到数据则抛异常org.hibernate.ObjectNotFoundException;
Hibernate对象状态
- Hibernate 把对象分为 4 种状态:
1.临时状态(Transient):在使用代理主键的情况下, OID 通常为 null,不处于 Session 的缓存中,在数据库中没有对应的记录 。例如:临时工,没有编号,不在公司编制里面;
2.持久化状态(也叫”托管”)(Persist):
OID 不为 null ,位于 Session 缓存中,若在数据库中已经有和其对应的记录, 持久化对象和数据库中的相关记录对应,Session 在 flush 缓存时, 会根据持久化对象的属性变化, 来同步更新数据库
在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象,例如上班之后;有编号,也在公司编制里面了;
3.游离状态(也叫”脱管”) (Detached):
OID 不为 null,不再处于 Session 缓存中,一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录,例如:你请假了;
4.删除状态(Removed)
在数据库中没有和其 OID 对应的记录,不再处于 Session 缓存中
一般情况下, 应用程序不该再使用被删除的对象,例如,你被开除了
四种状态的转换
-
缓存
- 什么是缓存(hibernate一共有三级缓存)
缓存就是数据交换的缓冲区(称作Cache),当某一硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存中找。由于缓存的运行速度比内存快得多,故缓存的作用就是帮助硬件更快地运行。缓存是指可以进行高速数据交换的存储器,它先于内存与CPU交换数据,因此速率很快。
- 测试session一级缓存:
/** * session的状态 * 瞬时态 没有oid * 持久态 有oid 和数据库同步 === session 的缓存 * 游离态 有oid 和数据库不同步 * 删除态 没有oid */ @Test public void test() { // 临时状态(Transient): User user = new User(); user.setUserName("瞬时态"); System.out.println(user);
// 持久化状态(也叫”托管”)(Persist): Serializable oid = session.save(user); user.setUserName("持久态"); System.out.println(user); transaction.commit(); session.close();
// 游离状态(也叫”脱管”) (Detached):session 关闭或者session 清除 user.setUserName("游离状态"); System.out.println(user);
// 删除状态(Removed) session.delete(user); }
|
通过结果可以看出:从sql上看 两次查询只打印了一次select语句;
从时间上看:缓存的读取速度明显要高于从数据库中的速度
原理:因为第二次查询的时候会先去查看缓存中是否存在该对象,如果缓存中存在该对象,直接从缓存中进行获取,如果缓存中不存在,才去数据库进行查询,
作用:缓存的存在有效的减少了对数据库的访问次数;有效减少时间,提高用户体验度减少程序的压力
- 二级缓存
内置缓存: Hibernate 自带的, 不可卸载. 通常在 Hibernate 的初始化阶段, Hibernate 会把映射元数据和预定义的 SQL 语句放到 SessionFactory 的缓存中, 映射元数据是映射文件中数据(.hbm.xml 文件中的数据)的复制. 该内置缓存是只读的.
外置缓存(二级缓存): 一个可配置的缓存插件. 在默认情况下, SessionFactory 不会启用这个缓存插件. 外置缓存中的数据是数据库数据的复制, 外置缓存的物理介质可以是内存或硬盘
适合放入二级缓存中的数据:
–很少被修改
–不是很重要的数据, 允许出现偶尔的并发问题
-高并发 ,访问次数多的
不适合放入二级缓存中的数据:
–经常被修改
–财务数据, 绝对不允许出现并发问题
–与其他应用程序共享的数据