01.Hibernate入门

前言:本文用一个简单的Hibernate应用程序例子来引领初学者入门,让初学者对Hibernate的使用有一个大致的认识。本文例子使用了MySQL数据库、Maven管理工具、Eclipse开发工具,创建的项目是Maven项目但是本质上只是用了Java SE的东西。

1.在Maven项目中引入Hibernate库

    我们可以在Maven官网上搜索Hibernate库,选择Hibernate版本,复制Maven依赖代码到pom.xml文件引用Hibernate。由于当前Hibernate的最新版是4.3.8.Final所以我的引用如下:
  1. <!-- 依赖项定义 -->
  2. <dependencies>
  3. <dependency>
  4. <groupId>org.hibernate</groupId>
  5. <artifactId>hibernate-core</artifactId>
  6. <version>4.3.8.Final</version>
  7. </dependency>
  8. <dependency>
  9. <groupId>mysql</groupId>
  10. <artifactId>mysql-connector-java</artifactId>
  11. <version>5.1.34</version>
  12. </dependency>
  13. </dependencies>
    如果你没有使用Maven,你也可以到Hibernate官网下载Hibernate引用到项目里,不过我在这里强烈推荐大家使用Maven管理项目,因为Maven管理很方便,它不需要你去网上找项目依赖的Jar文件,一个依赖配置就搞定。并且Maven的官网很强大几乎所有的Java开源项目都可以在这里找到!下面提供Maven的官网和Hibernate的官网:Maven:http://mvnrepository.com/ Hibernate:http://hibernate.org/

2.搭建数据库环境(MySQL)

    为了测试我在本地计算机安装了Linux虚拟机,并在虚拟机中安装了MySQL数据库。下面是我新建的测试表(tb_teacher):
  1. CREATE TABLE tb_teacher
  2. (
  3. id bigint NOT NULL auto_increment COMMENT 'ID',
  4. no varchar(10) NOT NULL COMMENT '教师编号',
  5. name varchar(50) NOT NULL COMMENT '教师姓名',
  6. sex char(1) NOT NULL COMMENT '教师性别',
  7. job_title varchar(50) NOT NULL COMMENT '职称',
  8. PRIMARY KEY (id)
  9. ) COMMENT = '教师信息表';

3.设置Hibernate配置文件(hibernate.cfg.xml)

    hibernate.cfg.xml配置文件需要放到项目ClassPath根路径,hibernate.cfg.xml配置文件是Hibernate的核心配置文件,其作用是:设置数据源、配置Hibernate属性、设置映射文件(*.hbm.xml)等。下面是一个简单的配置:
  1. <!DOCTYPE hibernate-configuration PUBLIC
  2. "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  3. "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
  4. <hibernate-configuration>
  5. <session-factory>
  6. <!-- 设置MySQL的数据库路径、用户名、密码 -->
  7. <property name="hibernate.connection.url">jdbc:mysql://192.168.10.201:3306/Study</property>
  8. <property name="hibernate.connection.username">root</property>
  9. <property name="hibernate.connection.password">lizhiwei</property>
  10. <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
  11. <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
  12. <!-- Hibernate配置 -->
  13. <property name="connection.pool_size">1</property>
  14. <property name="show_sql">true</property>
  15. <property name="current_session_context_class">thread</property>
  16. <property name="hibernate.cache.use_second_level_cache">false</property>
  17. <property name="hibernate.format_sql">true</property>
  18. <!-- 设置实体类到数据库的映射文件 -->
  19. <mapping resource="model/Teacher.hbm.xml"/>
  20. </session-factory>
  21. </hibernate-configuration>
    对于上面的配置的说明:
  1. hibernate.dialect:设置数据库方言,我使用的MySQL数据库就用MySQL数据库的方言。
  2. connection.pool_size:设置数据库连接池大小。
  3. current_session_context_class:与SessionFactory.getCurrentSession()相关,如果得到一个Session是调用这个方法(并非openSession())那么会使用这个属性。
  4. show_sql:配置是否显示Hibernate操作数据库的SQL,调试时非常有用。
  5. hibernate.format_sql:与show_sql配合使用,用于格式化打印的SQL。
  6. hibernate.cache.use_second_level_cache:是否使用Hibernate的二级缓存,关于二级缓存的使用后面的章节会讲到。
  7. <mapping resource="model/Teacher.hbm.xml"/>:设置实体类与数据库表的映射文件,关于这个映射文件的作用和内容会在下面讲到。

