一、Hibernate的基本概念

前言

Hibernate是一个ORM框架,ORM是Object Relational Mapping的缩写,即对象关系映射,也就是将面向对象思想的编程语言与关系型数据库进行映射,让开发者可以用面向对象的思想来进行数据库的增删改查操作。

比如,Java是面向对象的语言,MySQL是关系型数据库,ORM框架就是将这两者进行映射

当下主流的ORM框架除了Hibernate,还有Mybatis。

1.Hibernate简介

Hibernate对数据库结构提供了校完整的封装,Hibernate的O/R Mapping实现了POJO和数据库表之间的映射,以及SQL的自动生成和执行。我们往往只需定义好了POJO到数据库表的映射关系,即可他那个个Hibernate提供的方法完成持久层操作。程序员甚至不需要对SQL的熟练掌握,Hibernate/OJB会根据制定的存储逻辑,自动生成对应的SQL并调用JDBC接口加以允许。

2.Hibernate和MyBatis的区别

MyBatis简介:MyBatis的着力点,在于POJO 与SQL之间的映射关系。然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定POJO。

区别:

  1. Hibernated 的设计理念完全是面向POJO的,而MyBatis不是。
  2. Hibernate基本不需要我们编写SQL语句就可以通过映射关系来操作数据库,是一种全表映射的体现,而MyBatis需要我们提供SQL去运行。
  3. 在复杂查询的情况下,由于无需SQL,通过Hibernate查询会造成很多的性能丢失。而MyBatis不会,因为MyBatis可以自由书写SQL、支持动态SQL、处理列表、动态生成表名,支持存储过程。非常的灵活,可以满足各类需求和性能优化。

在管理系统时代,Hibernate是主流

​ 因为在管理系统中,首先是实现业务逻辑,然后才是性能。

在移动互联网时代,MyBatis是首选

​ 因为MyBatis不屏蔽SQL,程序员可以自己制定SQL规则,能更加精确定义SQL,从而优化性能。更符合移动互联网高并发,大数据,高性能,高响应的要求。

二、Hibernate的使用

了解完Hibernate的基本概念,接下来讲解如何使用。简单分为五个步骤:

1.导入相关jar包(两组jar包,一组Hibernatejar包,一组Oracle驱动jar包)。

2.创建Hibernate配置文件。

3.创建实体类。

4.创建实体-关系映射文件。

5.调用HibernateAPI对数据库进行管理。

1.添加相关依赖

我是创建了一个maven项目,所以需在pom.xml文件中导入以下依赖

        <!-- Oracle的jdbc驱动包 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>12.1.0.2.0</version>
</dependency>
<!-- 添加Hibernate依赖 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.6.10.Final</version>
</dependency>
<!-- 添加Log4J依赖 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.6.4</version>
</dependency>
<!-- 添加javassist -->
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.0.GA</version>
</dependency>

2.创建配置文件

2.1.在项目中添加Hibernate,Ctrl+ALT+Shift+S

2.2.生成hibernate.cfg.xml配置文件,点击+号然后会出来一个文件

在resources中会生成一个怎样的配置文件

3.配置hibernate.cfg.xml

接下来就是配置Hibernate的属性了,这里我配置了这些属性

    <session-factory>
<!--配置Oracle连接数据库的基本信息-->
<property name="connection.username">Li</property>
<property name="connection.password">123456</property>
<property name="connection.driver_class">
oracle.jdbc.driver.OracleDriver
</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
<!--每个数据库都有其对应的方言(Dialect)以匹配其平台特性-->
<property name="dialect">
org.hibernate.dialect.Oracle10gDialect
</property>
<!--指定当前session范围和上下文-->
<property name="current_session_context_class">thread</property>
<!--是否将运行期生成的SQL输出到日志以供调试-->
<property name="show_sql">true</property>
<!--是否格式化SQL-->
<property name="format_sql">true</property>
</session-factory>

简单介绍一下之前没见过的参数:

  1. dialect:

    用于配置Hibernate的数据库类型。Hibernate支持几乎所有的主流数据库,包括Oracle、DB2、MS SQL Sserver 和Mysql等。org.hibernate.dialect.Oracle10gDialect指定当前数据库类型是Oracle 10g及以上版本。current_session_context_class

  2. current_session_context_class

    指定org.hibernate.context.CurrentSessionContext.currentSession()方法所得到的Session由谁来管理。thread指Session由当前执行的线程来跟踪管理。

  3. show_sql

    如果设置为true,则程序运行时在控制台输出SQL语句。

  4. format_sql

    如果设置为true,则程序运行时在控制台输出格式化后的SQL语句。

