Hibernate①单表案例入门Hibernate

更多Hibernate在框架开发


1.关于Hibernate

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

说的通俗点,传统的JDBC需要在数据库中创建数据库,创建表,使用Java代码中的Connection对象连接数据库,编写SQL语句实现增删改查,虽然有DBUtils工具帮我们处理事务,各种代码简化,但表字段非常多的时候,给参数赋值非常繁琐。而Hibernate利用实体类与表字段建立的配置文件帮我们自动创建表,并且在进行增删改查的时候不需要写SQL语句了,与SpringMVC等框架结合后,真正实现了一行代码搞定一个功能。所以这个框架大大简化了编码的复杂度,已经成为了一个共同协作的持久层框架之一。

2.一个单表小项目入门Hibernate

2.1 项目介绍

用户管理系统:

  • MySQL数据库8.0版本: 项目数据库user01,用户单表tb_user 、用户表字段userid(int型,自增长)、username、userage
  • 持久层操作: 对单表 添加用户、修改用户属性、删除用户、根据id查询用户。
  • 额外技术: c3p0数据库连接池

2.2 项目编写之前的配置

Hibernate官网ORM模型Releases栏中下载Hibernate资源包(本文:hibernate-release-5.0.12.Final)。

导入jar包:

  • 必须jar包:hibernate-release-5.0.12.Final/lib/required/文件夹下的所有jar包是hibernate的必须jar包
  • 数据库jar包:mysql-connector-java-8.0.11.jar
  • 日志相关jar包 : log4j-1.2.16.jar slf4j-api-1.6.1.jar slf4j-log4j12-1.7.2.jar

在数据库中创建数据库user

mysql> create databases user;

2.3 编写实体类

实体类(也叫持久化类)就是JavaBean,编写的实体类属性最好与数据库表字段一样,实体类编写是有规范的:

  • 提供无参数构造方法
  • 属性私有化,提供get和set方法
  • 尽量使用包装类的类型。int-Integer,char-Character,其余首字母大写。
  • 属性中要有唯一标识与数据库中表的主键对应
  • 尽量不用final修饰
public class User import Serializable; {
    private Integer userid ;
    private String username ;
    private Integer userage ;
    // setter和getter方法
}

2.4 编写映射配置文件

作用是让实体类属性与表字段名称建立联系。映射配置文件的名字和位置不是固定的,但建议以实体类名.hbm.xml命名,并且放在实体类所在包下。

User.hbm.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!--引入dtd的XML约束-->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.kmust.entity">
<!-- 
         class:
            name:用户实体类
            table: 用户表名称
            catalog:数据库名(可省略)
         id: 主键设置
            name : 实体类中与主键相对应的属性
            column: 表主键名称
         generator: 主键增长方式
            class :主键增长方式
         property: 其余属性设置
            name: 实体类属性
            column: 表中字段名,(省略表示字段名与实体类属性名一致)              
-->
     <!-- 第一部分:建立类和表的映射关系 -->
     <class name="User" table="tb_user">
          <!-- 第二部分:建立实体类属性与主键的映射关系 -->
          <id name="userid" column="userid">
               <generator class="native"/>
          </id>
          <!-- 第三部分:建立实体类其余属性与表字段的映射关系 -->
          <property name="username" />
          <property name="userage" /> 
     </class>
</hibernate-mapping>

XML约束 : 在hibernate-core-5.2.17.Final.jar包下的org.hibernate下的hibernate-mapping-3.0.dtd里面有这段dtd的XML约束代码。
主键生成策略:(最常用两种)

  • native : 设置主键(int)的生成策略为 自动增长,能够根据所用数据库自动判断增长方式(mysql是identity ,oracle是sequence)。
  • uuid : 设置主键(String)的生成策略为 采用128位的UUID算法生成的唯一标识。

如果实体类属性与表字段名称一致,则可以省略column属性。
<hibernate-mapping>标签中如果没有package属性,则实体类应该写完整的cn.kmust.entity.User

2.5 编写核心配置文件

作用是配置连接数据库的参数以及其他运行参数。核心配置文件的名字和位置也不是必须固定的,但最好以hibernate.cfg.xml命名,并且放在src下,如果位置不是放在src下,则必须在代码中加载其路径。

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入dtd的XML约束 -->
<!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>
      <!-- 第一部分:配置连接数据库的基本参数 -->
      <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
      <property name="hibernate.connection.url">jdbc:mysql:///user01?useSSL=false</property>
      <property name="hibernate.connection.username">root</property>
      <property name="hibernate.connection.password">root</property>
      <!--配置方言 -->
      <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
      <!-- 第二部分:配置Hibernate的一些可选属性参数 -->
      <!-- 显示sql语句 -->
      <property name="hibernate.show_sql">true</property>
      <!-- 格式化显示sql语句 -->
      <property name="hibernate.format_sql">true</property> 
      <!--在SessionFactory创建时自动更新表结构,没有创建,不一样就修改  -->
      <property name="hibernate.hbm2ddl.auto">update</property>
      <!-- 第三部分:加载映射配置 -->
      <mapping resource="cn/kmust/entity/User.hbm.xml"/>
   </session-factory>
</hibernate-configuration>