4.创建实体类与其映射文件(Teacher.hbm.xml)

    实体类的创建要与前面新建的表(tb_teacher)对应,下面是我的实体类(Teacher.java):
  1. package model;
  2. /**
  3. * 教师信息表
  4. * */
  5. public class Teacher
  6. {
  7. /** ID */
  8. private Long id;
  9. /** 教师编号 */
  10. private String no;
  11. /** 教师姓名 */
  12. private String name;
  13. /** 教师性别 */
  14. private String sex;
  15. /** 职称 */
  16. private String job_title;
  17. //省略setter、getter、toString...
  18. }
    创建好实体类后,Hibernate并不知道这个实体类会与数据库中的tb_teacher表对应,所以还要创建一个配置文件告诉Hibernate实体类与数据库表的映射细节,配置文件如下(Teacher.hbm.xml):
  1. <!DOCTYPE hibernate-mapping PUBLIC
  2. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  3. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  4. <hibernate-mapping package="model">
  5. <class name="Teacher" table="tb_teacher">
  6. <id name="id" column="id">
  7. <generator class="native"></generator>
  8. </id>
  9. <property name="no" column="no"/>
  10. <property name="name" column="name"/>
  11. <property name="sex" column="sex"/>
  12. <property name="job_title" column="job_title"/>
  13. </class>
  14. </hibernate-mapping>
    注意:这个配置文件的位置要与Teacher.java类在同一个文件夹下,并且并命必须是:[实体类名].hbm.xml。但这不是不必需的,这是Hibernate默认的规则,若要改变就要在hibernate.cfg.xml中加上额外的配置。
    对于Teacher.hbm.xml配置的说明:
  1. package="model":用于设置实体类的命名空间。
  2. name="Teacher" table="tb_teacher":设置实体类名与数据库表名的映射。
  3. <id name="id" column="id">:设置实体类的属性与数据库的主键的映射。
  4. <generator class="native"></generator>:设置主键的生成方式,如:自定义、序列、自增长等。native表示根据底层数据库对自动生成标识的能力自动选择。
  5. <property name="no" column="no"/>:设置实体类属性与数据库字段的映射关系。

5.编写测试代码(Holle World)

    编写测试代码必然会用到Hibernate API,这里我先看看测试代码和其运行的效果,再简单的分析一下Hibernate API的接口与其使用,代码如下(Test01.java):
  1. package test;
  2. import model.Teacher;
  3. import org.hibernate.Session;
  4. import org.hibernate.SessionFactory;
  5. import org.hibernate.cfg.Configuration;
  6. import org.hibernate.service.ServiceRegistry;
  7. import org.hibernate.service.ServiceRegistryBuilder;
  8. @SuppressWarnings("deprecation")
  9. public class Test01
  10. {
  11. public static void main(String[] args)
  12. {
  13. Configuration cfg = new Configuration();
  14. cfg.configure();
  15. ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
  16. SessionFactory sf = cfg.buildSessionFactory(sr);
  17. System.out.println("连接数据库");
  18. Session session = sf.openSession();
  19. Teacher teacher =(Teacher) session.get(Teacher.class, new Long(1));
  20. System.out.println(teacher);
  21. session.close();
  22. System.out.println("关闭数据库");
  23. System.exit(0);
  24. }
  25. }
    这段代码的作用是从数据库中找到ID==1的Teacher记录并打印在控制台,运行效果如下(省略了部分Hibernate日志):
  1. 连接数据库
  2. Hibernate:
  3. select
  4. teacher0_.id as id1_0_0_,
  5. teacher0_.no as no2_0_0_,
  6. teacher0_.name as name3_0_0_,
  7. teacher0_.sex as sex4_0_0_,
  8. teacher0_.job_title as job_titl5_0_0_
  9. from
  10. tb_teacher teacher0_
  11. where
  12. teacher0_.id=?
  13. tb_teacher [id=1, no=000001, name=教师1, sex=女, job_title=初级教师]
  14. 关闭数据库
    从打印结果中可以看出数据库中的记录“tb_teacher [id=1, no=000001, name=教师1, sex=女, job_title=初级教师]”,还可以看到Hibernate查询所用的SQL语句。