4.创建持久化类和映射文件

4.1 实体类

注意事项

  1. 必须有一个无参构造函数

    因为Hibernate查询出数据需要将数据封装到一个对象中,底层通过反射机制调用无参构造创建对象,所以必须提供无参构造函数,否则代码报错。

  2. 提供一个标识属性,表的主键

    此属性一般定义为id,int类型,与业务无关,只是用来标识对应表的主键。

  3. 类的所有属性都要有getter和setter方法

    Hibernate通过setter方法将查询出的字段值分别赋给对应对象的各个属性,通过getter方法取属性值,若没有gtter和setter方法,直接报错,必须同时拥有这两个方法。

  4. 建议为实体类实现java.io.Serializable接口,这并不是Hibernate所要求的,为了在将持久化类用于数据传输等用途时能够对其实例正确执行序列化操作。

部门持久化类Dept.java的代码:

@Data
public class Dept implements Serializable {
private Byte deptNo;
private String deptName;
private String location;
}

4.2 实体映射关系文件

创建持久类后,Hibernate会根据此文件将持久化类数据库进行关联,需要“告诉”Hibernate,持久化类映射到数据库的哪个表,以及哪个属性对应到数据库表的哪个字段,这些都要在持久类的映射文件中配置。此文件与持久化类在同一包下。

注意:在Hibernate中,映射文件通常与对应的持久化类同名,并以“.hbm.xml”作为后缀。

特别注意:Maven默认的只编译加载resources目录的配置文件,如果把文件放在了java目录下,需要在pom.xml中添加如下配置(eclipse中可能不会出现这种情况)

<build>
<resources> 
<resource> 
<directory>src/main/java</directory>  
<includes> 
<include>**/*.xml</include> 
</includes>  
<filtering>true</filtering> 
</resource>  
<resource> 
<directory>src/main/resources</directory> 
<includes>  
<include>**/*.xml</include>   
<include>**/*.properties</include>   
</includes> 
</resource> 
</resources>
</build>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--在dept包下-->
<hibernate-mapping package="com.lily.pojo.dept">
<!--类名为Dept,表名为DEPT-->
<class name="Dept" table="`DEPT`">
<!--主键映射,属性名为deptNo,列名为DEPTNO-->
<id name="deptNo" type="java.lang.Byte" column="`DEPTNO`">
<!--主键由应用程序负责生成,无需Hibernate参与。这是指定<generator>元素时的默认生成策略-->
<generator class="assigned"/>
</id>
<!--非主键映射,属性和列名一一对应-->
<property name="deptName" type="java.lang.String" column="`DNAME`"/>
<property name="location" type="java.lang.String" column="LOC"/>
</class>
</hibernate-mapping>

映射文件定义完毕,还需要在配置文件hibernate.cfg.xml中声明

    <session-factory>
<!--其他配置文件省略-->
<!--映射文件配置,注意文件名必须包含相对于classpath的全路径-->
<mapping resource="hbm/Dept.hbm.xml"/>
</session-factory>

4.3 操作数据库的七个步骤

  1. ​ 读取并解析配置文件及映射文件。

    //获取加载配置管理类  
    Configuration configuration = new Configuration();
    //不给参数就默认加载hibernate.cfg.xml文件,
    configuration.configure();
  2. 依据配置文件和映射文件中的信息,创建SessionFactory对象。

    //创建Session工厂对象    
    SessionFactory factory = configuration.buildSessionFactory();
  3. 打开Session

     //得到Session对象  
    Session session = factory.openSession(); //或者 factory.getCurrentSession();
  4. 开启事务

     //使用Hibernate操作数据库,都要开启事务,得到事务对象  
    Transaction transaction = session.beginTransaction();
  5. 数据库操作

    //把对象添加到数据库中  
    session.save(user);
  6. 结束事务

    //提交事务
    transaction.commit();

    //回滚事务
    transaction.rollback();
  7. 如果是通过SessionFactory的openSession()方法获取的Session对象,则需要关闭session

    session.close();
    
    

    ps:如果在Hibernate配置文件中将参数current_session_context_class设置为thread,并采用SessionFactory的getCurrentSession()方法获得Session对象,则不需要执行session.close()方法,通过这种方式获得的Session对象,会在管理的事务结束(提交或回滚)时自动关闭。

4.4 管理SessionFactory和Session工具类

​ 在项目开发过程中,通常使用工具类来管理SessionFactory和Session,代码如下

public class HibernateUtil {
private static Configuration configuration;
private static SessionFactory sessionFactory; //初始化Configuration和SessionFactory
static {
try {
configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
} catch (HibernateException e) {
e.printStackTrace();
}
} private HibernateUtil(){}
//获取Session对象
public static Session currentSession(){
return sessionFactory.getCurrentSession();
}
}

在此工具类中,采用SessionFactory的getCurrentSession()方法获取Session对象,结合Hibernate配置文件中的如下设置:

<property name="current_session_context_class">thread</property>

三、 增删改查示例

为了简化编码我们可以定义一个DAO基类,对获得Session方法调用进行封装,代码如下

public class BaseDao {
public Session currentSession(){
return HibernateUtil.currentSession();
}
}

1. DAO层

public class DeptDao extends BaseDao {
/**
* 根据主键查询,传入对应的class和id就可以查询
* @param id 主键id
* @return 实体对象
*/
public Dept get(Serializable id){
//通过Session的get()方法根据OID加载指定对象
return (Dept) currentSession().get(Dept.class,id);
} /**
* 根据主键查询,支持懒加载
* @param id 主键id
* @return 查询的实体
*/
public Dept load(Serializable id){
//通过Session的load()方法根据OID加载指定对象
return (Dept) currentSession().load(Dept.class,id);
} /**
* 保存
* @param dept 实体对象
*/
public void save(Dept dept){
currentSession().save(dept); //保存指定的Dept对象
} /**
* 删除
* @param dept 实体对象
*/
public void delete(Dept dept){
currentSession().delete(dept); //删除指定的Dept对象
}
}

