Hibernate的搭建

2022-11-15 13:36:38 浏览数 (1)

1 Hibernate概述

       Hibernate是Java世界中使用最广泛的数据持久化框架,使用ORM(对象关系映射)模式简化关系型数据库的的数据增删改查功能。

1.1 数据持久化

数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。数据模型可以是任何数据结构或对象模型,存储模型主要是关系型数据库,还可以是XML、二进制流等。在Java中提供了JDBC组件来实现对象和数据库之间的持久化。

1.2 ORM框架

(1)JDBC的不足

直接使用JDBC开发具有以下问题:开发效率低、代码冗余高和重复性工作多。为了减少数据库开发中的管道代码,把开发精力集中在解决业务问题上,Java世界出现了很多的持久化框架,比较著名的有:Hibernate、MyBatis、TopLink(Oracle商业产品)等。

(2)ORM框架

对象关系映射(ORM,Object Relation Mapping)是持久化框架经常采用的技术模式。Object是指编写程序的时候,以面向对象的方式处理数据;Relation是指保存数据的时候,以关系型数据库的方式存储;而ORM框架则通过映射信息自动完成Java对象与数据库表之间的存取。

1.3 Hibernate

Hibernate是Java世界最经典的对象关系映射框架,堪称ORM技术的典范,简化了JDBC繁琐的编码,大大增加程序可靠性。

Hibernate的创始人Gavin King是EJB3.0专家委员会成员,EJB 3.0 JPA规范的主要制定者,是JBoss核心开发者之一著有《Hibernate in Action》一书。

2 Hibernate起步

       下面通过简单的示例,介绍Hibernate的基本用法。

(1)导入hibernate依赖

代码语言:javascript复制
           <!-- mysql jdbc驱动,或替换为Oracle的jar包 -->

              <dependency>

                     <groupId>mysql</groupId>

                     <artifactId>mysql-connector-java</artifactId>

                     <version>5.1.8</version>

              </dependency>

              <!-- Hibernate 3.6.10, Core Annotation -->

              <dependency>

                     <groupId>org.hibernate</groupId>

                     <artifactId>hibernate-core</artifactId>

                     <version>3.6.10.Final</version>

              </dependency>

              <!-- 为Hibernate 提供支持 -->

              <dependency>

                     <groupId>javassist</groupId>

                     <artifactId>javassist</artifactId>

                     <version>3.9.0.GA</version>

              </dependency>

(2)构建Hibernate主配置文件

       在项目“类路径”下,添加hibernate.cfg.xml配置文件.

该文件主要配置JDBC连接、SQL方言和实体映射文件的位置。

代码语言:javascript复制
<?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>

        <!-- 数据库连接配置 -->

        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

        <property name="connection.url">jdbc:mysql://localhost:3306/MyCinema</property>

        <property name="connection.username">root</property>

        <property name="connection.password">1234</property>

        <!-- SQL方言(Dialect)配置 -->

        <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>

        <!-- 是否显示执行的SQL语句 -->

        <property name="show_sql">true</property>

              <!-- 是否格式化SQL语句 -->

        <property name="format_sql">true</property>

        <!-- 配置实体映射文件路径 -->

        <mapping resource="mapping/Category.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

(3)编写实体映射文件

在项目类路径下创建mapping文件夹,在其下创建“实体映射文件”,描述Java对象和数据库表的对应关系。

实体映射文件中元素功能如下:

  1. class元素用于声明Java类和数据库表的映射关系

2)id 元素用于声明主键属性映射,name属性用于指定对象属性名,column用于指定对应的表字段名

3)id中的generator子元素用于指定主键的生成策略,常见的策略有identity(自增长字段)、sequence(Oracle序列)、native(自适应)、uuid(全局唯一编号)等。

4)property元素用于声明普通属性映射

代码语言:javascript复制
<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

       "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    

       "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="demo.entity">

    <class name="Category" table="CATEGORY">

              <id name="id" column="ID">

                     <generator class="identity" />

              </id>

        <property name="name"  column="NAME"/>

    </class>

</hibernate-mapping>

(4)编写查询功能

       要实现查询Hibernate需要使用以下几个重要对象

  1. Configuration:用于加载配置信息(hibernate.cfg.xml),是SessionFactory的工厂。
  2. SessionFactory:Session的工厂,用于维护数据库连接池和二级缓存。在一个应用程序中,一般只需要一个SessionFactory对象,应用单例模式维护其唯一性。
  3. Session:代表Hibernate与数据库之间的一次回话,维护数据连接和一级缓存,该对象不是线程安全的,应该每次使用前创建用完关闭,建议保存在方法或请求级别。
  4. Query:用于执行HQL查询语句的工具对象,由Session对象创建。