​6.Hibernate API接口简介

(1)Hibernate核心接口介绍
  1. Configuration接口:配置Hibernate,启动Hibernate,创建SessionFactory对象。
  2. SessionFactory接口:初始化Hibernate,充当数据源的代理,创建Session对象。
  3. Session接口:负责保存、更新、删除、加载和查询对象。
  4. Transaction接口:事务管理接口。
  5. Query和Criteria接口:用于执行数据库查询。
  6. Callback接口:Hibernate事件回调接口。
(2)Configuration接口
    Configuration接口的作用是对Hibernate进行配置,以及对它进行启动。在Hibernate的启动过程中,Configuration类实例首先定位映射文档的位置,读取这些配置,然后创建一个SessionFactory对象。
    Configuration对象的作用是除了有读取配置文件的功能,还能创建SessionFactory对象。通常,一个应用程序会创建一个Configuration对象,然后利用Configuration实例建立唯一的SessionFactory实例,这就意味着Configuration对象只存在于系统的 初始化阶段,然后所有的持久化操作都能通过这个唯一的SessionFactory实例来进行。
    Configuration对象只有在Hibernate 进行初始化的时候才需要创建,当使用Configuration对象的实例创建了SessionFactory对象的实例后,其配置信息已经绑定在他返回的SessionFactory对象实例中。因此,一般情况下,得到SessionFactory对象后,Configuration对象的使命就结束了。
    重要方法:
    public Configuration configure (*)
        在参数中指定要加载的配置文件
    public SessionFactory buildSessionFactory()
        根据配置文件实例化一个新的SessionFactory对象,这个SessionFactory将是不可变的,所以在创建了SessionFactory对象后,对Configuration对象作出的所有修改不会影响以前创建出的SessionFactory对象。
(3)SessionFactory接口
    这里用到了一个设计模式—工厂模式,用户程序从工厂类SessionFactory中取得Session的实例。SessionFactory不是轻量级的!它的设计者的意图是让它能在整个应用共享。典型地来说,一个项目通常只需要一个SessionFactory就够了,但是当你的项目要操作多个数据库时,那你必须为每个数据库指定一个SessionFactory。一个SessionFactory实例对应一个数据存储源,应用从SessionFactory中获得Session实例。它具有如下特点:
  1. 它是线程安全的,这意味着它的同一个实例可以被应用的各个线程共享。
  2. 它是重量级的,这意味着不能随意创建或销毁它的实例。
  3. 之所以说SessionFactory是重量级的,是因为它需要一个很大的缓存,用来存放预定义的SQL语句以及映射元数据等。用户还可以为SessionFactory配置一个缓存插件,这个缓存插件被称为Hibernate的第二级缓存,该缓存用来存放被工作单元读过的数据,将来其它工作单元可能会重用这些数据,因此这个缓存中的数据能够被所有工作单元共享,一个工作单元通常对应一个数据库事务。SessionFactory接口负责初始化Hibernate。
    重要方法:
    public Sessioin openSession()
        创建一个数据库连接,并把他放在Session对象中,并返回
    public Session openSession(Connection connection)
        创建一个Session对象,并把参数给出的 connection对象放在其中
    public boolean isClosed()
        判断当前SessionFactory对象是否关闭了
    public void close()
        关闭SessionFactory以及释放所有的SessionFactory涉及到的资源(缓存,数据库连接池等)但在调用此方法之前,应该确定没有当前对象创建的 Session没有关闭
