Hibernate框架

来源:互联网 发布:知乎 日本整容 编辑:程序博客网 时间:2024/06/10 09:26

<br>
Hibernate是一个开放源代码的对象关系映射框架(ORM),它对JDBC进行了非常轻量级的对象封装,简化了java应用程序与数据库交互的开发。简化了数据创建,数据处理和数据访问。

  • ①面向对象操作:将对数据库的操作转换为对Java对象的操作。
  • ②数据库独立查询:通过配置对应的数据库“方言”,就可以根据不同类型的数据库生成适合的SQL语句。
  • ③非侵入式:Hibernate不要求持久化类实现任何接口或继承任何类。
  • ④快速性能:Hibernate框架内部使用缓存,支持查询缓存,因此性能很快。
  • ⑤自动创建表:Hibernate框架提供了自动创建数据库表的功能。
  • ⑥简化复杂连接:在hibernate框架中可轻松获取多个表中的数据。
  • ⑦提供查询统计和数据库状态:Hibernate提供有关查询和数据库状态的统计信息。

这里写图片描述





一、ORM概念

对象关系映射(Object Relational Mapping,简称ORM),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。

把对象表示的映射到基于SQL的关系模型数据库结构中去。在具体的操作实体对象的时候,就不需要再去和复杂的 SQ L 语句打交道,只需简单的操作实体对象的属性和方法。ORM 技术是在对象和关系之间提供了一条桥梁,对象型数据和数据库中的关系型的数据通过这个桥梁来相互转。

ORM技术特点:

  • ①提高了开发效率。由于ORM可以自动将对象与数据库中的字段与属性的映射,所以已经不需要一个专用的、庞大的数据访问层。
  • ②ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。

这里写图片描述





二、第一个hibernate

(一)Hibernate体系结构

Hibernate架构包括许多对象持久对象,会话工厂,事务工厂,连接工厂,会话,事务等。hibernate架构中有4层Java应用层,持久层,hibernate映射层和数据库层。

这里写图片描述



(二)引入相关jar包

需要引入hibernate的核心包和数据库连接包。只要到maven公库就能找到相应的jar包。我使用的以下版本:

这里写图片描述

这里写图片描述


(三)映射文件(**.hbm.xml)

1、创建实体类。

package org.ssh1.entity;import java.util.Date;/** * 用来封装数据的实体类 *  * @author lee * */public class User {    private int id;    private String name;    private Date birthday;    //默认构造器    public User() {};    public int getId(){        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Date getBirthday() {        return birthday;    }    public void setBirthday(Date birthday) {        this.birthday = birthday;    }}


2、映射文件

映射文件的名称必须和实体类一样,以 .hbm.xml 结尾。例如上面实体类的映射文件则为 User.hbm.xml 。

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!--     映射文件     package属性:为该映射文件所在的包 --><hibernate-mapping package="org.ssh1.entity">    <!-- 实体类映射        name属性:对应实体类的全称,包名+类名         table属性:对应实体类的 数据库表名     -->    <class name="User" table="user">        <!-- 1、主键映射            name属性:实体类的成员变量            type属性:实体类的成员变量的类型            (可以为JAVA的类型 或 hibernate类型)         -->        <id name="id" type="int">            <!-- 字段映射                 name属性:对应数据库的字段的名称             -->            <column name="id" />            <!-- 主键的生成策略  -->            <generator class="native" />        </id>        <!-- 2、普通字段映射             name属性:实体类的成员变量名称            type属性:实体类的成员变量的类型         -->        <property name="name" type="java.lang.String">            <!-- 字段映射                 name属性:对应数据库的字段的名称             -->            <column name="name" />        </property>        <property name="birthday" type="java.util.Date">            <column name="birthday" />        </property>    </class></hibernate-mapping>


4、创建数据库

例如,上面实体类和数据库的对应
这里写图片描述
这里写图片描述

PS:实体类和映射文件必须在同一个包下面
PSPS : 实体类的成员变量 和 数据库的字段 名称可以不一样。



(四)配置文件(**.cfg.xml)

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory>    <!-- 数据库连接配置 -->        <!-- 配置文件的问题一定要注意好.            hibernate有时候即使是配置错了,在一定的条件下也可以运行。            不要因此出现问题时,而不检查配置文件的问题。 -->        <!-- mysql驱动 -->        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>        <!-- url -->        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>        <!-- 用户名 -->        <property name="hibernate.connection.username">root</property>        <!-- 密码 -->        <property name="hibernate.connection.password">qwertyuio</property>        <!-- 配置数据库的方言            根据不同的数据库,配置不同的方言。            通过这种方式,hibernate就可以以面向对象的形式来操作数据库,自动生成对应不同数据库的sql语句。            而不会因为数据库版本的不同而,而需要修改sql语句。        -->        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>        <!--             是否打印出 执行的sql语句         -->        <property name="hibernate.show_sql">true</property>        <!-- 配置映射文件             resource属性:包名+映射文件名             file属性:如果不用resource属性,file属性要求是绝对路径。         -->        <mapping resource="org/ssh1/entity/User.hbm.xml"></mapping>    </session-factory></hibernate-configuration>



(五)使用Hibernate

到了这里基本配置已经完成了。现在我们尝试使用hibernate来想数据库,保存一个对象到数据库中。

1、相关API

在使用hibernate前,我们先了解相关的API。

(1)Configuration类:负责管理 hibernate配置文件。
①Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)。
②持久化类与数据表的映射关系(*.hbm.xml 文件)