2. Service层

@Data
public class DeptBiz {
private DeptDao deptDao = new DeptDao(); /** 根据id查找
* @param id 主键id
* @return 实体对象
*/
public Dept findDeptById(Byte id){
Transaction tx = null;
Dept result = null;
try {
//开启事务
tx = HibernateUtil.currentSession().beginTransaction();
result = deptDao.get(id); //调用Dao方法,根据OID加载指定Dept对象
//输出结果,与调用get()方法时不同,须在关闭会话前测试查询效果
//提交事务
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback();//回滚事务
}
}
return result;
} /**
* 添加
* @param dept 实体对象
*/
public void addNewDept(Dept dept){
Transaction tx = null;
try {
tx = deptDao.currentSession().beginTransaction(); //开启事务
deptDao.save(dept);
tx.commit(); //提交事务
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback(); //回滚事务
}
}
} /**
* 修改
* @param dept 实体对象
*/
public void updateDept(Dept dept){
Transaction tx =null;
try {
tx = deptDao.currentSession().beginTransaction(); //开启事务
//加载要修改的部门对象
Dept deptToUpdate = deptDao.load(dept.getDeptNo());
//更新部门数据
deptToUpdate.setDeptName(dept.getDeptName());
deptToUpdate.setLocation(dept.getLocation());
//提交事务
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback(); //回滚事务
}
} } /**
* 删除
* @param id 主键id
*/
public void deleteDept(Byte id){
Transaction tx = null;
try {
tx = deptDao.currentSession().beginTransaction(); //开启事务
//加载需删除的部门对象
Dept deptToDelete = deptDao.load(id);
deptDao.delete(deptToDelete);
tx.commit(); //提交事务
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback(); //回滚事务
}
}
}
}

3. 测试类

public class CRUDTest {

    DeptBiz deptBiz =new DeptBiz();

    /**
* 查询
*/
@Test
public void testGetAllById(){
//1.加载数据操作
Dept dept = deptBiz.findDeptById(new Byte("10"));
//2.输出数据
System.out.println(dept.getDeptName());
} /**
* 添加
*/
@Test
public void testAddDept(){
//构建测试数据
Dept dept = new Dept();
dept.setDeptNo(new Byte("11"));
dept.setDeptName("测试部");
dept.setLocation("东区");
//保存新部门信息
deptBiz.addNewDept(dept);
} /**
* 修改
*/
@Test
public void testUpdateDept(){
//构建测试数据
Dept dept = new Dept();
dept.setDeptNo(new Byte("11"));
dept.setDeptName("质管部"); //发生变化
dept.setLocation("东区");
//更新
deptBiz.updateDept(dept);
} /**
* 删除
*/
@Test
public void testDeleteDept(){
deptBiz.deleteDept(new Byte("11"));
}
}

总结:

Hibernate作为一个主流的ORM框架,我们需要学会怎样去使用。框架的使用很简单,可以将其理解为一个别人封装好的工具交给你来使用,所以单纯开发的角度讲,我们只需要学会怎样去使用框架,按照作者指定的方式去进行开发即可。当然,底层的原理最好也需要简单的理解,多关注,多思考,对提供我们自己的编程思想是有很大的帮助的。


