Cheug's Blog

当前位置:网站首页 / JAVA / 正文

Hibernate[一]

2019-10-17 / JAVA / 1011 次围观 / 0 次吐槽 /

1hibernate简介

1.1、项目中框架的体系结构

image.png

1.2ORM框架

n  对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping

n  对象和表字段进行对应

n  是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。

n  Object:对象,java对象,此处特指JavaBeanModel

n  Relational:关系,二维表,数据库中的表。

n  Mapping:映射

1.3、什么是hibernate

n  Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装

n  DBUtils也是对JDBC的封装

n  它将POJO与数据库表建立映射关系,是一个全自动的orm框架

n  POJOPlain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans

n  hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库

n  Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSPWeb应用中使用

 

1.4、总结Hibernate

n  Hibernate是一个数据持久化层的ORM框架,它的主要功能就是把对象映射到表中,操作API,只需要将一个对象存储到数据库,不需要写sql语句

n  Hibernate提供了对关系型数据库增删改成操作

image.png

1.5主流的ORM框架

n  JPA Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系(只有接口规范)

n  Hibernate 最流行ORM框架,通过对象-关系映射配置,可以完全脱离底层SQL

n  MyBatis  本是apache的一个开源项目 iBatis,支持普通 SQL查询,存储过程和高级映射的优秀持久层框架

n  Apache DBUtils Spring JDBCTemplate

 

1.6Hibernate的优点

v  HibernateJDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码

v  Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作  session.save(User);

v  Hibernate使用java的反射机制

v  Hibernate性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,有一对一到多对多的各种复杂关系映射

2、hibernate的简单使用

hibernate的使用步骤

