一、Hibernate框架快速入门

Hibernate快速入门


一、Hibernate的介绍

Hibernate是轻量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架。

ORM:Object Relational Mapping,对象关系映射

优点:

  • Hibernate是基于jdbc的主流持久化框架。
  • Hibernate是一个开源的ORM框架,。
  • Hibernate对JDBC数据库的操作进行了封装,简化了数据库操作的代码,提高了开发效率。
  • 程序员能够利用Hibernate框架更好的使用面向对象的编程思维来操纵数据库。

二、 Hibernate使用入门

  1. 创建java项目
  2. 导入Hibernate所需jar包与数据库驱动连接
  3. 创建数据库表
  4. 创建javaBean实体类
  5. 编写数据库表与javaBean实体类的映射(配置)文件
  6. 编写Hibernate的核心配置文件
  7. 使用Hibernate

1. 导入jar包

  • 数据库驱动
  • Hibernate所需jar包
  • 日志记录jar包
需要导入的jar包
jar包解释

2. 创建数据库表

CREATE DATABASE hibernate_day01;
USE hibernate_day01;

CREATE TABLE USER(
    uid INT PRIMARY KEY AUTO_INCREMENT,
    uname VARCHAR(20),
    upassword VARCHAR(20)
);

3. 创建实体类(略)

4. 编写数据库表与javaBean实体类的映射(配置文件)

  1. 在javaBean的同级目录下创建文件名为 实体类名.hbm.xml的配置文件.如:User.hbm.xml

  2. 导入配置文件的DTD约束:mapping

  3. class标签定义javaBean与数据库表的映射

  4. id标签定义javaBean与数据库表中的主键的映射关系

  5. property标签定义普通字段的映射关系

     <?xml version="1.0" encoding="UTF-8"?>
     
     <!-- 引入DTD约束 -->
     <!-- 找到buildPath之后的Hibernate的Liberaries,打开hibernate的核心包:hibernate-core-5.0.7.Final.jar -->
     <!-- 打开和新包下的org.hibernate包,找到dtd结尾的映射配置文件mapping.dtd与hibernate的核心配置文件configuration.dtd -->
     <!-- 找到两个文件的dtd约束,copy到对应的xml配置文件中 -->
     
     <!DOCTYPE hibernate-mapping PUBLIC 
         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
         "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
     
     <hibernate-mapping>
         <!-- 创建javaBean实体类与数据库表的映射 -->
         <class name="com.itdream.domain.User" table="user">
             <!-- javaBean与表的主键的映射,相同时,column可省略 -->
             <id name="uid" column="uid"></id>
     
             <!-- 创建javaBean于表的普通字段的映射,相同时column可省略 -->
             <property name="uname" column="uname"></property>
             <property name="upassword" column="upassword"></property>
         </class>
     </hibernate-mapping>
    