Hibernate快速入门之CRUD的更多相关文章

  1. (转)Hibernate快速入门

    http://blog.csdn.net/yerenyuan_pku/article/details/64209343 Hibernate框架介绍 什么是Hibernate 我们可以从度娘上摘抄这样有 ...

  2. Structs+Spring+Hibernate快速入门

    Structs+Spring+Hibernate,这是很经典的一个搭配,它的开发流程也比较程式化,下面以用户注册为例.     注册页面代码: <%@page contentType=" ...

  3. 01.Hibernate快速入门

    第一步:下载Hibernate5的运行环境 https://sourceforge.net/projects/hibernate/files/hibernate-orm/ 第二步:在数据库创建表 Cr ...

  4. hibernate快速入门示例

    hibernate概述 hibernate是一个java的全自动ORM框架,它可以自动生成SQL语句.自动建表.自动执行,使用者可以不使用SQL完成数据的CRUD操作,同时它也是基于JPA规则的一种实 ...

  5. hibernate快速入门

    第一步:下载Hibernate的开发包: http://sourceforge.net/projects/hibernate/files/hibernate3 第二步:Hibernate框架目录结构: ...

  6. Hibernate快速入门实例

    Hibernate工程项目创建基本步骤:导包(Hibernate依赖包.SQL驱动包).编写实体类.编写ORM映射配置文件.编写核心配置文件.编写测试驱动. 整个工程项目结构如下图: 一.导包 笔者使 ...

  7. 笔记47 Hibernate快速入门(四)

    Hibernate注解,完成原来xml文件里的映射信息. 使用注解时,要修改hibernate.cfg.xml中的映射,不再是通过xml文件 <mapping class="hiber ...

  8. 笔记46 Hibernate快速入门(三)

    Hibernate相关概念 一.事物概念 Hibernate的任何对数据有改动的操作,都应该被放在事务里面. hibernate中的事务由s.beginTransaction();开始由s.getTr ...

  9. 笔记45 Hibernate快速入门(二)

    Hibernate O/R 映射 一.多对一 一个Product对应一个Category,一个Category对应多个Product,所以Product和Category是多对一的关系.使用hiber ...

随机推荐

  1. 6362. 【NOIP2019模拟2019.9.18】数星星

    题目描述 题解 一种好想/好写/跑得比**记者还快的做法: 对所有询问排序,按照R递增的顺序来处理 维护每个点最后一次被覆盖的时间,显然当前右端点为R时的答案为所有时间≥L的点的权值之和 LCT随便覆 ...

  2. 理解URL以及如何区分相对URL和绝对URL

    URL(Uniform Resource Locator 统一资源定位符)可以理解为网络地址. url 包含了关于文件储存位置和浏览器应该如何处理文件的信息. URL的第一个部分称为模式scheme, ...

  3. HDU 6620 Just an Old Puzzle

    Time limit 2000 ms Memory limit 262144 kB OS Windows 解题过程 感觉搜索不可行,状态太多了,120步,判断状态是否重复时,即使用std::map也太 ...

  4. adaboost面试题

    1.简述权值更新方法 (1)初始化权值分布: (2)找到误差最小的弱分类器: (3)计算弱分类器的权值: (4)更新下一轮样本的权值分布: (5)集合多个弱分类器成一个最终的强分类器. 2.为什么能快 ...

  5. 双系统使用Linux引导

    今天在装linux的window双系统时,出现在无法使用linux引导的问题,开机总是自动进windows,照理来说我先装的window,后装的linux,应该是开机进grub引导才对.在主板的boo ...

  6. [CSP-S模拟测试]:树(树上上升序列+主席树+线段树)

    题目传送门(内部题78) 输入格式 第一行输入两个整数$n,q$,表示节点数和询问数. 第二行输入$n$个整数$w_i$,表示第$i$个点的智商. 第三行至第$n+1$行每行输入两个数$x,y$,表示 ...

  7. python的filter,reduce,map

    1.filter filter(func,iter) 只能处理一个参数(iter),仅仅将满足func方法的数值过滤出来 如: a = [,,,,] list(filter(lambda x:x> ...

  8. Gym 100507H - Pair: normal and paranormal

    题目链接:http://codeforces.com/gym/100507/attachments -------------------------------------------------- ...

  9. So the type system doesn’t feel so static.

    object wb{ def main(args:Array[String]){ println("Happy everyday!DATA-CENTER!") println(ne ...

  10. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第1节 Scanner类_1-API概述和使用步骤

    官方翻译的中文版本