Hibernate
写在前面
作为一名大二的学生,在学习这些框架和一些知识点的时候,总是因为别的事情例如考试复习,学习别的科目,总会在学习知识的时候学一半就断了,等到自己再回来学习的时候,总是会出现“我是谁,我在哪”的感觉,总是无从下手,于是又重头学习一遍,这样真的很烦,于是打算一边学习,一边写一些笔记。所以我打算写一系列的笔记,主要目的是帮助自己复习和巩固知识,因为自己再回忆总结一遍印象会更加深刻。所以一定会有很多理解不正确的地方,希望读者能多多包含,欢迎在评论区指点错误,我会努力改正。
Hibernate的概述
- 什么是HIbernate
Hibernate是一个开放源代码的对象关系映射框架,总的来说Hibernate是一个持久层的ORM(Object Relational Mapping)(对象关系映射)框架。 - 什么是ORM呢
就和上面说的一样是一种对象关系映射。指的是将Java中的对象与关系型数据库中的表建立一种映射关系,从而操作对象就可以直接操作数据库中的表。
举例:
由表所示中的java类中的属性对应关系型数据库中表中的属性及为“对象关系映射”Java:Object(User类) MySql:Relational(user表) String name name varchar(20) String password password varchar(20)
Hibernate的配置和用法概述
- 下载Hibernate的开发环境(这里选用Hibernate5.x版本)
下载地址
解压后有三个文件夹- documentation :Hibernate开发文档
- lib :Hibernate开发包
- required:Hibernate开发的必须依赖包
- optional:Hibernate开发的可选择包
- project:Hibernate提供的项目
- 创建项目需要引入的jar包
- 数据库驱动包
- Hibernate开发的必须的jar包
- hiberna引入日志记录包
- 创建数据库表
CREAT TABLE 'cst_customer'(
'cust_id' bigint(32) NOT NULL AUTO_INCREMENT
'cust_name' varchar(32) NOT NULL,
'cust_source' varchar(32) DEFAULT NULL,
'cust_industry' varchar(32) DEFAULT NULL,
'cust_level' varchar(32) DEFAULT NULL,
'cust_phone' varchar(64) DEFAULT NULL,
PRIMARY KEY('cust_id')
)
- 创建实体类
public class Customer{
private Long cust_id;
private String cust_name;
private String cust_industry;
private String cust_level;
private String cust_phone;
//....get set........
.....
}
- 创建映射
映射需要通过XML的配置文件完成,这个配置文件可以任意命名
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://ww.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!--建立与表的映射-->
<class name="com.muzile.hibernate.demo.Customer" table="cst_customer">
<!--建立类中的属性与主键的映射-->
<id name="cust_id" column="cust_id">
<generator class="native"/>
</id>
<!--主键外的类中的属性与表的映射-->
<property name="cust_name" column="cust_name"/>
<property name="cust_source" column="cust_source"/>
<property name="cust_industry" column="cust_industry"/>
<property name="cust_level" column="cust_level"/>
<property name="cust_phone" column="cust_phone"/>
</class>
</hibernate-mapping>
- 创建一个HIbernate核心配置文件
HIbernate的核心配置文件名:hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://ww.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factroy>
<!--连接数据库的基本参数-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_cst</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123</property>
<!--配置HIbernate的方言-->
<property name="hibernate.dialect">org.hibernate.dialect.MySqlDialect</property>
<!--********可选配置**********-->
<!--打印SQL-->
<property name="hibernate.show_sql">true</property>
<!--格式化SQL语句-->
<property name="hibernate.format_sql">true</property>
<!--*****在核心配置文件中引入映射配置文件-->
<mapping resource="com/muzile/hibernate/demo/Customer.hbm.xml"/>
</session-factroy>
</hibernate-configuration>
- 编写测试代码
package com.muzile.hibernate.demo
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
/**
*
* Hibernate的演示
* @author muzile
*/
public class HibernateDemo{
@Test
public void demo1(){
//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("小张");
session.save(customer);
//6.事务提交
transaction.commit();
//7.释放资源
session.close();
}
}
现在hibernate_cst数据库中的cst_customer表就成功的保存了一条数据
cust_id | cust_name | cust_source | cust_industry | cust_level | cust_phone |
---|---|---|---|---|---|
1 | 小张 | NULL | NULL | NULL | NULL |
下面我们详细介绍一下HIbernate的配置
HIbernate配置和用法的详介
1.映射的配置
- 【class标签的配置】
- 标签用来建立类与表的映射关系
- 属性:
- name:类中的属性名
- table:表名(类名与表名一致,table可以省略)
- catalog:数据库名
- 【id标签的配置】
- 标签用来建立类中属性与表中的主键的对应关系
- 属性:
- name:类中的属性名
- column:表中的字段名(类中的属性名和表中的字段名如果一致,column可以省略)
- length:长度
- type:类型
- 【property标签的配置】
- 标签用来建立类中的普通属性与表中的字段的对应关系
- 属性:
- name:类中的属性名
- column:表中的字段名
- length:长度
- type:类型
- not-null:设置非空
- unique:设置唯一
由于在Hibernate的核心配置中的可选配置中有选择是否自动建表配置(这个我们下面再说),所以上面的映射配置中的catalog、length、type、可用于Hibernate建表的时候初始化表中的字段。
2.Hibernate的核心配置
首先,Hibernate的核心配置文件可以是xml文件也可以是properties文件,所以就会有一下两种配置方式。
- 第一种方式:属性文件的方式
- hibernate.properties
- hibernate.connection.driver_class=com.mysql.jdbc.Driver
- …
- hibernate.show_sql=true
- 由于属性文件不能引入映射文件,所以要手动编写加载映射文件
- hibernate.properties
- 第二种方式:XML文件的方式
- hibernate.cfg.xml
其次,Hibernate核心的配置
- hibernate.cfg.xml
- 必须的配置
- 连接数据库的基本参数
- 驱动类(hibernate.connection.driver_class)
- url路径(hibernate.connection.url)
- 数据库的用户名(hibernate.connection.username)
- 数据库的密码(hibernate.connection.password)
- 数据库方言(hibernate.dialect 不同的数据库有不同的方言:例如MySql的方言是:org.hibernate.dialect.MySqlDialect)
- 连接数据库的基本参数
- 可选配置
- 显示SQl:hibernate.show_sql
- 格式化SQL:hibernate.format_sql
- 自动建表:hibernate.hbm2ddl.auto
- none:不适用hibernate的自动建表
- create:如果数据库已经有表,删除原有表,重新创建,如果没有表,新建表
- create-drop: 如果数据库已经有表,删除原有表,执行操作,删除这个表,如果没有表,新建一个,使用完删除该表
- update:如果数据库中有表,使用原有表,如果没有表,创建新表(更新表结构)
- validate:如果没有表,不会创建表。只会使用数据库中原有的表(检验映射和表结构)
- 映射文件的引入
- 引入映射文件的位置
<mapping resource="com/muzile/hibernate/demo/Customer.hbm.xml"/>
3.Hibernate的核心API
- Configuration:Hibernate的配置对象
Configuration类的作用是对Hibernate进行配置,以及对它的启动。在Hibernate的启动过程中,Configuration类的实例首先定位映射文档的位置,读取配置,然后创建一个SessionFactory对象。虽然Configuration类在整个Hibernate项目中只扮演着一个很小的角色,但是他是启动Hibernate时所遇到的第一个对象。
作用: 加载核心配置文件(两种加载方式)
第一种:加载properties配置文件
第二种:加载XML配置文件//1.用Configuration读取核心配置文件 Configuration cfg = new Configuration(); //2.手动加载映射文件 cfg.addResource("com/muzile/hibernate/demo/Customer.hbm.xml");
Configuration cfg = new Configuration.configure();
- SessionFactory:Session 工厂类似于jdbc的链接池
SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是一个轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够了,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
注意 :(1)SessionFactory内部维护了Hibernate的连接池和Hibernate的二级缓存(由于现在二级缓存多被Redis等所代替,所以在这一系列的Hibernate中,将不会设计到Hibernate的二级缓存)。是线程安全的对象。一个项目创建一个对象即可。(2)可以更改为别的连接池,例如C3P0连接池,只需在Hibernate的核心配置中添加c3p0连接池的配置即可。
方法 | 作用 |
---|---|
Session openSession() | 从连接池中获得一个Session连接对象 |
由于为了节约资源,只需要创建一个SessionFactory对象,所以将SessionFactory获得Session重新抽取封装成一个工具类:
/**
* Hibernate工具类
* @author muzile
*/
public class HibernateUtils(){
public static final Configuration cfg;
public static final SessionFactory sf;
static{
cfg=new Configuration().configure();
sf=cfg.buildSessionFactory();
}
public static Session openSession(){
return sf.openSession();
}
}
- Session:类似Connection对象,是连接对象
Session接口负责执行被持久化(对象的持久化下一篇再仔细讨论)对象的CRUD操作。要注意的是Session对象是非线程安全的。同时,Hibernate的Session不同于JSP应用中的HttpSession。这里的Session指的是Hibernate中的Session,而以后将httpSession称之为用户Session。
注意:Session代表的是Hibernate于数据库的连接对象。不是线程安全的。与数据库交互的桥梁。
Session中的API
方法 | 作用 |
---|---|
Serializable save(Object obj) | 用于向与obj关联的数据库的表中保存对象,并返回唯一的序列化id |
T get(class c,Serializable id) | 根据唯一的序列化id,从数据库表中获得一组数据并返回封装好的对象 |
T load(class c,Seralizable id) | 根据唯一的序列化id,从数据库表中获得一组数据并返回封装好的对象 |
void update(Object obj) | 更新数据库,向数据库更新obj对象 |
void delete(Object obj) | 从数据库中,删除和obj对象相同的数据 |
void saveOrUpdate(Object obj) | 保存或更新数据库,若无数据则保存,若有数据则更新 |
Query createQuery(String args) | 该方法接受HQL(Hibernate Query Language)面向对象的查询语言 |
SQLQuery createSQLQuery(String args) | 该方法接受SQL语句,进行数据库查询 |
Transaction beginTransaction() | 开启事务,并返回Transaction对象 |
get方法与load方法的区别:
(1).get方法:
采用的是立即加载,执行到这行代码的时候,就会马上发送SQl语句去查询
查询后返回对象的本身
查询一个不存在的对象时,返回null
(2).load方法
采用的时延迟加载(lazy懒加载),只想到这行代码的时候,不会发送SQL语句,当真正使用这对象的时候才会发送SQL语句。
查询后返回的是代理对象,javassist-3.18.1-GA.jar 利用javassist技术产生的代理(详细下一篇介绍)
查询一个不存在的对象时,返回ObjectNotFoundException
- Transacton:事务对象
Transaction中的API简单介绍
方法 | 作用 |
---|---|
commit() | 提交事务 |
rollback() | 回滚事务 |
API代码测试
package com.muzile.hibernate.Test
import com.muzile.hibernate.utils.HibernateUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
/**
*
* Hibernate基础API的演示
* @author muzile
*/
@Test
//保存方法
public void demo1(){
//获得连接对象
Session session = HibernateUtils.openSession();
//开启事务
Transaction transaction = session.beginTransaction();
//创建与数据库对应的对象
Customer customer1 = new Customer();
Customer customer2 = new Customer();
customer1.serCust_name("小王");
customer1.setCust_id(1l);
customer2.setCust_name("小刚");
customer2.setCust_id(2l);
//保存对象
session.save(customer1);
session.save(customer2);
//提交事务
transaction.commit();
//关闭资源
session.close();
}
@Test
//查询方法
public void demo2(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//get方法查询
Customer customer1 = session.get(Customer.class,1l);
System.out.println(customer1);//小王
//load方法获得
Customer customer2 = session.get(Customer.class,2l);
System.our.prinln(customer2);//小刚
transaction.commit();
session.close();
}
@Test
//修改操作
public void demo3(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//直接查询对象修改
//原因下一篇分析
/*Customer customer = new Customer();
customer.setCust_id(1l);
session.delete(customer);*/
//先查询再删除(推荐)
Customer customer = session.get(Customer.class,2l);
session.delete(customer);
transaction.commit();
session.close();
}
@Test
//保存或更新
public void demo4(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_id(3l);
customer.setCust_name("小明");
session.saveOrUpdate(customer);
transaction.commit();
session.close();
}
@Test
//查询所有
public void demo5(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//接受HQL: Hibernate Query Language 面向对象的查询语言
/*Query query = session.createQuery("from Customer");
List<Customer> list = query.list();
for(Customer customer:list){
System.out.println(customer);
}*/
//接受SQL
SQLQuery query = session.createSQLQuery("select * from cst_customer");
List<Object[]> list = query.list();
for(Object[] objects:list){
System.out.println(Arrays.toString(objects));
}
transaction.commit();
session.close();
}
以上的某些方法中用到的两种方式其中一种放在了注释中。