XML约束 : 在hibernate-core-5.2.17.Final.jar/org/hibernate/hibernate-configuration-3.0.dtd里面有这段dtd的XML约束代码。

第一部分:数据库信息

  • Platforms 下的各种数据库。

第二部分 :可选的配置

  • Miscellaneous Settings(其他设置)下的各种配置。
  • Plugin ConnectionProvider下的各种连接池。
  • ……………………………..

提示 :

(1) 第一部分和第二部分的所有配置参数可在hibernate-release-5.2.17.Final/project/etc/hibernate.properites文 件下查看

(2)hibernate.properites文件中各参数配置可以网络搜索查看其具体用途,这儿不做累述。

第三部分 :程序运行只会加载核心配置文件,所以需要在核心配置文件中加载映射配置文件。

2.6 配置c3p0数据库连接池

导入c3p0数据库连接池相关的jar包(hibernate-release-5.0.17.Final/lib/optional/c3p0/)

在核心配置文件中的第二部分加入c3p0的配置

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

2.7 编写HibernateUtils工具类

以下涉及的对象可以在附录1中进行查看

在创建SessionFactory对象过程中就已经在更新表了,每次创建每次更新表,这导致资源消耗,所以,一般情况下,一个项目(一个数据库)只有一个SessionFactory实例,也就是SessionFactory实例第一次创建后,就不再关闭,让其为整个项目一直服务下去,所以,一般考虑抽取一个HibernateUtils工具类,把SessionFactory实例的创建放在静态代码块中,防止多次创建,降低了资源消耗。并且该类用静态方法返回Session对象,方便直接类名调用。

(1)静态代码块:静态代码块在类第一次加载时自动执行,并且只执行这一次,以后除非是创建该类对象,否则再次加载时也不会执行,常常用作初始化操作。

(2)静态方法: 静态方法在类加载的时候就已经加载,所以不需要用类的实例进行调用,而是可以用类名直接调用

所以应该注意的是:在一个项目中,SessionFactory在类加载时创建后就不能关闭了,如果一旦关闭,则再也不能开启。

public class HibernateUtils {
    private static final SessionFactory sessionFactory ;
    static {
        try {
            Configuration cfg = new Configuration().configure() ;
            sessionFactory = cfg.buildSessionFactory();
        } catch (ExceptionInInitializerError e) {
            throw new ExceptionInInitializerError("初始化SessionFactory失败!") ;
        }
    }
    /**
     * 获取一个新的Session对象
     * @return
     */
    public static Session openSession() {
        return sessionFactory.openSession();
    }
}

2.8 编写Dao+测试(添加、删除、修改)

以下涉及的对象请查看附录1

以下给出测试框架,包含了事务的操作。其中,SessionFactory对象不能关闭,但是Session对象必须关闭。

public void add() {
        //类名直接调用静态方法获取Session对象
        Session session = HibernateUtils.openSession();
        Transaction tx = null ;
        try {
            tx = session.beginTransaction();
            //增删改查 操作
            tx.commit();
        } catch (Exception e) {
            if (tx!=null) tx.rollback();
            throw e;
        }finally {
            session.close();
        }
    }

单表部分增删改查测试:

//增
session.saveOrUpdate(user);
//根据id查询
User user = session.get(User.class,1) ;
//修改年龄
User user = session.get(User.class,1) ;
user.setUserage(17);
session.saveOrUpdate(user);
//删除
User user = session.get(User.class,3) ;
session.delete(user);

3 注意MySQL版本与JDBC参数

重点提示(1):

在核心映射配置文件中,一些参数可能并不是hibernate.properites文件中给出的参数。尤其是第一部分的数据库参数,这与数据库的版本有很大关联。关于mysql最新版本8.x的JDBC连接请参考官网MySQL Connector/J 8.0 Developer Guide

例如:本人使用的是mysql8.0版本,这个版本要求 驱动参数里面加 了一个cj ,并且有SSL认证(url参数后多了一个userSSL的字段),5.7版本后,方言参数变为org.hibernate.dialect.MySQL5InnoDBDialect

如果写错了这些参数可能会导致一些列的问题,比如连接不上数据库,方言参数写错会导致虽然有Sql语句输出,但数据库中并没有建表成功等等问题。

重点提示(2)

mysql的驱动jar也有版本的问题,请根据mysql版本下载相应的驱动。MySQL官网驱动下载地址


4 参考


附录1:Hibernate API重点对象

Hibernate5.0.12版本API参考(https://docs.jboss.org/hibernate/stable/orm/javadocs/)

Configuration对象 (org.hibernate.cfg.Configuration)是hibernate启动后的第一个对象,用来启动、加载、管理配置文件,并且创建SessionFactory对象实例。

SessionFactory接口(org.hibernate.SessionFactory)是用来初始化hibernate和创建Session对象。

Session接口(org.hibernate.Session)是负责执行创建Transaction对象和执行CRUD操作,是非线程安全的,多个线程并发操作一个Session实例时,会导致数据存取混乱。

Transaction接口(org.hibernate.Transaction)用于事务管理,通过session对象开启。

猜你喜欢

转载自blog.csdn.net/g425680992/article/details/80290987