• 3.hibernate


    1. hibernate框架

    框架的含义:

    • 1.框架是用来提高开发效率的
    • 2.封装了好了一些功能.我们需要使用这些功能时,调用即可.不需要再手动实现.
    • 3.所以框架可以理解成是一个半成品的项目.只要懂得如何驾驭这些功能即可.

    javaEE三层开发框架及hibernate框架对应的位置如下:

    Hibernate框架优点: 操作数据库的时候,可以以面向对象的方式来完成.不需要书写SQL语句

    Hibernate框架:是当今主流的Java持久层框架之一,由于它具有简单易学、灵活性强、扩展性强等特点,能够大大地简化程序的代码量,提高工作效率,因此受到广大开发人员的喜爱。

    Hibernate是一个开放源代码的ORM(object relationship mapping,关系对象映射)框架,它对JDBC进行了轻量级的对象封装,使得Java开发人员可以使用面向对象的编程思想来操作数据库。

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。

    为什么学习Hibernate?

     使用传统的JDBC开发应用系统时,如果是小型应用系统,并不觉得有什么麻烦,但是由于大型应用系统的开发,使用JDBC就会显得力不从心。例如对几十、几百张包含几十个字段的表进行插入操作时,编写的SQL语句不但很长,而且繁琐,容易出错;在读取数据时,需要写多条getXxx语句从结果集中取出各个字段的信息,不但枯燥重复,并且工作量非常大。为了提高数据访问层的编程效率,Gravin King开发出了一个当今最流行的ORM框架,它就是Hibernate框架。

    所谓的ORM就是利用描述对象和数据库表之间映射的元数据,自动把Java应用程序中的对象,持久化到关系型数据库的表中(自动创建表)。通过操作Java对象,就可以完成对数据库表的操作。可以把ORM理解为关系型数据和对象的一个纽带,开发人员只需要关注纽带一端映射的对象即可。ORM原理:

    与其它操作数据库的技术相比,Hibernate具有以下优势:

    • Hibernate对JDBC访问数据库的代码做了轻量级封装,大大简化了数据访问层繁琐的重复性代码,并且减少了内存消耗,加快了运行效率。
    • Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现,它很大程度的简化了DAO(Data Access Object,数据访问对象)层编码工作。
    • Hibernate的性能非常好,映射的灵活性很出色。它支持很多关系型数据库,从1对1到多对多的各种复杂关系。
    • 可扩展性强,由于源代码的开源以及API的开放,当本身功能不够用时,可以自行编码进行扩展。

    orm分4级
    hibernate属于4级:完全面向对象操作数据库
    mybatis属于2级
    dbutils属于1级

    Hibernate5.0.7的目录介绍:

    • documentation文件夹:存放Hibernate的相关文档,包括参考文档的API文档。
    • lib文件夹:存放Hibernate编译和运行所依赖的JAR包。其中required子目录下包含了运行Hibernate5项目必须的JAR包。
    • project文件夹:存放Hibernate各种相关的源代码。

    2. Hibernate入门

      框架搭建

    • 导包

    lib/required子目录中,包含的JAR包

    驱动包

    日志记录包

    • 创建实体(持久化类):创建数据库,准备表,实体

    持久化类是应用程序中的业务实体类,这里的持久化是指类的对象能够被持久化保存到数据库中。

    Hibernate使用普通Java对象(Plain Old Java Object),即POJO的编程模式来进行持久化。POJO类中包含的是与数据库表相对应的各个属性,这些属性通过getter和setter方法来访问,对外部隐藏了内部的实现细节。下面就来编写Customer持久化类。

    在项目src目录下,创建cn.eagle.domain包,并在保重创建类Customer(对应数据库表cst_customer),Customer类包含了与cst_customer数据表字段对应的属性,以及相应的getXxx()和setXxx()方法。

     1 package cn.eagle.domain;
     2 
     3 public class Customer {
     4 
     5     private Long cust_id;
     6     private String cust_name;
     7     private String cust_source;
     8     private String cust_industry;
     9     private String cust_level;
    10     private String cust_phone;
    11     private String cust_mobile;
    12 
    13     public Long getCust_id() {
    14         return cust_id;
    15     }
    16 
    17     public void setCust_id(Long cust_id) {
    18         this.cust_id = cust_id;
    19     }
    20 
    21     public String getCust_name() {
    22         return cust_name;
    23     }
    24 
    25     public void setCust_name(String cust_name) {
    26         this.cust_name = cust_name;
    27     }
    28 
    29     public String getCust_source() {
    30         return cust_source;
    31     }
    32 
    33     public void setCust_source(String cust_source) {
    34         this.cust_source = cust_source;
    35     }
    36 
    37     public String getCust_industry() {
    38         return cust_industry;
    39     }
    40 
    41     public void setCust_industry(String cust_industry) {
    42         this.cust_industry = cust_industry;
    43     }
    44 
    45     public String getCust_level() {
    46         return cust_level;
    47     }
    48 
    49     public void setCust_level(String cust_level) {
    50         this.cust_level = cust_level;
    51     }
    52 
    53     public String getCust_phone() {
    54         return cust_phone;
    55     }
    56 
    57     public void setCust_phone(String cust_phone) {
    58         this.cust_phone = cust_phone;
    59     }
    60 
    61     public String getCust_mobile() {
    62         return cust_mobile;
    63     }
    64 
    65     public void setCust_mobile(String cust_mobile) {
    66         this.cust_mobile = cust_mobile;
    67     }
    68 
    69     @Override
    70     public String toString() {
    71         return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + ", cust_source=" + cust_source
    72                 + ", cust_industry=" + cust_industry + ", cust_level=" + cust_level + ", cust_phone=" + cust_phone
    73                 + ", cust_mobile=" + cust_mobile + "]";
    74     }
    75 
    76 }
    Customer
    • 创建映射文件

    实体类Customer目前还不具备持久化操作的能力,而Hibernate需要知道实体类Customer映射到数据库Hibernate中的哪个表,以及类中的哪个属性对应数据库表中的哪个字段,这些都需要在映射文件中配置。

    在实体类Customer所在的包中,创建一个名称为Customer.hbm.xml的映射文件,在该文件中定义了实体类Customer的属性是如何映射到cst_customer表的列上的。

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
     3 <hibernate-mapping>
     4     <class name="cn.eagle.domain.Customer" table="cst_customer">
     5         <id name="cust_id" column="cust_id">
     6             <generator class="native"></generator>
     7         </id>    
     8         <property name="cust_name" column="cust_name"></property>
     9         <property name="cust_source" column="cust_source"></property>
    10         <property name="cust_industry" column="cust_industry"></property>
    11         <property name="cust_level" column="cust_level"></property>
    12         <property name="cust_phone" column="cust_phone"></property>
    13         <property name="cust_mobile" column="cust_mobile"></property>
    14     </class>
    15 </hibernate-mapping>
    Customer.hbm.xml
    • 创建Hibernate的核心配置文件

    Hibernate的映射文件反映了持久化类和数据库表的映射信息,而Hibernate的配置文件则主要用来配置数据库连接以及Hibernate运行时所需要的各个属性的值。在项目的src下创建一个名称为hibernate.cfg.xml的文件

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" >
     3 <hibernate-configuration>
     4   <session-factory>
     5       <property name="hibernate.connection.dirver_class">com.mysql.jdbc.Driver</property>
     6       <property name="hibernate.connection.url">jdbc:mysql:///day24_db</property>
     7       <property name="hibernate.connection.username">root</property>
     8       <property name="hibernate.connection.password">toor</property>
     9       <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    10       <property name="hibernate.show_sql">true</property>
    11       <property name="hibernate.format_sql">true</property>
    12       <property name="hibernate.hbm2ddl.auto">update</property>
    13       <mapping resource="cn/eagle/domain/Customer.hbm.xml"/>
    14   </session-factory>
    15 </hibernate-configuration>
    hibernate.cfg.xml

    3. Hibernate配置文件详解

    在以上部分中,我们已经接触过Hibernate的映射文件和配置文件。接下来,将对这些文件进行详细的讲解。

    • 映射文件Customer.hbm.xml用于向Hibernate提供持久化类到关系型数据库的映射,每个映射文件的结构基本都是相同的,其普遍的代码形式如下所示:

    <?xml version="1.0" encoding="UTF-8"?>

     

    <!-- 映射文件的dtd信息 -->

    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping>

     

     <-- class元素:配置实体与表的对应关系

            name:完整类名;

            table:数据库表名。(如果类名和表名是一致的,那么table属性可以省略) -->

    <class name="cn.eagle.domain.Customer" table="cst_customer">

      

     <!-- id元素:配置主键映射的属性

            name:主键对应的属性名;

            column(可选):填写表中的主键列名。默认值:列名会默认使用属性名;

            type(可选):填写列(属性)的类型。Hibernate会自动检测实体的属性类型。

              每个类型有三种填法:java类型|hibernate类型(默认)|数据库类型;

            not-null(可选):配置该属性(列)是否不能为空。默认值:false

            length(可选):配置数据库中列的长度,默认值:使用数据库类型的最大长度

      -->    

     

    <id name="cust_id" column="cust_id">

    <generator class="native"></generator>      // 主键的生成策略

    </id>

     

     <!-- 其它属性使用property标签来映射 -->

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

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

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

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

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

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

    </class>

    </hibernate-mapping>

    映射文件通常是一个xml文件即可,但一般命名为类名.hbm.xml

    • 核心配置文件hibernate.cfg.xml包含了连接持久层与映射文件所需的基本信息,其配置文件有两种格式,具体如下:
      • 一种是properties属性文件格式的配置文件,它使用键值对的形式存放信息,默认文件名称为Hibernate.properties;
      • 另一种是XML格式的配置文件,XML配置文件的默认名称为hibernate.cfg.xml。

      上述两种配置文件是等价的,具体使用哪个可以自由选择。XML格式的配置文件更易于修改,配置能力更强,当改变低层应用配置时不需要改变和重新编译代码,只修改配置文件的相应属性即可,而properties格式的文件则不具有次优势,因此,在实际开发项目中,大多数情况会使用XML格式的配置文件。下面将对XML格式的配置文件进行详细介绍。

      hibernate.cfg.xml配置文件一般在开发时会放置在src的源文件夹下,发布后,该文件会在项目的WEB-INF/classes路径下。配置文件的常用配置信息如下所示。

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" >

    <hibernate-configuration>

    <session-factory>

     

      <!-- 5个必选连接数据库基本参数属性

        hibernate.connection.dirver_class 数据库驱动

        hibernate.connection.url    数据库url

        hibernate.connection.username  数据库连接用户名

        hibernate.connection.password  数据库连接密码

        hibernate.dialect    数据库方言,不同的数据库中,sql语法略有区别,

                    指定方言可以让hibernate框架在生成sql语句时,针对数据库的方言生成;

            sql99标准:DDL 定义语言 库表的增删改查

                  DCL 控制语言  事务、权限

                  DML  操纵语言  增删改查

                注意: Mysql在选择方言时,请选择最短的方言

        hibernate.connection.autocommit  可选,事务是否自动提交

      -->

     

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

    <property name="hibernate.connection.url">jdbc:mysql:///day24_db</property>

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

    <property name="hibernate.connection.password">toor</property>

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

     

      <!-- 3个可选属性

         hibernate.show_sql 将hibernate生成的sql语句打印到控制台

         hibernate.format_sql  将hibernate生成的sql语句格式化(语法缩进)

         hibernate.hbm2ddl.auto (auto scheme export 自动导出表结构,自动建表)

           create: 自动建表.每次框架运行都会创建新的表,以前的表将会被覆盖,表数据会丢失。(开发环境中测试使用)

           create-drop: 自动建表。每次框架运行结束都会将所有表删除。(开发环境中测试使用)

           update: 推荐使用  自动生成表,如果已经存在不会再生成,如果表有变动,自动更新表(不会删除任何数据)

           validate: 校验 不自动生成表。每次启动会校验数据库中表是否正确,只会使用原有的表 -->

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

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

    <property name="hibernate.hbm2ddl.auto">update</property>

     

      <!-- 引入orm源数据

        路径书写:填写src下的路径   -->

    <mapping resource="cn/eagle/domain/Customer.hbm.xml" />

    </session-factory>

    </hibernate-configuration>

    4. Hibernate API详解

    • Configuration

    Configuration主要用于Hibernate框架加载映射文件,它的作用是对Hibernate进行配置,以及对它进行启动。在Hibernate的启动过程中,Configuration类的实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。虽然Configuration类在整个Hibernate项目中只扮演着一个很小的角色,但他是启动hibernate时所遇到的第一个对象;

    Configuration实例用于启动、加载、管理hibernate的配置文件信息。在启动Hibernate的过程中,Configuration实例首先确定Hibernate配置文件的位置,然后读取相关配置,最后创建一个唯一的SessionFactory实例。Configuration对象只存在于系统的初始化阶段,它将SessionFactory创建完成后,就完成了自己的使命。

    Configuration cfg = new Configuration().configure();

    此种方式默认会去src下读取hibernate.cfg.xml配置文件。如果不想使用默认的hibernate.cfg.xml配置文件,而是使用指定目录下(或自定义)的配置文件,则需要向configuration()方法中传递一个文件路径的参数即可。

    也可以使用该对象加载映射文件:

    configuration.addResource("cn/eagle/domain/Customer.hbm.xml");

    • SessionFactory

    该接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。

    SessionFactory接口负责Hibernate的初始化和建立Session对象。它在Hibernate中起到一个缓冲区作用,Hibernate可以将自动生成的SQL语句、映射数据以及某些可重复利用的数据放在这个缓冲区中。同时它还保存了对数据库配置的所有映射关系,维护了当前的二级缓存。

    SessionFactory实例是通过Configuration对象获取的,其获取方法如下所示:

    SessionFactory sessionFactory = cfg.buildSessionFactory();

    它的特点如下:

      1. 它是线程安全的,它的同一个实例能够供多个线程共享。

      2. 它是重量级的,不能随意的创建和销毁它的实例

      3. 负责保存和使用所有配置信息,消耗内存资源非常大

      4. 保证在web项目中,值创建一个SessionFactory

    由于SessionFactory的这些特点,一般情况下,一个项目中只需要一个SessionFactory,只有当应用中存在多个数据源时,才为每个数据源建立一个SessionFactory实例。因此,在实际项目使用中,通常会抽取出一个HibernateUtils的工具类,用来提供Session对象。

    SessionFactory内部还维护了一个连接池,如果我们需要使用第三方的连接池如C3P0,那么需要我们自己手动进行配置

    <!-- 配置C3P0连接池  -->

    <property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>

    <!-- 在连接池中可用的数据库连接的最少数目 -->

    <property name="c3p0.min_size">5</property>

    <!-- 在连接池中所有数据库连接的最大数目 -->

    <property name="c3p0.max_size">20</property>

    <!-- 设定数据库连接的过期时间,以秒为单位,如果连接池中的某个数据库连接处于

    空闲状态的时间超过了timeout时间,就会从连接池中清除 -->

    <property name="c3p0.timeout"></property>

    <!-- 每3000秒检查所有连接池中的空闲连接,以秒为单位 -->

    <property name="c3p0.idle_test_period">3000</property>

    测试C3P0连接池

    新建测试单元

     1 package cn.eagle.test;
     2 
     3 import static org.junit.Assert.*;
     4 
     5 import java.sql.Connection;
     6 import java.sql.SQLException;
     7 
     8 import org.hibernate.Session;
     9 import org.hibernate.SessionFactory;
    10 import org.hibernate.Transaction;
    11 import org.hibernate.cfg.Configuration;
    12 import org.hibernate.jdbc.Work;
    13 import org.junit.After;
    14 import org.junit.Before;
    15 import org.junit.Test;
    16 
    17 public class HibernateTestC3P0 {
    18     private SessionFactory sessionFactory;
    19     private Session session;
    20     private Transaction transaction;
    21     
    22     @Before
    23     public void init() {
    24         Configuration configuration = new Configuration().configure();
    25         sessionFactory = configuration.buildSessionFactory();
    26         session = sessionFactory.openSession();
    27         transaction = session.beginTransaction();
    28     }
    29     
    30     @After
    31     public void destroy() {
    32         transaction.commit();
    33         session.close();
    34         sessionFactory.close();
    35     }
    36     
    37     @Test
    38     public void test() {
    39         session.doWork(new Work() {
    40 
    41             @Override
    42             public void execute(Connection conn) throws SQLException {
    43                 System.out.println(conn);
    44             }
    45             
    46         });
    47     }
    48 
    49 }
    HibernateTestC3P0

    • Session

    Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句)。但需要注意的是Session对象是非线程安全的。同时,Hibernate不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSession对象称为用户session。

    Session是应用程序与数据库之间交互操作的一个单线程对象,是Hibernate运作的中心,它的主要功能是为持久化对象提供创建、读取和删除的能力,所有持久化对象必须在session的管理下才可以进行持久化操作。

    创建SessionFactory实例后,就可以通过它获取Session实例。获取Session实例有两种方式,

    一种是通过openSession()方法,另外一种是通过getCurrentSession()方法。两种方法获取session的代码如下所示:

    Session session = sessionFactory.openSession();

    Session session = sessionFactory.getCurrentSession();

    以上两种获取session实例方式的主要区别是,采用openSession方法获取Session实例时,SessionFactory直接创建一个新的Session实例,并且在使用完成后需要调用close方法进行手动关闭。而getCurrentSession方法创建的Session实例会被绑定到当前线程中,它在提交或回滚操作时会自动关闭。

     Session是线程不安全的,多个并发线程同时操作一个Session实例时,就可能导致Session数据存取的混乱(方法内部定义和使用Session时,不会出现线程问题)。因此设计软件架构时,应避免多个线程共享一个Session实例。同时,它也是轻量级的,实例的创建和销毁不需要消耗太多的资源。它还有给个缓存,即Hibernate的一级缓存,这个缓存主要用于存放当前工作单元加载的对象。

      在Session中提供了大量的常用方法,具体如下:

      1. save()、update()和saveOrUpdate()方法:用于增加和修改对象。

      2. delete()方法:用于删除对象。

      3. get()和load()方法:根据主键查询。

      4. createQuery()和createSQLQuery()方法:用于数据库操作对象。

      5. createCriteria()方法:条件查询。 

    • Transaction

      Transaction接口是一个可选的API,可以选择不适用这个接口,取而代之的是Hibernate的设计者自己写的底层事务处理代码。Transaction接口是对实际事务实现的一个抽象,这些实现包括JDBC事务、JTA中的UserTransaction、甚至可以是CORBA事务。之所以这样设计是能让开发者能够使用一个统一事务的操作界面,使得自己的项目可以在不同的环境和容器之间方便地移植。

    Transaction接口主要用于管理事务,它是Hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是通过Session对象开启的,其开启方式如下所示。

    Transaction tx = session.beginTransaction();

     

     在Transaction接口中,提供了事务管理的常用方法,具体如下:

      1. commit()方法:提交相关联的session实例。

      2. rollback()方法: 撤销事务操作。

    Session执行完数据库操作后,要使用Transaction接口的commit()方法进行事务提交,才能真正的将数据库操作同步到数据库中。发生异常时,需要使用rollback()方法进行事务回滚,以避免数据发生错误。因此,在持久化操作后,必须调用Transaction接口的commit()方法和rollback()方法。如果没有开启事务,那么每个Session操作,都相当于一个独立的操作。

  • 相关阅读:
    通用指令-数据库通用操作
    通用指令-key通用操作
    数据类型-sorted_set类型基本操作和扩展操作
    数据类型-set类型基本操作和扩展操作
    数据类型-list类型基本操作和扩展操作
    数据类型-hash类型基本操作和扩展操作
    ORACLE 函数 NVL, NVL2, NULLIF
    maven 配置jdk版本
    maven仓库添加自己的jar包
    Map 中的EntrySet()
  • 原文地址:https://www.cnblogs.com/eaglesour/p/9481009.html
Copyright © 2020-2023  润新知