1 JDBC的优缺点

  • 优点:

    • 直接底层操作,提供了简单、便捷的访问数据库的方法,跨平台比较强。
    • 灵活性比较强,可以写复杂的SQL。  
  • 缺点:
    • JDBC没有做到面向对象的编程,使得程序员的思考还停留在SQL之上。
    • 操作比较频繁,很多代码需要重复的写很多次。
    • 如果遇到批量操作,频繁的和数据库进行交互,容易造成效率的下降。  

2 Hibernate的优缺点

  • 优点:

    • 面向对象编程
    • 缓存
      • 一级缓存
      • 二级缓存
      • 查询缓存    
    • 代码操作比较简单
    • 平台的移植性比较强  
  • 缺点:
    • 如果该项目对SQL的优化要求比较高,不适合用Hibernate。
    • 如果数据库的数据量比较大,也不适合用Hibernate。
    • 如果表和表之间的关系比较复杂,也不能用Hibernate。  

3 Hibernate的使用场合

  • 表的关系不是很复杂
  • 数据量不是很大

4 Hibernate的入门案例

4.1 导入jar包

4.2 编写hibernate.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>
    <!--
        一个sessionFactory就代表一个数据库的描述
    -->
    <session-factory>
        <!-- 链接数据库的用户名 -->
        <property name="connection.username">root</property>
        <!-- 链接数据库的密码 -->
        <property name="connection.password">root</property>
        <!-- 链接数据库的驱动 -->
        <property name="connection.driver_class">
            com.mysql.jdbc.Driver
        </property>
        <!-- 链接数据库的url -->
        <property name="connection.url">
            jdbc:mysql://localhost:3306/hibernate
        </property>
        <!--
            方言
            告诉hibernate用什么样的数据库,将来会生成什么样的sql语句
        -->
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>
        <!--
            hibernate对表的策略
            validate  在hibernate容器启动的时候,根据映射文件和持久化类校验表
            create    每次当hibernate启动的时候,都会根据持久化类和映射文件创建表
            create-drop  每次当hibernate启动的时候,都会根据持久化类和映射文件创建表,销毁的时候删除表
            update  检查,如果和映射文件不一致,则更新表的结构,如果没有表,则会创建表
        -->
        <property name="hbm2ddl.auto">update</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

    </session-factory>
</hibernate-configuration>

4.3 编写持久化类和映射文件

  • Person.java
package com.xuweiwei.vo;

import java.io.Serializable;

/**
 * 实体类
 */
public class Person implements Serializable {
    private Long pid;
    private String name;
    private String sex;

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}
  • Person.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">
<hibernate-mapping >
    <!--
     class元素代表持久化类
        name属性为类的全名
        table属性为表的名字,默认值类名

     -->
    <class name="com.xuweiwei.vo.Person" table="person">
        <!--
            id为主键元素
                name 标识符属性
                column 对应表的字段
                type 类型
                length 数据库中pid的长度
        -->
        <id name="pid" column="pid">
            <!--
                主键生成策略
                    需要通过什么样的方式产生主键
            -->
            <generator class="native"/>
        </id>
        <!--
            property代表普通的属性
        -->
        <property name="name" column="name"/>
        <property name="sex" column="sex"/>
    </class>

</hibernate-mapping>
  • hibernate.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>
    <!--
        一个sessionFactory就代表一个数据库的描述
    -->
    <session-factory>
        <!-- 链接数据库的用户名 -->
        <property name="connection.username">root</property>
        <!-- 链接数据库的密码 -->
        <property name="connection.password">root</property>
        <!-- 链接数据库的驱动 -->
        <property name="connection.driver_class">
            com.mysql.jdbc.Driver
        </property>
        <!-- 链接数据库的url -->
        <property name="connection.url">
            jdbc:mysql://localhost:3306/hibernate
        </property>
        <!--
            方言
            告诉hibernate用什么样的数据库,将来会生成什么样的sql语句
        -->
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>
        <!--
            hibernate对表的策略
            validate  在hibernate容器启动的时候,根据映射文件和持久化类校验表
            create    每次当hibernate启动的时候,都会根据持久化类和映射文件创建表
            create-drop  每次当hibernate启动的时候,都会根据持久化类和映射文件创建表,销毁的时候删除表
            update  检查,如果和映射文件不一致,则更新表的结构,如果没有表,则会创建表
        -->
        <property name="hbm2ddl.auto">update</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

        <mapping resource="com/xuweiwei/vo/Person.hbm.xml"/>

    </session-factory>
</hibernate-configuration>

4.4 测试

  • 示例:
