一、hibernate框架的入门
1、先了解下CRM,在之后的学习中会用到。
CRM的概诉:https://baike.baidu.com/item/CRM,CRM即客户关系管理。
2、Hibernate 开放源代码的对象关系映射框架的概诉。
Hibernate维基百科介绍、Hibernate百度百科介绍。
3、什么是框架?
框架指的是软件的半成品,已经完成了部分功能。
4、EE的经典三层结构。
5、Hibernate是一个“持久层”的ORM框架。
什么是ORM?
ORM:(Object Relational Mapping)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。 这也同时暗示着额外的执行开销;然而,如果ORM作为一种中间件实现,则会有很多机会做优化,而这些在手写的持久层并不存在。 更重要的是用于控制转换的元数据需要提供和管理;但是同样,这些花费要比维护手写的方案要少;而且就算是遵守ODMG规范的对象数据库依然需要类级别的元数据。
6、下载hibernate的开发环境
目前最新的好像到6了,在这里用的是5即hibernate-release-5.0.7.Final,解压之后如下图
-
document:Hibernate开发的文档
-
lib: Hibernate的开发包
-
project:Hibernate提供的项目,到项目里可以找到相关的配置,比如hibernate.cfg.xml、hibernate.properties
二、建立项目
1、在idea中创建
2、引入基本的jar包
- Hibernate必须的包
- 数据库驱动包(使用的是mysql)
- Hibernate引入日志记录包(向后台输出信息,是否输出打印信息取决于自己的意愿)
3、在idea中连接数据库hibernate_dayone,并在其中建表“ cst_customer”
CREATE TABLE `cst_customer` (
`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
`cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
`cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
4、创建实体类,同时生成get/set方法
package com.chun.demo1;
//客户管理的实体类
public class Customer {
private Long cust_id;
private String cust_name;
private String cust_phone;
public Long getCust_id() {
return cust_id;
}
public void setCust_id(Long cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_phone() {
return cust_phone;
}
public void setCust_phone(String cust_phone) {
this.cust_phone = cust_phone;
}
}
5、对象有了,数据库关系有了,接下来需要创建映射文件
映射是配置文件,需要通过xml来完成,这个配置文件可以任意命名,但是基于规范化,建以尽量统一使用类名.hbm.xml
6、在src下创建hibernate的核心配置(有两种方式)文件,引入基本数据库用户和密码等配置
基于hibernate的基本规范,命名应该只能为hibernate.cfg.xml
在之后的引入中只识别hibernate.cfg.xml
基本必须配置
-
数据库驱动(不同数据库不一样,在这写mysql的):
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
-
url路径
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedayone?useUnicode=true&characterEncoding=UTF8</property>
-
用户名
<property name="hibernate.connection.username">root</property>
-
密码
<property name="hibernate.connection.password">666666</property>
可选配置
-
显示SQL
<property name="hibernate.show_sql ">true</property>
-
格式化SQL
<property name="hibernate.format_sql">true</property>
-
自动建表
<property name="hibernate.hbm2ddl.auto">none</property>
映射文件的引入
-
引入映射文件的位置
<mapping resource="com/chun/demo1/Customer.hbm.xml"></mapping>
在解压的hibernate包中
hibernate-release-5.0.7.Final\project\etc\hibernate.properties
可以找到各个数据库基本的配置编码,如下是Mysql
在配置基本配置时,需要hibernate方言配置,那么什么是方言呢?
hibernate方言的介绍–来自“络庆钟朔”的介绍
在hibernate的核心配置中有一些可选配置,比如打印Mysql语句(默认是不打印的)
<property name="hibernate.show_sql ">true</property>
格式化Mysql语句
<property name="hibernate.format_sql">true</property>
7、编写测试代码
package com.chun.demo1;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class HibernateDemoOne {
public static void main(String[] args) {
//1、加载Hibernate核心配置文件
Configuration configuration = new Configuration().configure();
//2、创建一个SessionFactory对象,类似于JDBC中的连接池
SessionFactory sessionFactory = configuration.buildSessionFactory();
//3、通过sessionFactory获取session对象类似于JDBC中的connection
Session session = sessionFactory.openSession();
//4、手动开启事务
Transaction transaction = session.beginTransaction();
//5、编写代码,保存客户
Customer customer = new Customer();
customer.setCust_name("刘文");
customer.setCust_phone("17839682092");
Customer customer1 = new Customer();
customer1.setCust_name("王帅");
customer1.setCust_phone("15812356987");
session.save(customer);
session.save(customer1);
//6、提交事务
transaction.commit();
//7、资源释放
session.close();
}
}
运行截图
三、hibernate的常见配置
1、有关xml文件的配置
我们会发现在xml的文件中写代码的时候会有提示,这是因为在每个xml文件中都有一个链接,如下图,在联网的时候会有代码提示,在不联网的时候可能没有代码提示,这个时候我们就需要为这个xml文件引入schema约束了,在idea中引入过程如下。
四、hibernate的核心API
1、Configuration:hibernate的配置对象
Configuration
Configuration类用来管理我们的配置文件的信息的。通过它,可以从properties或者xml文件中加载软件的配置信息,用来构建支撑软件运 行的基础环境。在一些配置文件较多较的复杂的情况下,使用该配置工具比较可以简化配置文件的解析和管理。我们可以通过创建一个configuration实例来管理相应的配置文档,但是通常我们只创建一个configuration实例。
2、SessionFactory:Session工厂
SessionFactory
来自大佬的介绍
SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
SessionFactory内部维护了hibernate的连接池和hibernate的二级缓存(我不懂),是线程安全的对象,一个项目只需要一个SessionFactory的对象就可以
SessionFactory sessionFactory = configuration.buildSessionFactory();
<!--配置C3P0连接池-->
<property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!--在连接池中可用的数据库连接的最少数目 -->
<property name="c3p0.min_size">10</property>
<!--在连接池中所有数据库连接的最大数目 -->
<property name="c3p0.max_size">20</property>
<!--设定数据库连接的过期时间,以秒为单位,如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
<property name="c3p0.timeout">120</property>
<!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
<property name="c3p0.idle_test_period">3000</property>
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static final Configuration configuration;
private static final SessionFactory sessionFactory;
static {
configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
}
public static Session openSession() {
return sessionFactory.openSession();
}
}
package com.chun.demo1;
import com.chun.Utils.HibernateUtils;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
public class HibernateDemoTwo {
@Test
public void demo () {
Session session = HibernateUtils.openSession();
//4、手动开启事务两种方式
//方式一
Transaction transaction = session.beginTransaction();
//方式二
Transaction transaction =session.getInstance();//获取一个实例
transaction.begin();//开启事务
//5、编写代码,保存客户
Customer customer = new Customer();
customer.setCust_name("王飞");
customer.setCust_phone("17839689999");
session.save(customer);
//6、提交事务
transaction.commit();
//7、资源释放
session.close();
}
}
要注意由于session不是线程安全的,要将 Session session = HibernateUtils.openSession()写在方法里
SessionFactory的特点
- 线程安全的,一个实例可以多个线程访问
- 重量级的,不能随意创建和销毁它的实例
由于SessionFactory的这些特点,一般情况下,一个项目种一般只需要一个SessionFactory实例,当应用中存在多个 数据源时,才会为每个数据源建立一个SessionFactory实例,因此,在实际开发中,通常会抽取一个HibernateUtils的工具类,用来提供Session对象。
Session对象:类似于Connection连接对象
Session作为贯穿Hibernate的持久化管理器核心,提供了众多的持久化的方法,如save(),update,delete,find(Hibernate 3中已经取消了此方法,)等,通过这些方法可以透明的完成对象的增删改查(CRUD-- create read update delete),这里所谓的透明是指,Session在读取,创建和删除映射的实体对象的实例时,这一系列的操作将被转换为对数据库表中数据的增加,修改,查询和删除操作。
-
Session代表的是Hibernate与数据库连接的对象,有以下的特点:
- 1、不是线程安全的,应该避免多个线程共享同一个Session实例;
- 2、Session实例是轻量级的,所谓轻量级:是指他的创建和删除不需要消耗太多资源;
- 3、Session对象内部有一个缓存,被称为Hibernate第一缓存,他存放被当前工作单元中加载的对象,每个Session实例都有自己的缓存。
-
Session中的API
在hibernate解压的包中documentation/javadocs/index.html文件夹下可以看到方法
-
保存/增加和修改方法
- Serializable save(Object object)(Serializable代表的是对象可序列化,Java的对象序列化是指将那些实现了Serializable接口的对象转换成一个字符序列,并能够在以后将这个字节序列完全恢复为原来的对象。这一过程甚至可通过网络进行,这意味着序列化机制能自动弥补不同操作系统之间的差异。 只要对象实现了Serializable接口)
- update()方法
(不好之处就是之前的部分数据会为空,比如下图的cust_phone)
推荐以下方式修改或者更新数据
- saveOrUpdate()方法
-
根据主键查询方法
- get(Class entityType, Serializable id)
- load(Class theClass, Serializable id)
- get(Class entityType, Serializable id)
-
-
get和load方法的区别
1.执行get()方法会立即加载对象,而执行load()方法,若不使用该对象(延迟加载),则不会立即执行查询操作,而返回一个代理对象;
2.load()方法可能会抛出LazyInitializationException异常:在需要初始化代理对象之前已经关闭了Session;
3.若数据表中没有记录:get()方法返回null,而load()方法抛出ObjectNotFoundException异常。- 用于数据库操作对象
-createQuery()和createSQLQuery()方法 - 条件查询
- createCriteria()方法
- 删除方法
- delete()
推荐下边的删除方法–因为hibernate中是级联删除(级联删除就是把关联的数据也删除了)
- delete()
- 用于数据库操作对象
3、Transaction:事务对象
Transaction 接口是一个可选的API,可以选择不使用这个接口,取而代之的是Hibernate 的设计者自己写的底层事务处理代码。 Transaction 接口是对实际事务实现的一个抽象,这些实现包括JDBC的事务、JTA 中的UserTransaction、甚至可以是CORBA 事务。之所以这样设计是能让开发者能够使用一个统一事务的操作界面,使得自己的项目可以在不同的环境和容器之间方便地移植。
Transaction接口主要用于管理事务,它是hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是 通过Session对象开启的,开启方式如下:
Transaction transaction = session.beginTransaction();
在transaction的事务接口中,提供了管理事务的常用方法:
-
commit():提交相关联的session实例
-
rollback():撤销事务操作
Session执行完数据库操作后,要使用Transaction接口的commit()方法进行事务提交,才能真正的将
数据操作同步到数据库中。发生异常时,需要使用rollback0)方法进行事务回滚,以避免数据发生错
误。因此,在持久化操作后,必须调用Transaction接口的conmitO方法和rollbackO方法。如果没有
开启事务,那么每个Session的操作,都相当于一个独立的操作。