5. 编写Hibernate的核心配置文件

  1. 在src目录下创建文件名为 ``hibernate.cfg.xml```的配置文件.
  2. 导入配置文件的DTD约束:configuration
  3. <hibernate-mapping></hibernate-mapping>标签中分为三部份:以property标签标记
    1. 必要的配置信息 : 连接数据库的基本参数

    2. Hibernate的属性

      2.1 : Hibernate的方言 : 根据配置生成对应的SQL语句,实现了跨数据域,切换数据库只需更改这里的配置即可

    3. Hibernate加载映射文件,<maping resource="相对路径" />

Hibernate核心配置文件的一些属性

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 引入DTD约束 -->
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    
    <!-- Hibernate核心配置 -->
    <hibernate-configuration>
        <session-factory>
            <!-- 1.必要的配置信息:连接数据库的基本参数 -->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_day01</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">root</property>

            <!-- 2. 与本地线程绑定 -->
            <property name="hibernate.current_session_context_class">thread</property>
            
            <!-- 3. Hibernate的属性 -->
            <!-- Hibernate的方言:根据配置的方言生成对应的SQL语句.实现了跨数据库 .切换数据库时只需要更改此处的配置即可-->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
            
            <!-- Hibernate显示SQL语句 -->
            <property name="hibernate.show_sql">true</property>
            <!-- Hibernate格式化SQL语句 -->
            <property name="hibernate.format_sql">true</property>
            
            <!-- Hibernate的hbm2ddl,定义hibernate对数据库表格的创建方式,开发一般用none -->
            <!-- 取值:none,create,create-drop,update,validate -->
            <property name="hibernate.hbm2ddl.auto">none</property>
            
            <!-- 4. Hibernate加载映射 -->
            <mapping resource="com/itdream/domain/User.hbm.xml"/>       
        </session-factory>
    </hibernate-configuration>

6. 使用Hibernate完成用户User的注册

  1. 创建Hibernate的配置对象Configuration
  2. 通过配置对象,获取SessionFactory工厂对象
  3. 通过工厂对象获取Session对象
  4. 开启事务
  5. 实现自己的业务逻辑
  6. 提交事务
  7. 关闭资源

代码实现:


    @Test
        //Hibernate入门案例,存储用户到MySQL数据库
        public void test01() {
            //1. 创建Hibernate配置对象
            Configuration configuration = new Configuration();
            //默认加载放在src下以hibernate.cfg.xml命名的Hibernate核心配置文件
            //1.1 加载配置文件
            configuration.configure();
            //2. 通过配置对象创建SessionFactory对象
            SessionFactory sessionFactory = configuration.buildSessionFactory();
            //3. 通过工厂对象获取Session对象
            Session session = sessionFactory.openSession();
            //4. 开启事务
            Transaction transaction = session.beginTransaction();
            //5. 实现自己的业务逻辑
            
            User user = new User();
            user.setUname("唐嫣");
            user.setUpassword("123");
            //实现了insert into user values(null,'唐嫣','123')的操作
            session.save(user);
            
            //6. 提交事务
            transaction.commit();
            //7. 释放资源
            session.close();
            sessionFactory.close();
        }

三、Hibernate配置文件如何导入DTD约束

  1. 导入Hibernate的jar包后build path会产生对应的liberary
  2. 在liberary中找到Hibernate的核心jarhibernate-core-5.0.7.Final.jar
  3. 找到核心jar中的org.hibernate包,点击打开这个包
  4. 分别找到hibernate-mapping-3.0.dtdhibernate-configuration-3.0.dtd的dtd约束
  5. copy两个dtd文件中的约束

    hibernate-mapping-3.0.dtd:

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


    hibernate-configuration-3.0.dtd:

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

6.点开eclipse的window的prference的属性,设置约束的编写提示。
7.找到xml catalog的窗口,点击add

导入DTD编写提示一

8.将约束中双引内的http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd 或(mapping) 填入key的输入框,key type选URI,Location选择FileSystem找到对应的DTD文件导入即可.

导入DTD编写提示二

四、 Hibernate的相关API

1. Configuration对象

  1. 用于配置并且启动Hibernate框架。

  2. Hibernate框架通过该对象来获得对象-关系映射文件中的元数据,以及动态配置Hibernate的属性。

  3. 可以创建SessionFactory对象。

    //获取Configuration对象
    Configuration conf = new Configuration();

    //加载配置文件: 以默认方式加载,配置文件必须放在src目录下,并以hibernate.cfg.xml命名
    conf.configure();//推荐:

    conf.configure(String path);//不推荐

  4. 如果hibernate.cfg.xml中没有使用mapping标签加载映射文件,可以使用该配置对象加载。

    configuration.addResource(String path);
    不推荐该方式,推荐在核心配置文件中直接配置映射文件的加载路径。

2. SessionFactory : Session工厂对象

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

SessionFactory的实例通过Configuration获取:

SessionFactory factory = configuration.buildSessionFactory();

Session具有以下特点:

1. 它是线程安全的,他的同一个实例可以被多个线程共享。
2. 它是重量级的,因此不能随意的销毁和创建。

由于这个特点,因此一个项目中只需要一个SessionFactory对象,因此对其抽取一个工具类,使其只创建一次,并且能够提供Session对象。

    
    /**
     * 1. 完成SessionFactory的初始化
     * 2. 提供Session对象的获取
     */
    public class HibernateUtils {
        
        //声明SessionFactory对象,将其实例化放在static静态代码块中,保证其在一开始就完成初始化
        private static SessionFactory sf = null;
        
        static {
            //1. 创建Hibernate配置对象
            Configuration configuration = new Configuration();
            //2. 加载配置文件:hibernate.cfg.xml,默认加载src目录下的hibernate.cfg.xml
            configuration.configure();
            
            //3. 实例化SessionFactory对象
            sf = configuration.buildSessionFactory();
            
            //4. 关闭虚拟机时,释放SessionFactory
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                
                @Override
                public void run() {
                    System.out.println("虚拟机关闭,释放SessionFactory资源");
                    sf.close();
                }
            }));
        }
        
        
        //提供获取Session对象的方法
        public static Session openSession() {
            return sf.openSession();
        }
        
        
        //获得当前线程中的绑定的Session
        //注意:必须配置
        //return 
        public static Session getCurrentSession() {
            return sf.getCurrentSession();
        }
    }

3. Session对象

Session是应用程序与数据库之间交互操作的一个单线程对象,它的主要功能是为持久化对象提供增,删,改,查的操作。

通过SessionFactory对象获得Session对象,获取Session实例有两种方式:

1. 采用openSession方式:

Session session = sessionFactory.openSession();


2. 采用getCurrentSession方式:

Session session = sessionFactory.getCurrentSession();

他们的区别:

1. openSession获取的Session对象,SessionFactory会直接创建一个Session实例,在使用完成后需要调用close方法手动关闭。
2. getCurrentSession方法获取的Session对象实例会被绑定到当前线程中,它在事务提交或回滚后会自动删除。

Session是线程不安全的,多个并发线程同时操作一个Session对象会导致Session数据存取的混乱,(方法内部定义与使用Session对象时,不会出现线程问题),因此应该避免成员位置定义Session,而在局部位置定义Session对象实例,从而避免线程问题。

Session对象的几个API方法:

  • save(obj) : 增
  • get/load(obj,id) : 取
  • delete(obj) : 删,两种方式,直接删,先获取再删除.推荐先获取在删除。
  • update(obj) : 改,两种方式,直接修改,先获取再修改.推荐先获取再修改.防止数据丢失
  • createQuery("hql") : 获得Query对象
  • createCriteria(Class) : 获得Criteria对象

测试:


    public class HibernateTest2 {
    
        @Test
        //使用Hibernate向数据库中保存数据
        public void save() {
            //1.创建Hibernate配置对象
            //2.创建SessionFactory对象
            //3.获取Session对象
            Session session = HibernateUtils.openSession();
            //4.开启事务
            Transaction transaction = session.beginTransaction();
            //5.实现业务逻辑
            User user = new User();
            user.setUname("林志玲");
            user.setUpassword("123");
            session.save(user);
            
            //6.提交事务
            transaction.commit();
            //7.关闭资源
            session.close();
        }
        
        
        @Test
        //根据主键获取user对象
        public void get() {
            //1. 获取Hibernate配置对象
            //2. 通过配置对象获取SessionFactory工厂对象
            //3. 获取Session对象
            Session session = HibernateUtils.openSession();
            //4. 开启事务
            Transaction transaction = session.beginTransaction();
            //5. 实现业务逻辑
            //参数1:javaBean的实体类 ; 参数2: 序列化,根据表的主键查找对应的javaBean对象
            User user = session.get(User.class, 1);
            System.out.println(user);
            //6. 提交事务
            transaction.commit();
            //7. 释放资源
            session.close();
        }
        
        
        @Test
        //根据主键获取user对象
        public void load() {
            //1. 创建配置对象
            //2. 通过配置对象获取SessionFactory工厂对象
            //3. 获取Session对象
            Session session = HibernateUtils.openSession();
            //4. 开启事务
            Transaction transaction = session.beginTransaction();
            //5. 实现业务逻辑
            //与get用法一致
            User user = session.load(User.class, 2);
            System.out.println(user);
            //6. 提交事务
            transaction.commit();
            //7. 关闭资源
            session.close();
        }
        
        
        //根据主键更改user对象的值
        @Test
        public void update() {
            //1.获取Hibernate配置对象
            //2.通过配置对象获取SessionFactory工厂对象
            //3.获取Session对象
            Session session = HibernateUtils.openSession();
            //4.开启事务
            Transaction transaction = session.beginTransaction();
            //5.实现业务逻辑
            //首先通过主键获取到对象,然后在对对象进行修改,这样在更改对象的值的时候就不会发生丢失
            User user = session.get(User.class, 1);
            user.setUpassword("999");
            session.update(user);
            //6.提交事务
            transaction.commit();
            //7.释放资源
            session.close();
        }
        
        @Test
        //根据主键删除对应user对象
        public void delete() {
            //1. 获取Hibernate配置对象
            //2. 通过配置对象获取SessionFactory工厂对象
            //3. 获取Session对象
            Session session = HibernateUtils.openSession();
            //4. 开启事务
            Transaction transaction = session.beginTransaction();
            //5. 实现业务逻辑
            //首先获取到这个要删除的对象然后删除
            User user = session.get(User.class, 2);
            session.delete(user);
            //6. 提交事务
            transaction.commit();
            //7. 关闭资源
            session.close();
        }
    }

get与load的区别:

get方法 : 立即加载策略:执行get,立即发送SQL语句


load方法 : 延迟加载(懒加载):执行load,不会发送sql语句;只要在真正使用数据的时候,才会发送sql语句。

4. Transction

负责事务管理

  • 常用API :

    • beginTransction() : 开启事务
    • commit() : 提交事务
    • roolback() : 回滚事务
  • 特点

    • Hibernate框架默认情况下事务不自动提交,需要手动提交事务
    • 如果没有开启事务,每一个Session操作,都相当于一个独立的事务
    • 每段事务隐藏着异常,需要手动添加try/catch

五、Hibernate整合C3P0实现连接池

hibernate中可以使用默认的连接池,无论功能与性能都不如C3PO。

步骤:

  1. 找到Hibernate中的c3p0的jar包添加到项目中
  2. 修改hibernate.cfg.xml的配置文件,添加属性,Hibernate会自动发现所配置的信息,选择c3p0作为连接池。

     <!-- C3P0的供应商 -->
     <property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
     <!-- 最小连接 -->
     <property name="hibernate.c3p0.min_size">5</property>
     <!-- 最大连接数 -->
     <property name="hibernate.c3p0.max_size">20</property>
     <!-- 连接超时时长 -->
     <property name="hibernate.c3p0.timeout">120</property>
     <!-- 每120秒检查空闲连接 -->
     <property name="hibernate.c3p0.idle_test_period">120</property>
     <!-- 最大statments数量 -->
     <property name="hibernate.c3p0.max_statements">120</property>  
     <!-- 连接用完后,每次增加的连接数 -->
     <property name="hibernate.c3p0.acquire_increment">2</property> 
     <!-- 每次都验证连接是否可用 -->
     <property name="hibernate.c3p0.validate">false</property>

3.查看连接池是否起作用

方法1:

修改log4j的log4j.properties,修改log4j.rootLogger=Info,这样降低记录与显示日志的级别.
运行程序时如果能看到控制台出现[org.hibernate.connection.C3P0ConnectionProvider]说明
Hibernate已经选择了C3P0作为连接池
方法1

方法2:

在mysql中使用命令show processlist查看连接数,如连接池中配置最小5个连接时将显示:
方法2

六、 日志集成

  • JCL规范。Java Commen logger
  • SLF4J规范。Simple Logger fade for Java。
  • log4j:实现。

规范的出现是因为在一个程序中多个框架用到了不同的日志系统,日志杂乱。规范提供统一解决方案。
规范和实现的整合,需要中间整合桥梁。

Log4j与slf4j集成步骤:

  • 导入jar包

    • slf4j-api-x.x.x.jar : 规范接口jar
    • slf4j-log4j12-x.x.x.jar : log4j与Slf4j整合的jar
    • log4j-x.x.x.jar : log4j实现日志规范的jar
  • 在src目录下编写log4j.properties配置文件

      ##设置日志记录到控制台的方式
      log4j.appender.stdout=org.apache.log4j.ConsoleAppender
      log4j.appender.stdout.Target=System.err
      log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
      log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
      ##设置日志记录到文件的方式
      log4j.appender.file=org.apache.log4j.FileAppender
      log4j.appender.file.File=c\:mylog.log
      log4j.appender.file.layout=org.apache.log4j.PatternLayout
      log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
      ##日志输出的级别,以及配置记录方案
      log4j.rootLogger=info, stdout, file 
    
  • 代码中调用Log4j

    • 初始化(引入的包为slf4j的,使用规范接口编程)

        Logger logger = LoggerFactory.getLogger(Clazz);
      
    • 调用

        logger.trace();
        logger.debug();
        logger.info();
        logger.warn();
        logger.error();
      

日志级别:

trance
debug
info
warn
error
fatal

Log4j日志配置规则介绍【参考log4j介绍】:

日志记录器:rootLogger
日志输出源:appender
日志布局器:layout

真实使用导入jar包,配好log4j.properties就可以使用c3p0连接池了.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容