package com.xuweiwei.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class TestPerson {

    @Test
    public void testCreateTable(){
        //创建Configuration对象并加载hibernate.cfg.xml文件
        Configuration configuration = new Configuration().configure();
        //创建SessionFactory对象
        SessionFactory sessionFactory = configuration.buildSessionFactory();

    }

}
  • 如果你想看的仔细的话,可以在类路径下加入log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout

#log4j.logger.org.hibernate=info
log4j.logger.org.hibernate=debug

### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug

### log just the SQL
#log4j.logger.org.hibernate.SQL=debug

### log JDBC bind parameters ###
log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug

### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug

### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug

### log cache activity ###
#log4j.logger.org.hibernate.cache=debug

### log transaction activity
#log4j.logger.org.hibernate.transaction=debug

### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace

4.5 CRUD操作

  • 示例:增加
package com.xuweiwei.test;

import com.xuweiwei.vo.Person;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class TestPerson {

    @Test
    public void testCreateTable(){
        //创建Configuration对象并加载hibernate.cfg.xml文件
        Configuration configuration = new Configuration().configure();
        //创建SessionFactory对象
        SessionFactory sessionFactory = configuration.buildSessionFactory();
    }

    @Test
    public void testInsert(){
        //创建Configuration对象并加载hibernate.cfg.xml文件
        Configuration configuration = new Configuration().configure();
        //创建SessionFactory对象
        /**
         * 1.SessionFactory是单例的
         * 2.Hibernate的配置文件的信息、映射文件的信息、持久化类的信息全部在SessionFactory中
         * 3.sessionFactory封装的信息是公共的数据
         * 4.sessionFactory本身是线程安全的
         */
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        //创建session对象
        Session session = sessionFactory.openSession();
        //开启事务
        Transaction tx = session.beginTransaction();
        Person p = new Person();
        p.setName("丁希希");
        p.setSex("女");
        session.save(p);

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

        session.close();
        sessionFactory.close();

    }

}
  • 示例:根据指定的id查询对象
    @Test
    public void testQuery(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = (Person) session.get(Person.class,1L);
        System.out.print(p.getPid()+":"+p.getName()+":"+p.getSex());

        tx.commit();

        session.close();
        sessionFactory.close();
    }
  • 示例:查询所有的对象
    @Test
    public void testAllQuery(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Query query = session.createQuery("from Person");
        List<Person> list =  query.list();
        for(Person p :list){
            System.out.print(p.getPid()+":"+p.getName()+":"+p.getSex());
        }
        tx.commit();

        session.close();
        sessionFactory.close();
    }
    @Test
    public void testAllQuery(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        SQLQuery query = session.createSQLQuery("select * from person");
        query.addEntity(Person.class);

        List<Person> list =  query.list();
        for(Person p :list){
            System.out.print(p.getPid()+":"+p.getName()+":"+p.getSex());
        }
        tx.commit();

        session.close();
        sessionFactory.close();
    }
    @Test
    public void testAllQuery(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Criteria criteria = session.createCriteria(Person.class);
        List<Person > peoples = criteria.list();
        for(Person p :peoples){
            System.out.println(p.getPid()+":"+p.getName()+":"+p.getSex());
        }

        tx.commit();

        session.close();
        sessionFactory.close();
    }
  • 示例:更新
    @Test
    public void testUpdate(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = (Person) session.get(Person.class,1L);
        p.setName("丁希希是我公司的前端妹子");

        tx.commit();

        session.close();
        sessionFactory.close();
    }
  • 示例:删除
    @Test
    public void testDelete(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = (Person) session.get(Person.class,1L);
        session.delete(p);

        tx.commit();
        session.close();
        sessionFactory.close();
    }

4.6 主键生成策略(在*.hbm.xml中配置)

  • 封装Hibernate工具类:HibernateUtil.java
package com.xuweiwei.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * Hibernate工具类
 */
public class HibernateUtil {

    public static SessionFactory sessionFactory;
    static{
        Configuration configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
    }