A.下载hibernate jar包,并导入到项目中(http://hibernate.org/orm/)

B.创建数据库和表

C.配置核心配置文件hibernate.cfg.xml【这个文件有连接数据库的配置】

D.编写映射文件hibernate mapping(*.hbm.xml),【声明对象如何关联数据库表字段】

E.调用hibernateapi

导入jar

v  这里我们使用3.6.0的版本开发,4.0开发是建议使用注解

v  所需要导入的jar,如下图,然后再导入一个mysql数据库连接驱动

image.pngimage.pngimage.png

image.png

hibernate的核心配置文件

²  hibernate.cfg.xml放入src

<!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>
         <!-- 1、配置数据库连接的4个参数 -->
         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
         <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/DB</property>
         <property name="hibernate.connection.username">root</property>
         <property name="hibernate.connection.password">123456</property>
         
         <!--  是否显示sql语句 -->
         <property name="show_sql">true</property>
         <!--  是否格式化sql语句 -->
         <property name="format_sql">true</property>
<!--  是否自动提交事务 -->
         <property name="hibernate.connection.autocommit">true</property>
         
         <!-- 2、配置JavaBean与表的映射文件 -->
         <mapping resource="com/cheug/hibernate/domain/User.hbm.xml"/>
     </session-factory>
</hibernate-configuration>

编写JavaBean和映射文件.hbm.xml

JavaBean.hbm.xml文件包属的包和文件名要一致

User.java 提供get/set方法

image.png

<!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="com.cheug.hibernate.domain.User" table="t_user">
         <!-- 1、主键,如果属性与表字段不一至,要指定column -->
         <id name="uid" column="id">
              <!-- 主键生成策略  -->
              <generator class="native"></generator>
         </id>
         <!-- 2、用户字段 -->
         <property name="username"></property>
         <property name="password"></property>
     </class>
</hibernate-mapping>

使用

public class Demo01 {
     @Test
     public void test1(){
         //1.获取核心 配置文件对象,默认是加载src的hibernate.cfg.xm文件
         Configuration cfg = new Configuration().configure();
         
         //2.创建会话工厂
         SessionFactory factory = cfg.buildSessionFactory();
         
         //3.创建会话
         Session session = factory.openSession();
         //开启事务
         Transaction trans = session.beginTransaction();
         
         //保存
         User user = new User();
         user.setUsername("cheug");
         user.setPassword("123");
         session.save(user);
         
         //提交事务
         trans.commit();
         //4.关闭会话
         session.close();
         //5.关闭工厂,释放资源
         factory.close();
     }
}


常见问题

v  下面未知的实体是指在hibernate.cfg.xml中没有配置映射文件

image.png

3、API详解

3.1Configuration 配置对象

² Hibernate的核心配置文件的多种形式

u  hibernate.cfg.xml 通常使用xml配置文件,可以配置内容更丰富。

                hibernate.properties 用于配置key/value 形式的内容,key不能重复的。配置有很多的局限性。一般不用。【可以进入hibernate-distribution-3.6.10.Final\project\etc目录看内容】

² Configuration 对象

²  Configuration对象就是用来加载配置文件

²  new Configuration构造方法配置加载的是hibernate.properties

²  configre()方法加载的是hibernate.cfg.xml

       默认情况下,上面两种配置文件都需要放在src目录下

image.png

configure(String resource)这个方法可以指定配置文件路径

² 加载映射文件方式

n  一种是在hibernate.cfg.xml配置,另一种是代码设置

image.png

image.png

² 常见异常

n  重复了映射文件

image.png

注意:开发中:将hbm.xml映射 配置 hibernate.cfg.xml

3.2SessionFactory 工厂

image.png

²  SessionFactory 相当于java web连接池,用于管理所有session

²  获得SessionFactory 方式:config.buildSessionFactory();

²  sessionFactory 还用于缓存配置信息 (数据库配置信息、映射文件,预定义HQL语句 等)

²  SessionFactory线程安全多个线程同时访问时,不会出现线程并发访问问题

3.3Session 会话

session会话的获取

²  sessionFactory提供了两个方法来获取session

1.         factory.openSession() 获取一个全新的session

2.         factory.getCurrentSession() 获取一个与当前线程绑定的session

a.要使用这个方法必须在hibernate.cfg.xml中配置

<property name="hibernate.current_session_context_class">thread</property>

b.hibernate支持,将创建的session绑定到本地线程中,底层使用ThreadLocal,在程序之间共享session。

c.如果提交或者回滚事务,底层将自动关闭session

image.png

3.4Transaction事务

²  掌握Hibernate中怎么获取事务,开启、提交、回滚事务

image.png

try{

   //开启

   //session操作

   //提交

} catch(e){

   //回滚

}

扩展:不需要手动的管理事务,之后所有的事务管理都交予spring

v  事务也可以在hibernate.cfg.xml配置文件中设置

<!--  是否自动提交事务 -->

<property name="hibernate.connection.autocommit">true</property>

3.5sessionapi(方法)

n   save 保存

n   get 通过id查询,如果没有 null

n   load 通过id查询,如果没有抛异常

n   update 更新

   n  delete 删除

@Test
    public void test4(){
        Configuration cfg = new Configuration().configure();
        SessionFactory sf = cfg.buildSessionFactory();
        Session session = sf.openSession();
        //1.save保存,插入数据,需要提交事务
        //User u1 = new User("abc","123");
        //session.save(u1);
        
        //2.get查询,根据id查询,hibernate会根据类名查表,如果没查找,返回null值
        User u2 = (User) session.get(User.class, 15);
        System.out.println(u2);
        
        //3.load查询,如果没有查到,会抛出ObjectNotFoundException异常
        User u3 = (User) session.load(User.class, 22);
        System.out.println(u3);
        
        session.close();
        sf.close();
    }

image.png

image.png

3.6getload方法的区别

 

v  get方法是直接加载数据库

v  load的设计是懒加载,用到时才去查询数据库

v  load方法返回的是对象的一个代理

image.png

v  load执行原理图

image.png

3.7Query 查询对象

HQL:Hibernate Query Language的缩写,就是Hibernate的查询语言

面向对象查询语言,最终底层要转成面向数据库查询语言

SQL:直接面向数据库查询语言

 

Query:用于查询的对象,可以设置查询条件和分页查询

image.png

image.png

3.8Criteria

v  QBCquery by criteria),hibernate提供纯面向对象查询语言,提供直接使用PO对象进行操作。

image.png

概念:

        POpersistent object ,用于与数据库交互数据。--dao  JavaBean + hbm

        BOBusiness object 业务数据对象。--service

        VOValue Object 值对象。--web

3.9SQLQuery

²  SQLQuery:使用原生的SQL语句查询

²  并不是所有sql都能转成hql

image.png

3.10工具类

public class HibernateUtils {
    private static SessionFactory sf;
    
    static{
        //1.加载配置
        Configuration cfg = new Configuration().configure();
        
        //2.创建一个sessionFactory
        sf = cfg.buildSessionFactory();
        
        //3.在虚拟机关闭时,释放SessionFactory
        Runtime.getRuntime().addShutdownHook(new Thread(){
            @Override
            public void run() {
                sf.close();
                System.out.println("释放资源");
            }
        });
        
    }
    