(2)SessionFactory类:
①Configuration对象根据当前的配置信息生成 SessionFactory 对象。SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息。
②SessionFactory 对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存。

(3)Session类
①Session是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短。
②Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处。相当于 JDBC 中的 Connection。持久化类与 Session 关联起来后就具有了持久化的能力

(4)Transaction类
①代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
②session.beginTransaction() 开启事务
③commit() 提交事务
④rollback() 事务回滚
⑤wasCommitted() 检查事务是否提交


2、使用hibernate

package org.ssh1.dao;import java.util.Date;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.junit.Test;import org.ssh1.entity.User;public class Dao {    @Test     public void dao() {        //创建Configuratiion对象        Configuration config = new Configuration();        //加载配置文件        //(默认加载 src下的 hibernate.cfg.xml文件,也可以传入路径参数,加载其他的配置文件)        config.configure();        //创建一个Session工厂类        SessionFactory sessionFactory = config.buildSessionFactory();        Session session = null;        Transaction trans = null;        try {            //创建一个会话            session = sessionFactory.openSession();            //开启事务            trans = session.beginTransaction();            //创建一个User对象,并添加一些信息            User user = new User();            user.setName("yang");            user.setBirthday(new Date());            //保存对象            //在这里我们可以看到,hibernate封装后的数据库操作,是以对象的形式来操作的            //不需要写任何的sql语句            session.save(user);            //提交事务            trans.commit();        }catch(Exception e) {            //出现异常,事务回滚            trans.rollback();            throw new RuntimeException(e);        }finally {            //关闭会话            session.close();        }    }}

测试运行一下:
这里写图片描述

可以看到正确执行了,保存一个User对象到数据库中。hibernate,使程序脱离了繁琐的 JDBC的操作,以操作对象的形式来操作数据库。


PS:可能出现的异常:
Field ‘id’ doesn’t have a default value
数据库表中的主键没设置自动增长。也可以将主键的配置<generator class="native"/>改为<generator class="assigned"/>
assigned是指主键是由人工分配的,native则指主键值由库自动给出。





三、hibernate 常用API

这里主要讲解如何使用 Session的方法来操作数据库。(相关的映射文件、配置文件、实体类、数据库和上面一样。)

(一)这里将hibernate的加载配置的方法,写到一个hibernate工具类中,方便我们使用。

package org.ssh1.utils;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;/** * hibernate工具类 *  * @author lee * */public class HibernateUtils {    public static SessionFactory sessionFactory ;    static {        Configuration config = new Configuration();        config.configure();        sessionFactory = config.buildSessionFactory();    }    public static Session openSession() {        return sessionFactory.openSession();    }}

(二)使用相关的API

package org.ssh1.dao;import java.util.Date;import org.hibernate.Session;import org.hibernate.Transaction;import org.junit.Test;import org.ssh1.entity.User;import org.ssh1.utils.HibernateUtils;/** * 相关的hibernate API 使用 *  * @author lee * */public class Dao {    //1、save 保存对象(数据)方法    @Test     public void testSave(){        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //因为id主键为自动增长,因此不需要指定id属性            User user = new User();            user.setName("qing");            user.setBirthday(new Date());            System.out.println("1、将一个对象保存到数据库当中:");            session.save(user);            trans.commit();        }catch(Exception e){            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //2、update 更新对象(数据)方法    @Test     public void testUpdate(){        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //更新必须要有主键,当成员变量为null的时候,也会将对应的字段更新为null            //例如:下面的User对象没有设置 birthday属性,当执行更新操作,可以看到该条数据的birthday字段为null            User user = new User();            user.setId(100);            user.setName("xiao");            System.out.println("2、将指定id值的对象 更新到数据库中:");            session.update(user);            trans.commit();        }catch(Exception e){            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //3、get 获取对象(数据)方法 (主键查询)    @Test     public void testGet(){        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //要查询对象(数据)的 id值            int id = 1;            System.out.println("3、根据 id 值获取指定的对象(数据):");            User user = session.get(User.class, id);            trans.commit();        }catch(Exception e){            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //4、load 获取对象(数据)方法 (主键查询)(懒加载,就是用到时才会去查询。)    @Test     public void testLoad(){        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //要查询对象(数据)的 id值            int id = 1;            System.out.println("4、根据 id 值获取指定的对象(数据):");            User user = session.load(User.class, id);            user.getName();//这时候才会去数据库中查找数据(懒加载)            trans.commit();        }catch(Exception e){            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //5、saveOrUpdate 保存或更新对象(数据)方法    @Test     public void testSaveOrUpdate(){        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //当该 对象的id值对应的数据,在数据库中存在时,则更新对象            //当该 对象没有设置id值 ,或id值对应的数据,在数据库中不存在时,则保存对象            User user = new User();            user.setId(99);            System.out.println("5、保存或更新一个对象(数据):");            session.saveOrUpdate(user);            trans.commit();        }catch(Exception e){            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //6、delete 删除对象(数据)方法    @Test     public void testSaveOrUpdate(){        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //以传入一个id值来删除指定的对象(数据)            int id = 88;            System.out.println("6、删除一个对象(数据):");            session.delete(id);            trans.commit();        }catch(Exception e){            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }}

测试运行一下,可以看到结果:

这里写图片描述





四、hibernate 查询方法

hibernate的查询方式常见的主要分为三种: HQL查询,QBC(Criteria)查询,以及使用原生SQL查询。

(一)HQL查询(推荐使用)

HQL(Hibernate Query Language)是hibernate提供的面向对象的查询语言,在HQL中使用类名,而不是表名。所以是数据库独立的查询语言。

HQL查询提供了更加丰富的和灵活的查询特性,因此Hibernate将HQL查询方式立为官方推荐的标准查询方式,HQL查询在涵盖Criteria查询的所有功能的前提下,提供了类似标准SQL语句的查询方式,同时也提供了更加面向对象的封装。

HQL有很多优点。 它们如下:

  • 数据库独立
  • 支持多态查询
  • 易于Java程序员学习


1、常用API

HQL查询主要是调用 Query对象的方法来实现。Query的对象可以通过Session接口调用createQuery()方法。常用的方法有:

//获取一个Query对象Query query = session.creaeteQuery("HQL语句");//将获取的结果作为列表返回public List list()//指定从哪里检索数据public Query setFirstResult(int rowno) //指定从表中检索数据的行数public Query setMaxResult(int rowno) //设置占位符的值public Query setParameter(int position, Object value) //设置占位符的值public Query setParameter(String name, Object value) 


2、常用的HQL查询方式

这里,我们介绍下一些常用的查询。
(查询所有、条件查询)(单个字段查询、单列查询、多列查询)(统计查询、分页查询)

package org.ssh1.dao;import java.util.List;import org.hibernate.Session;import org.hibernate.Transaction;import org.hibernate.query.Query;import org.junit.Test;import org.ssh1.entity.User;import org.ssh1.utils.HibernateUtils;/** * 常用的HQL查询 *  * @author lee * */public class Dao {    //1、查询所有    @Test    public void getAll() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            /*              * 类似于SQL语句,但是通过操作对象来实现的。             * 例如,"from User"  中,"User" 不是数据表的名称,而是实体类的名称。             * 相对于sql语句 (select * from user) 来,还可以略写 "select * "             *              */            //HQL语句 ,获取所有的 User对象            String HQL = "from User";            //创建一个Query类            @SuppressWarnings("unchecked")            Query<User> query = session.createQuery(HQL);            //将获取的结果作为列表返回            List<User> users = query.list();            //输出从数据库获得的结果            System.out.println(users);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //2、条件查询    @Test    public void getPart() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            /**             * 这里还有很多的条件查询,这里只是作为一个举例             *              */            //HQL语句 ,获取字段 name为指定的值的 User对象            String HQL = "from User where name = ?";            //创建一个Query类            @SuppressWarnings("unchecked")            Query<User> query = session.createQuery(HQL);            //设置第 1 个占位符的值(从0开始)            query.setParameter(0, "lee");            //query.setParameter("name","lee")//这种形式也是允许的            //获取 单一的一个 查询到的数据            User user = query.uniqueResult();            //输出从数据库获得的结果            System.out.println(user);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //3、单个字段查询    @Test    public void getSingleProperty() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            /**             * 这里还有很多的单个字段查询,这里只是作为一个举例             *              */            //HQL语句 ,获取指定 id值的对象的 name字段            String HQL = "select u.name from User u where id = ?";            //创建一个Query类            @SuppressWarnings("unchecked")            Query<String> query = session.createQuery(HQL);            //设置第 1 个占位符的值(从0开始)            query.setParameter(0, 1);            //获取 单一的一个 查询到的数据            String name = query.uniqueResult();            //输出从数据库获得的结果            System.out.println(name);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //4、单列查询    @Test    public void getSingleColumn() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            /**             * 这里还有很多的单列查询,这里只是作为一个举例             *              */            //HQL语句 ,获取所有User对象的 name 字段            String HQL = "select u.name from User u ";            //创建一个Query类            @SuppressWarnings("unchecked")            Query<String> query = session.createQuery(HQL);            //获取 多个查询到list集合            List<String> names = query.list();            //输出从数据库获得的结果            System.out.println(names);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //5、多列查询    @Test    public void getColumns() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            /**             * 这里还有很多的多列查询,这里只是作为一个举例             *              */            //HQL语句 ,获取所有User对象的 name 、id字段            String HQL = "select u.name,u.id from User u ";            //创建一个Query类            @SuppressWarnings("unchecked")            Query<Object> query = session.createQuery(HQL);            //获取 多个查询到list集合            List<Object> results = query.list();            //输出从数据库获得的结果            //因为其返回的是一个集合,集合里面装的每一个元素是数组。            for(Object result :results ) {                Object[] res = (Object[]) result;                System.out.println(res[1]+" "+res[0]);            }            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //6、统计查询    @Test    public void getSum() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            /**             * 这里还有很多的统计查询,这里只是作为一个举例             *              */            //HQL语句 ,获取 数据的总数            String HQL = "select count(*) from User";            //创建一个Query类            @SuppressWarnings("unchecked")            Query<Long> query = session.createQuery(HQL);            //获取 单一的一个 查询到的数据            Long count = query.uniqueResult();            //输出从数据库获得的结果            System.out.println(count);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //7、分页查询    @Test    public void getParts() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            /**             * 这里还有很多的分页查询,这里只是作为一个举例             *              */            //HQL语句 ,获取所有的 User对象            String HQL = "from User";            //创建一个Query类            @SuppressWarnings("unchecked")            Query<User> query = session.createQuery(HQL);            //从第 2 行开始查询            query.setFirstResult(2);            //查询 10 行数据            query.setMaxResults(10);            //获取 单一的一个 查询到的数据            List<User> users = query.list();            //输出从数据库获得的结果            System.out.println(users);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }}


(二)Criteria查询

Criteria(QBC query by criteria,完全面向对象的查询)提供了一种面向对象的方式查询数据库。

package org.ssh1.dao;import java.util.List;import org.hibernate.Criteria;import org.hibernate.Session;import org.hibernate.Transaction;import org.hibernate.criterion.Restrictions;import org.junit.Test;import org.ssh1.entity.User;import org.ssh1.utils.HibernateUtils;/** *  * Criteria查询(只做简单的介绍) * 更多关于Criteria查询可以查看其 API,进行更深度的学习 *  * @author lee * */public class CriteriaDao {    //1、获取所有的 User对象    @Test    public void getAll() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //可以看到 criteria的查询中 看到任何的类似sql的语句,完全地面向对象开发            //但是需要了解很多的API            //传入一个 类的class属性            Criteria qbc = session.createCriteria(User.class);            //获取所有            @SuppressWarnings("unchecked")            List<User> list = qbc.list();            //输出获取的结果集            System.out.println(list);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //2、条件查询    @Test    public void getPart() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //传入一个 类的class属性            Criteria qbc = session.createCriteria(User.class);            //获取指定 id 值的User            qbc.add(Restrictions.eq("id", 1));            @SuppressWarnings("unchecked")            User user = (User) qbc.uniqueResult();            //输出获取的结果集            System.out.println(user);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }}


(三)本地SQL查询

多用于使用于复杂的查询,就是使用原生态的sql查询。(不能跨数据库平台)

package org.ssh1.dao;import java.util.List;import org.hibernate.SQLQuery;import org.hibernate.Session;import org.hibernate.Transaction;import org.junit.Test;import org.ssh1.entity.User;import org.ssh1.utils.HibernateUtils;/** *  * SQL查询(只做简单的介绍) * 更多关于SQL查询可以查看其 API,进行更深度的学习 *  * @author lee * */public class CriteriaDao {    //1、获取所有的 User对象    @SuppressWarnings("deprecation")    @Test    public void getAll() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //传入一个 sql 语句            SQLQuery sql = session.createSQLQuery("select * from user");            //获取所有            @SuppressWarnings("unchecked")            List<User> list = sql.list();            //输出获取的结果集            System.out.println(list);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }    //2、条件查询    @SuppressWarnings("deprecation")    @Test    public void getPart() {        Session session = null;        Transaction trans = null;        try {            session = HibernateUtils.openSession();            trans = session.beginTransaction();            //传入一个sql语句            SQLQuery sql = session.createSQLQuery("select * from user where id=1");            @SuppressWarnings("unchecked")            User user = (User) sql.uniqueResult();            //输出获取的结果集            System.out.println(user);            trans.commit();        }catch(Exception e) {            trans.rollback();            throw new RuntimeException(e);        }finally {            session.close();        }    }}

PS:编写 hibernate的 映射文件 和 配置文件,要自己编写过于麻烦。可以在开发集成环境中,添加在 JBoss Tools插件,来帮助我们。

原创粉丝点击