Hibernate-ORM框架基础
对象保存在内存中,内存不能永久保存数据,如果要永久保存就需要对象持久化(将对象存储到数据库中).
关系型数据库存放关系型数据,它是非面向对象的,对象和关系数据都是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据.
内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联,继承关系等
因此,把对象持久化到关系数据库中,需要进行对象-关系的映射(Object Relation Mapping)即ORM
持久化为什么不使用JDBC?
- JDBC是java中最原始和最直接的访问关系型数卡的方式
- JDBC优点是运行效率高
- JDBC缺点是java程序中嵌入大量sql语句,使得项目难以维护
- 如果关系型数据库关系很复杂,业务逻辑很混乱,那么使用JDBC编程实现持久化需要更专业的知识(比如:缓存机制,日志等)
hibernate API分类
- 提供访问数据库(增删改查)的接口( Session, Transaction, Query )
- 配置Hibernate接口:Configuration
- 使应用程序拦截Hibernate内部发生的事情,不做出反应,这些接口包括:Interceptor, LoadEventListener, SaveEventListener等
- 扩展Hibernate功能的接口,UserType, CompositeUserType, IndentiFierGenerator等,如有需要应用程序可以扩展这些接口;
- hibernate内部封装了JDBC, JTA, JNDI, 其中JTA和JNDI使hibernate能够和JavaEE应用服务器集成;
hibernate核心接口
- Configuration接口:
Configuration对象用于配置, 启动hibernate ,
hibernatey应用通过Configuration对象获取对象-关系映射文件中元数据库,以及动态配置hibernate属性;创建SessionFactory对象 - SessionFactory接口 :
- 初始化Hibernate, 创建Session对象
- 是线程安全的,意味着同一个实例可以被多个线程共享;
- 重量级的,不能随意创建和销毁他的实例,如果应用只访问一个数据库,只需要创建一个SessionFactorys实例;
- 如果同时访问多个数据库,则需要为每个数据库创建单独的一个SessionFactorys实例.
- SessionFactory之所以是重量级别的,是因为它需要一个较大的缓存,用来存放预定义的sql语句以及映射元数据等.我们还可以为SessionFactory配置一个缓存插件,该插件叫做Hibernate的第二级缓存,该缓存用来存放被工作单元读过的数据,将来其他工作单元可能会重用这些数据,因此这个缓存中的数据可以被所有工作单元共享,一个工作单元通常对应一个数据库事务;
- Session接口:
- 负责增,删,改,加载/查对象
- 也称为持久化管理器
- 和HttpSession没有任何关系
- 不是线程安全的,因此在使用过程中应避免多个线程共享同一个session实例
- 轻量级的,创建和销毁不会销毁太多资源,意味着程序中可以经常创建和销毁Session实例;
- Session有一个缓存,被称为Hibernate的第一级缓存,存放的是当前工作单元加载的对象,每个Session实例都有自己的缓存,该缓存只能被当前工作单元访问;
- Transaction接口:管理事务
- Query和Cirteria接口:
- 执行复杂数据库查询;
- Query包装了HQL查询语句,与Sql相似,但是HQL查询是面向对象的,它引用类名以及属名,而不是表名和字段名;
- Criteria接口封装了基于字符串的查询语句,比query接口更加面向对象,Criteria接口擅长进行动态查询;
事务处理接口
当程序通过Hibernate来加载,保存,更新,删除对象时,会触发Hibernate拦截器以及事件监听器做处理;
映射类型接口
org.hibernate.type.Type接口表示将域对象数据类型映射为数据库的关系数据,Hiberate为Type实现了各种实现类,比如:InterType, FloatType等
可扩展的接口
Paste_Image.png一.hibernate功能
- hibernate是开源的
- ORM映射
- 是java领域的一款开源的ORM框架技术
- 对JDBC进行了非常轻量级的对象封装
- 是业务逻辑和数据库中间的持久化层( 中间件 )
- 数据查询和缓存
- 可以应用在独立的java程序和web应用中;
- 可以和多种Web服务器,应用服务器良好集成
-
支持几乎所有流行的数据库
Paste_Image.png - 点击查看练习代码
二.开发工具介绍以及安装
开发工具:Eclipse Standarg Kepler
Hibernate Tools for Eclipse Plugins
Hibernate Tools是JBoss公司推出的一个Eclipse综合开发工具插件,该插件可以简化ORM框架Hibernage, 以及JBoss Seam, EJB3等的开发工作,所以在Eclipse中安装Hibernate Tools之前要先确认Eclipse版本,在找对应的Hibernate Tools版本,我的eclipse版本是Eclipse Mars 4.5.2,以下是具体Hibernage Tools安装步骤,
参考文章
-
点击Eclipse -> Help -> Eclipse Marketplace
Paste_Image.png -
在Find中输入Hibernate找到JBoos Tools,选中下一步后只把Hibernate Tools选中,然后安装,
-
安装完毕后重启Eclipse,选择File->new->输入Hibernate,以下图片代表安装成功
Paste_Image.png
三.开发前准备
- 导入Hibernate jar包
- 首先要知道自己的Hibernate版本,我在eclipse目录下的plugins中找到的hiberate版本为org.hibernate.eclipse.console_5.0.1.Final-v20160331-1852-B88我的理解为5.0.1.Final,可以 点击下载
- 下载后将hibernate-release-5.0.1.Final.zip解压,hibernate-release-5.0.1.Final/lib/required目录下就是我们要的Hibernate的jar包
- 在eclipse中点击window -> Preferences-> java -> Build Path -> User Liberies -> New,输入hibernate-core(新建hibernate类库)确定.
- 然后导入外部jar包,点击Add External Jars,找到hibernate-release-5.0.1.Final/lib/required下的所有jar包并导入
- 导入junit4 jar包
- 点击下载
- 下载的包是junit-4.10.jar
- 下载后,在eclipse中新建junit4类库,方式参考以上方式(区别就是junit只有一个jar包)
-
导入mysql-connector-java-5.1.38.jar
在eclipse中新建mysql-jdbc类库方式参考以上方式. -
在工程中导入我们以上创建的三个类库
- 创建java project名为 hibernate-1
- hibernate-1 右键 -> properties -> java Build Path -> Libraries -> Add Library -> User Library 将刚刚创建的三个类库选中,点击Finsh就可以成功导入了.
-
导入工程成功的样子
Paste_Image.png
四.创建第一个Hibernate
-
创建hibernate配置文档
src-> New -> other -> Hibernate -> cfg.xml
Paste_Image.png -
创建持久化类( 实体类 )Students
javaBeans类创建原则:- 类必须是公有的
- 提供公有的不带参数的默认的构造方法
- 属性私有
- 属性setter/getter封装
-
创建关系对象映射文件(该文件是做数据库字段和实体类属性映射所用)
src-> New -> other -> Hibernate -> hbm.xml
Paste_Image.png
点击下一步找到我们刚才建立的实体类(Student)
Paste_Image.png
最后Finsh完成; -
使用junit单元测试
注解小执行方法的顺序为:- 1.@Before: 初始化方法
- 2.@Test : 测试方法
- 3.@After : 释放资源
建立测试项目:在Hibernate-1项目名右击 -> New -> Source Folder ->输入Test,在该目录下创建StudentsTest类:
package firstTest;
import java.util.Date;
import javax.print.attribute.standard.MediaPrintableArea;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import entity.Students;
/**
* 测试类
* @author lxf
*
*/
public class StudentsTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
//初始化配置
public void init()
{
/*
* 注意:我的hibernate是5.0和慕课网上讲的Hibernate4.2.4(就是4.0)两个版本的配置方法不一样
*/
//创建服务注册对象
//如果.cfg.xml取了其他的名字,要改为.configure("名字.cfg.xml")
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
//创建会话工厂对象
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
//创建会话对象
session = sessionFactory.openSession();
//开启事务
transaction = session.beginTransaction();
}
@Test
//真实的单元测试
public void testSaveStudent()
{
Students st = new Students(1,"张三丰", "nan", new Date(), "wds");
//保存对象进入数据库
session.save(st);
}
@After
//释放资源
public void destroy()
{
//提交事务
transaction.commit();
//关闭会话
session.close();
//关闭会话工厂
sessionFactory.close();
}
}
在StudentsTest.java右键Run as -> Junit Test执行,程序执行testSaveStudent罗辑,判断数据库hibernate中是否有students表,如果有则删除,没有则创建,然后将new Students(1,"张三丰", "nan", new Date(), "wds");对象属性insert到数据库的字段中;
五.Hibernate常用配置
-
hibernate.cfg.xml常用配置
Paste_Image.png -
Hibernate执行流程
Paste_Image.png -
transaction简介
- hibernate对数据库的操作都是封装在事务中,并且默认是非自动提交的方式,所以用session保存对象时,如果不开启事务,并且手工提交事务,对象并不会真正保存到数据库中;
- 如果想让hibernate自动提交事务,必须调用session.doWork()方法获取jdbc的connection后,设置为自动提交,(
不推荐使用
)
@Test
//真实的单元测试
public void testSaveStudent()
{
Students st = new Students(1,"张三丰", "nan", new Date(), "wds");
session.doWork(new Work(){
@Override
public void execute(Connection connection) throws SQLException {
// TODO Auto-generated method stub
//开启关系型数据库的自动提交
connection.setAutoCommit(true);
}
});
//保存对象进入数据库
session.save(st);
session.flush();
}
- session简介
- Hibernate是对JDBC的一个封装,所以不建议使用jdbc的connection操作数据库,而是通过使用session操作数据库;
- 可以session就是操作数据库的对象
- session与connection是多对一的关系,每个session都有一个与之对应的connection, 一个connection不同时刻可以提供多个session使用;
- 所以想把对象保存在关系型数据库中需要调用session的各种方法,如:save(), update(), delete(), createQuery()等等;
-
如果获取session对象的两种方式
- (1). sessionFactory.openSession()
-
(2). sessionFactory.getCurrentSession()
Paste_Image.png
-
openSession 和getCurrentSession区别
- openSession每次创建新的session对象, 而getCurrentSession使用现有的session对象(单例模式)
- getCurrentSession对象在事务提交或回滚后自动关闭,而openSession需要手动关闭,(如果使用openSession没有手动关闭,则会导致连接池溢出)
-
对象关系配置文档hbm常用配置
参考文章 -
单表映射
-
基本类型
Paste_Image.png -
日期类型
Paste_Image.png -
对象类型
Paste_Image.png -
组件属性
Paste_Image.png
- 单表CURD操作
- 获取单条数据有session.get()和session.load()
- get和load区别是:
(1) 在不考虑缓存的情况下,get方法会在调用之后立刻向数据库发出sql语句,返回持久化对象;
(2)而load方法会在调用后返回一个代理对象,该代理对象只保存实体对象的id,直到使用对象的非主键属性时菜会发出sql语句查询数据库;
(3)查询数据库中不存在的数据库时,get方法返回null,而load方法则会抛出异常:org.hibernate.ObjectNotFoundException