代码语言:javascript复制
      public static void main(String[] args) {

              Configuration cfg = new Configuration();                //创建Configuration对象

              cfg.configure();                                                      //读取配置文件

              SessionFactory factory = cfg.buildSessionFactory(); //创建SessionFactory对象

              Session session = factory.openSession();                 //获取Session

              Query query = session.createQuery("from Category");    //创建查询对象

              List<Category> list = query.list();                            //执行查询

              for(Category c : list){

                     System.out.println(c.getName());

              }

              session.close();                                                       //关闭Session

       }

3 Hibernate中持久化对象的三种状态

       在Hibernate框架中的持久化对象有三种状态:瞬时状态(临时状态)、持久状态、游离状态。

(1)瞬时状态(Transient)

  通过new创建对象后,对象并没有立刻持久化,它并未与数据库中的数据有任何关联,此时Java对象的状态为瞬时状态。

Session对于瞬时状态的Java对象是一无所知的,当对象不再被其他对象引用时,它的所有数据也就丢失了,对象将会被Java虚拟机按照垃圾回收机制处理。

(2)持久状态(Persistent)

  当对象与Session关联,被Session管理时,它就处于持久状态。处于持久状态的对象拥有数据库标识(数据库中的主键值)。

  那么,对象是什么时候与Session发生关联的呢?有两种方法:

第一种,通过Sesison的查询接口,或者get()方法,或者load()方法从数据库中加载对象的时候,加载的对象是与数据库表中的一条记录关联的,此时对象与加载它的Session发生关联;

第二种,瞬时状态的对象,通过Session的save()方法或SaveOrUpdate()方法时,Java对象也与Session发生关联。

对于处于持久状态的对象,Session会持续跟踪和管理它们,如果对象的内部状态发生了任何变更,Hibernate会选择合适的时机(如事务提交时)将变更固化到数据库中。

(3)游离状态(Detached)

  处于持久状态的对象,脱离与其关联的Session的管理后,对象就处于游离状态。

  处于游离状态的对象,Session无法保证对象所包含的数据与数据库中的记录一直,因为Hibernate已经无法感知对该对象的任何操作。

Session提供了两个方法(update()、merge()),将处于游离状态的对象,与一个新的Session发生关联。

Hibernate中对象的三种状态的相互转换机制如下图所示。

4 实现DAO模式

(1)封装一个用于构建Session对象的工具类

       为维护SessionFactory的全局单例,建议创建一个HibernateUtil工具类对其进行封装。

代码语言:javascript复制
public class HibernateUtil {

       private static SessionFactory factory;                //确保单例

       static{

              Configuration cfg = new Configuration();

              cfg.configure();

              factory = cfg.buildSessionFactory();

       }

       public static Session openSession(){

              return factory.openSession();

       }

}

(2)添加DAO组件并实现增删改查功能

代码语言:javascript复制
public class CategoryDaoImpl implements CategoryDao {

       public List<Category> getAll() {

              Session sess = HibernateUtil.openSession();

              try{

                     return sess.createQuery("from Category").list();

              }finally{

                     sess.close();

              }

       }

       public Category fetchById(int id) {

              Session sess = HibernateUtil.openSession();

              try{

                     return (Category)sess.get(Category.class, id);

              }finally{

                     sess.close();

              }

       }

       public void add(Category entity) {

              Session sess = HibernateUtil.openSession();

              Transaction tx = null;

              try{

                     tx = sess.beginTransaction();

                     sess.save(entity);

                     tx.commit();

              }catch(RuntimeException ex){

                     if(tx!=null)

                            tx.rollback();

                     throw ex;

              }finally{

                     sess.close();

              }

       }

       public void update(Category entity) {

              Session sess = HibernateUtil.openSession();

              Transaction tx = null;

              try{

                     tx = sess.beginTransaction();

                     sess.update(entity);

                     tx.commit();

              }catch(RuntimeException ex){

                     if(tx!=null)

                            tx.rollback();

                     throw ex;

              }finally{

                     sess.close();

              }

       }

       public void delete(int id) {

              Session sess = HibernateUtil.openSession();

              Transaction tx = null;

              try{

                     tx = sess.beginTransaction();

                     sess.delete(sess.get(Category.class, id));

                     tx.commit();

              }catch(RuntimeException ex){

                     if(tx!=null)

                            tx.rollback();

                     throw ex;

              }finally{

                     sess.close();

              }

       }

}

0 人点赞