    public static Session openSession(){
        return sf.openSession();
    }
    
    public static Session getCurrentSession(){
        return sf.getCurrentSession();
    }
}

4、配置文件详解

4.1 hibernate.cfg.xml

image.png

image.png

4.2hbm.xml映射文件 解说

实体类entitymodel)的编写规则

²  我们在使用Hibernate时,书写了一个User类,这个类我们称为JavaBean

²  JavaBean可以简单的理解成提供私有属性,并提供私有属性的get/set方法

²  POJOPlain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans

²  我们也称为模型,在Hibernate中,又称这种类为实体因为是与表关联的

编写规则:

Ø  提供一个无参数 public访问控制符的构造器

Ø  提供一个标识属性,映射数据表主键字段,提供id

Ø  所有属性提供public访问控制符的 set  get 方法(javaBean)

Ø  标识属性应尽量使用基本数据类型的包装类型

        不要用final修饰实体 (将无法生成代理对象进行优化)

持久化对象的唯一标识 OID

v  Java地址区分同一个类的不同对象.

v  关系数据库用主键区分同一条记录

v  Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系结论: 对象的OID和数据库的表的主键对应。

v  为保证OID的唯一性,应该让Hibernate来为OID赋值

区分自然主键和代理主键

v  主键需要具备: 不为空/不能重复/不能改变                 

v  自然主键:         在业务中,某个属性符合主键的三个要求.那么该属性可以作为主键列.登录名可以是自然主键

v  代理主键:        在业务中,不存符合以上3个条件的属性,那么就增加一个没有意义的列.作为主键.

基本数据与包装类型

v  基本数据类型和包装类型对应hibernate的映射类型相同

v  基本类型无法表达null、数字类型的默认值为0

v  包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类。

 

SQLHibernate和对象类型对应

Java数据类型

Hibernate数据类型

标准SQL数据类型
  (PS:
对于不同的DB可能有所差异)

bytejava.lang.Byte

byte

TINYINT

shortjava.lang.Short

short

SMALLINT

intjava.lang.Integer

integer

INGEGER

longjava.lang.Long

long

BIGINT

floatjava.lang.Float

float

FLOAT

doublejava.lang.Double

double

DOUBLE

java.math.BigDecimal

big_decimal

NUMERIC

charjava.lang.Character

character

CHAR(1)

booleanjava.lang.Boolean

boolean

BIT

java.lang.String

string

VARCHAR

booleanjava.lang.Boolean

yes_no

CHAR(1)('Y''N')

booleanjava.lang.Boolean

true_false

CHAR(1)('Y''N')

java.util.Datejava.sql.Date

date

DATE

java.util.Datejava.sql.Time

time

TIME

java.util.Datejava.sql.Timestamp

timestamp

TIMESTAMP

java.util.Calendar

calendar

TIMESTAMP

java.util.Calendar

calendar_date

DATE

byte[]

binary

VARBINARYBLOB

java.lang.String

text

CLOB

java.io.Serializable

serializable

VARBINARYBLOB

java.sql.Clob

clob

CLOB

java.sql.Blob

blob

BLOB

java.lang.Class

class

VARCHAR

java.util.Locale

locale

VARCHAR

java.util.TimeZone

timezone

VARCHAR

java.util.Currency

currency

VARCHAR

主键的生成策略【重要】

<id name="uid" column="id">
   <!-- generator:id的生成策略
      increment:也会自动增长id,但是它的这种增长是自己Hibernate实现
                 执行select max(id) 查询,这种会有线程并发问题
      sequence:一般在oracle数据库才用
      hilo:hibernate自己实现的id规则【不用,不用学】
      native:【经常常用】
          如果是mysql数据库,id会自动增长
          如果是oracle数据库,会自动增长,sequence
      uuid:【经常常用】一个长字符串,需要把模型的id改成字符串
             保存的时候,不用自己设置ID,hibernate会设置id
      assigned:【经常常用】要手动设置id属性
    -->
  
<generator class="assigned"></generator>
</id>

普通属性

²  class标签的dynamic-insert="true" 是否动态生成插入语句,

²  【如果属性字段为空,就不会有些字段的插入语句】

image.png

image.pngimage.png

²  class标签的dynamic-update="true" insert类似

type使用

v  type是设置

image.png

image.png

Powered By Cheug's Blog

Copyright Cheug Rights Reserved.