    public static SessionFactory getSessionFactory(){
        return sessionFactory;
    }

}
  • increment
    /**
     * select max(pid) from person
     * insert into person(name, sex, pid) values (?, ?, ?)
     * 1.先查询表中主键的最大值
     * 2.把最大值+1作为新的主键     * 即便在程序中设置主键也不起作用,原因参考1和2
     *
     * 主键必须是数字类型
     */
    @Test
    public void testIncrement(){
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = new Person();
        p.setName("许威威");
        p.setSex("男");

        session.save(p);

        tx.commit();
        session.close();
        sessionFactory.close();
    }
  • assigned
    /**
     * 该策略必须通过程序设置
     */
    @Test
    public void testAssigned(){
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = new Person();
        p.setPid(1L);
        p.setName("许威威");
        p.setSex("男");

        session.save(p);

        tx.commit();
        session.close();
        sessionFactory.close();
    }
  • identity
    /**
     * 利用数据库的主键自动增长,数据库的类型必须支持自动增长才行
     */
    @Test
    public void testIdentity(){
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = new Person();
        p.setName("许威威");
        p.setSex("男");

        session.save(p);

        tx.commit();
        session.close();
        sessionFactory.close();
    }
  • native:会根据不同的数据库判断底层的主键生成策略
  • uuid:是由Hibernate内部产生的
     /**
     * uuid
     */
    @Test
    public void testUuid(){
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = new Person();
        p.setName("许威威");
        p.setSex("男");

        session.save(p);

        tx.commit();
        session.close();
        sessionFactory.close();
    }
  • sequence:Oracle中支持的自动增长机制

5 各个类或接口的作用

5.1 Configuration

  • 用来加载hibernate.cfg,xml文件。

5.2 SessionFactory

  • SessionFactory是单例的。
  • Hibernate的配置文件的信息、映射文件的信息、持久化类的信息全部在SessionFactory中。
  • SessionFactory封装的信息是公开的数据。
  • SessionFactory本身是线程安全的。

5.3 Session

  • CRUD操作都是由Session来完成的。
  • Session是一个接口,实现类是SessionImpl。
  • 在创建SessionImpl的时候,传递了一个参数为Connection,所以在Hibernate编程的时候,创建Session就相当于打开了一个连接。
  • 当关闭Session的时候,相当于关闭了一个连接。

5.4 Transaction

  • 事务是由Session来产生的
  • 事务默认是关闭的,必须手动开启

6 Hibernate的加载流程

7 对象的状态

7.1 三种对象的定义和区别

  • 【注意】如果一个对象的状态是持久态,那么数据库中不一定有对应的值。
  • 比如:
 session.save(p);
  • 这个时候的对象的状态是持久态,但是数据库中是没有对应的值。  
//提交事务
tx.commit();
  • 这个时候对象的状态是持久态,但是数据库中有对应的值。
  • 瞬时态对象和脱管态对象的区别:

    • 瞬时太对象是从new创建的。
    • 脱管态对象是从持久态转换过来的。  

7.2 对象的状态转换

7.3 对象状态的示例

  • 示例:
   @Test
    public void testInsert(){
        //创建Configuration对象并加载hibernate.cfg.xml文件
        Configuration configuration = new Configuration().configure();
        //创建SessionFactory对象
        /**
         * 1.SessionFactory是单例的
         * 2.Hibernate的配置文件的信息、映射文件的信息、持久化类的信息全部在SessionFactory中
         * 3.sessionFactory封装的信息是公共的数据
         * 4.sessionFactory本身是线程安全的
         */
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        //创建session对象
        Session session = sessionFactory.openSession();
        //开启事务
        Transaction tx = session.beginTransaction();
        Person p = new Person();//顺时态对象
        p.setName("许威威");//顺时态对象
        p.setSex("男");//顺时态对象
        session.save(p);//持久态对象

        //提交事务
        tx.commit();//持久态对象

        session.close();//脱管态对象
        sessionFactory.close();
    }
  • 示例:
    @Test
    public void testUpdate(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = (Person) session.get(Person.class,1L);//持久态对象
        p.setName("呵呵");//持久态对象
        //session.update(p); 将一个对象变为持久化状态,此时,p已经是持久态对象,所以可以不需要写update方法

        tx.commit();

        session.close();
        sessionFactory.close();
    }
  • 示例:
    @Test
    public void testUpdate(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = (Person) session.get(Person.class,1L);//持久态对象
        p.setName("呵呵");//持久态对象

        session.evict(p);//把持久态对象变为了脱管态对象,所以不会更新
        session.update(p);//把脱管态对象变为了持久态对象

        tx.commit();

        session.close();
        sessionFactory.close();
    }
  • 示例:
    @Test
    public void testUpdate(){
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction tx = session.beginTransaction();

        Person p = (Person) session.get(Person.class,1L);//持久态对象
        p.setName("呵呵");//持久态对象

        session.clear();//把person对象从hibernate中清空
        session.update(p);

        tx.commit();

        session.close();
        sessionFactory.close();
    }
  • 总结:

    • 可以通过session的save/update/get等方法把一个对象变为持久态对象。持久态对象仅仅说明了该对象进入了Hibernate的区域,和数据库一点点关系也没有,和数据库有关系的是事务。
    • 可以通过session的close/evict/clear等方法,将持久态对象变为脱管态对象。    