(4)Session接口
    Session接口对于Hibernate 开发人员来说是一个最重要的接口。然而在Hibernate中,实例化的Session是一个轻量级的类,创建和销毁它都不会占用很多资源。这在实际项目中  确实很重要,因为在客户程序中,可能会不断地创建以及销毁Session对象,如果Session的开销太大,会给系统带来不良影响。Session具有一下特点:
  1. 不是线程安全的,因此在设计软件架构时,应该避免多个线程共享同一个Session实例。
  2. Session实例是轻量级的,所谓轻量级,是指它的创建和销毁不需要消耗太多的资源。这意味着在程序中可以经常创建和销毁Session对象,例如为每个客户请求分配单独的 Session实例,或者为每个工作单元分配单独的Session实例。
  3. Session有一个缓存,被称为Hibernate的第一级缓存,它存放被当前工作单元加载的对象。每个Session实例都有自己的缓存,这个Session实例的缓存只能被当前工作单元访问。Session接口负责执行被持久化对象的CRUD操作 (CRUD的任务是完成与数据库的交流,添加、更新、删除、加载和查询对象,包含了很多常见的SQL语句)。
    在Hibernate的设计者的头脑中,他们将session看作介于数据连接与事务管理一种中间接口。我们可以将session想象成一个持久对象的缓冲区,Hibernate能检测到这些持久对象的改变,并及时刷新数据库。我们有时也称Session是一个持久层管理器,因为它包含这一些持久层相关的操作,诸如存储持久对象至数据库,以及从数据库中获得它们。请注意,Hibernate 的session不同于JSP应用中的HttpSession。以后会将HttpSesion对象称为用户session。
    重要方法:
    public Transaction beginTransaction()
        在数据库中重新开始一个事务
    public Transaction getTransaction()
        返回和当前session联系的Transaction对象
    public Connection connection close()
        结束当前的Session对象
    public void clear()
        清空Session,清除所有保存在当前Session缓存中的实体对象,终止所有正在执行的方法(eg: save() , update() ,delete() .....)
    public Serializable save(Object object)
        对当前参数指定的对象进行持久化(系统会首先赋予参数对象一个标识符OID),他相当于insert语句 后面在详细介绍
    public Connection connection()
        得到当前Session 中包含的Connection对象。
    public boolean contains(Object object)
        判断参数给出的对象(持久化类)是否在当前Session的缓存中 
    public void evict(Object object)
        将参数给出的Object从当前Session对象类中删除,使这个对象从持久态变成游离态,这种状态的改变不会引起对数据库的同步
    public Object load(Class theclass ,Serializable id)
        返回第一个参数指定类对应的表中,第二个参数指定的行(第二个参数就是要取得对象的OID,他对应表中主键列的值)
    public void update(Object object)
        更新一个对象到数据库中
    public void delete (Object object)
        从数据库中删除和参数指定的对象对应的记录
    public Object get(Class class,Serializable id)
        和load()方法一样区别在于,如果数据库表中没有对应的记录,get()方法返回null,load()方法将报异常
(5)Transaction接口
    Transaction接口是一个可选的API,你可以选择不使用这个接口,取而代之的是Hibernate的设计者自己写的底层事务处理代码。它将应用代码从底层的事务实现中抽象出来——这可能是一个JDBC事务(Connection事务,基于数据库的事务),一个JTA事务(基于分布式的事务,同时管理多个数据库之间的事务)或者甚至是一个公共对象请求代理结构(CORBA)——允许应用通过一组一致的API控制事务边界。这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性。
    Transaction tx = session.beginTransaction();
    注意:使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认:autoCommit=false)。
    重要方法:
    public void commit()
        刷新当前的Session以及结束事务的工作,提交事务
    public void rollback()
        强迫回滚当前事务 
    public boolean isActive()
        这个事务是否存活
(6)Query和Criteria接口
    它们是Hibernate的查询接口,用于向数据库查询对象,以及控制执行查询的过程。query实例封装了一个HQL(Hibernate Query Language)查询语句,HQL是面向对象的,它引用类名及类的属性名,而不是表名及表的字段名。Criteria接口完全封装了基于字符串形式的查询语句,比Query接口更加面向对象,Criteria接口更擅长于执行动态查询。 Query接口让你方便地对数据库及持久对象进行查询,它可以有两种表达方式:HQL语言或本地数据库的SQL语句。Query经常被用来绑定查询参数、限制查询记录数量,并最终执行查询操作。
    Criteria接口与Query接口非常类似,它允许你创建并执行面向对象的标准化查询。
    值得注意的是Query接口也是轻量级的,它不能在Session之外使用。Session接口的find()方法也具有数据查询功能,但它只是执行一些简单的HQL查询语句的快捷方法,它的功能远没有Query接口强大。
(7)Callback接口
    当一些有用的事件发生时—例如持久对象的载入、存储、删除时,Callback接口会通知Hibernate去接收一个通知消息。一般而言,Callback接口在用户程序中并不是必须的,但要在项目中创建审计日志时,可能会用到它。
-------------------------------------------------------------------------------------------------------------------------------
上一篇:Redis_密码管理(转)


下一篇:Customize the SharePoint 2013 search experience with a Content Enrichment web service