Hibernate (一)的更多相关文章

  1. hibernate多对多关联映射

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  2. 解决 Springboot Unable to build Hibernate SessionFactory @Column命名不起作用

    问题: Springboot启动报错: Caused by: org.springframework.beans.factory.BeanCreationException: Error creati ...

  3. hibernate多对一双向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  4. Hibernate中事务的隔离级别设置

    Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下

  5. Hibernate中事务声明

    Hibernate中JDBC事务声明,在Hibernate配置文件中加入如下代码,不做声明Hibernate默认就是JDBC事务. 一个JDBC 不能跨越多个数据库. Hibernate中JTA事务声 ...

  6. spring applicationContext.xml和hibernate.cfg.xml设置

    applicationContext.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans ...

  7. [原创]关于Hibernate中的级联操作以及懒加载

    Hibernate: 级联操作 一.简单的介绍 cascade和inverse (Employee – Department) Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似 ...

  8. hibernate的基本xml文件配置

    需要导入基本的包hibernate下的bin下的required和同bin下optional里的c3p0包下的所有jar文件,当然要导入mysql的驱动包了.下面需要注意的是hibernate的版本就 ...

  9. Maven搭建SpringMVC+Hibernate项目详解 【转】

    前言 今天复习一下SpringMVC+Hibernate的搭建,本来想着将Spring-Security权限控制框架也映入其中的,但是发现内容太多了,Spring-Security的就留在下一篇吧,这 ...

  10. 1.Hibernate简介

    1.框架简介: 定义:基于java语言开发的一套ORM框架: 优点:a.方便开发;           b.大大减少代码量;           c.性能稍高(不能与数据库高手相比,较一般数据库使用者 ...

随机推荐

  1. 【读书笔记】【深入理解ES6】#13-用模块封装代码

    什么是模块 模块是自动运行在严格模式下并且没有办法退出运行的 JavaScript 代码. 在模块顶部创建的变量不会自动被添加到全局变量作用域,这个变量仅在模块的顶级作用域中存在,而且模块必须导出一些 ...

  2. Java架构师学习路线

    Java架构师,首先要是一个高级java攻城狮,熟练使用各种框架,并知道它们实现的原理.jvm虚拟机原理.调优,懂得jvm能让你写出性能更好的代码;池技术,什么对象池,连接池,线程池--   Java ...

  3. 洛谷 P3370 【模板】字符串哈希

    洛谷 P3370 [模板]字符串哈希 题目描述 如题,给定N个字符串(第i个字符串长度为Mi,字符串内包含数字.大小写字母,大小写敏感),请求出N个字符串中共有多少个不同的字符串. 友情提醒:如果真的 ...

  4. hackerrank Ticket

    传送门 题意:n个人排队买票,要把他们拆成k条队到k个窗口买,可以有队伍为空,每条队的顺序保持拆之前的顺序.如果某人和他前一个人买的票相同,就可以打八折,求最小花费. 题解:拆成k条队意味着只有[n- ...

  5. Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】

    校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,K= ...

  6. a*b(mod m)的实现过程

    /*a*b (mod m) 的实现过程*/ /*当a,b很大的时候mod m就会产生溢出, 故运用乘法原理转换为加法求解*/ LL multi(LL a, LL b, LL m) { LL exp = ...

  7. zookeeper基本讲解及基本命令和配置 (转)

    一.ZooKeeper概述 ZooKeeper是一种为分布式应用所设计的高可用.高性能且一致的开源协调服务,是Google的Chubby一个开源实现,是Hadoop和Hbase的重要组件,它提供了一项 ...

  8. 用 Deployment 运行应用 - 每天5分钟玩转 Docker 容器技术(123)

    从本章开始,我们将通过实践深入学习 Kubernetes 的各种特性.作为容器编排引擎,最重要也是最基本的功能当然是运行容器化应用,这就是本章的内容. Deployment 前面我们已经了解到,Kub ...

  9. Spark算子--partitionBy

    转载请标明出处http://www.cnblogs.com/haozhengfei/p/923b11fce561e82748baa016bcfb8421.html partitionBy--Trans ...

  10. ThinkPHP模板IF标签用法详解

    投稿:shichen2014 字体:[增加 减小] 类型:转载 时间:2014-07-01 我要评论 这篇文章主要介绍了ThinkPHP模板IF标签用法,需要的朋友可以参考下 ThinkPHP的IF标 ...