Hibernate浅谈

关于Hibernate的配置与介绍

ORM与Hibernate

ORM(Object Relational Mapping)是对象关系映射,使用ORM能使习惯面向对象的程序员在项目中少写和底层数据库相关的SQL语句,方便程序的维护、修改、跨平台性和扩展。
Hibernate是一款技术成熟稳定的ORM框架。

Hibernate开发基本步骤

  1. 编写配置文档hibernate.cfg.xml
  2. 编写实体类(和数据库的表一一对应,遵循JavaBean设计规范)
  3. 生成对应实体类的映射文件并添加到配置文档中
  4. 调用Hibernate API进行测试

Hibernate的执行流程

Hibernate01

hibernate.cgt.xml常用配置

  1. hibernate.show_sql
    是否把Hibernate运行时的SQL语句输出到控制台,编码阶段便于测试。

  2. hibernate.format_sql
    输出到控制台的SQL语句是否进行排版,便于阅读。建议设置为true。

  3. hbm2ddl.auto
    可以帮助由java代码生成数据库脚本,进而生成具体的表结构。

    • create
      每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行。
    • update
      最常用的值,第一次加载Hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
    • create-drop
      每次加载Hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
    • validate
      每次加载Hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
  4. hibernate.default_schema
    默认的数据库名
    在生成表结构的时候给所有表名加前缀。

  5. hibernate.dialect
    配置Hibernate数据库方言,Hibernate可针对特殊的数据库进行优化。

注:hibernate的前缀可以省略,即hibernate.dialect等同于dialect

session简介

  • session可以理解为操作数据库的对象。
  • session与connection,是多对一关系,每个session都有一个与之对应的connection,一个connection不同时刻可以供多个session使用。
  • 把对象保存在关系数据库中需要调用session的各种方法,如:save(),update(),delete(),createQuery()等。

transaction简介

Hibernate对数据的操作都是封装在事务当中,并且默认是非自动提交的方式。所以用session保存对象时,如果
不开启事务,并且手工提交事务,对象并不会真正保存在数据库中。

如果想让Hibernate像jdbc那样自动提交事务,必须调用session对象的doWork()方法,获得jdbc的connection后,设置其为自动提交事务模式(注:通常不推荐这样做)。

session详解

获得session对象

  1. openSession
  2. getCurrentSession

如果使用getCurrentSession需要在hibernate.cfg.xml文件中进行配置:
如果是本地事务(jdbc事务)

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

如果是全局事务(jta事务)

1
<property name="hibernate.current_session_context_class">jta</property>

openSession和getCurrentSession的区别

  1. getCurrentSession再事务提交或者回滚之后会自动关闭,而openSession需要你手动关闭。如果使用openSession而没有手动关闭,多次之后会导致连接池溢出。
  2. openSession每次创建新的session对象,getCurrentSession使用现有的session对象。

对象关系映射(hbm)常用配置

1
2
3
4
5
6
7
8
<hibernate-mapping
schema="schemaName"
catalog="catalogName"
default-cascade="cascade_style" //级联风格
default-access="field|property|ClassName" //访问策略
default-lazy="true|false" //加载策略
package="packagename"
/>
1
2
3
4
5
6
7
<class
name="ClassName" //对象关系映射 映射的哪个类
table="tableName"//把类映射成数据库中的哪张表
batch-size="N"//抓取策略 一次抓取多少条记录
where="condition"//设置的抓取条件
entity-name="EntityName"//支持同一个类映射多张表
/>
1
2
3
4
5
6
7
<id
name="propertyName" //映射的哪个属性
type="typename"//数据类型
column="colum_name"//映射成数据库的表当中的字段名称
length="length"//指定长度
<generator class="generatorClass"/>//主键生成策略
/>

主键生成策略

  • assigned
    适用于自然主键。由Java应用程序负责生成标识符(手工赋值)。
    如果实体类中设置的主键id是基本类型int的话,则可以不用赋值,系统默认值为0;如是引用类型Integer话,则默认值为null,不赋值系统则报错。

  • native
    适用于代理主键。根据底层数据库对自动生成标识符的方式,自动选择identity、sequence或hilo。
    系统会自动选择该数据库对应的自动增值方式,从1开始。即使手动给它赋值,也不会起作用,但也不会报错。

主键属性

实体类中的某个属性属于用户自定义类的对象。

1
2
3
4
5
<component name="address" class="Address">
<property name="postcode" column="POSTCODE"></property>
<property name="phone" column="PHONE"></property>
<property name="address" column="ADDRESS"></property>
</component>>

单表增删改查

save方法

1
2
3
4
5
6
@Test
public void testSaveStudents() {
//生成学生对象
Students s = new Students(1,"袁绍","男",new Date(),"南皮");
session.save(s);//保存对象进入数据库
}

get/load方法

  • get方法
    get不支持延迟加载,通过get查询数据时,立即向数据库发送查询语句,
    如果被查询的数据在数据库不存在时则返回null。
    get方法返回的是实体类的对象类型。
1
2
3
4
5
@Test
public void testGetStudents() {
Students s = (Students)session.get(Students.class, 1);//1为主键值
System.out.println(s);
}
  • load方法
    load方法默认支持延迟加载,通过load查询时,不会立即向数据库发送查询语句,
    只有当需要使用时被查询的数据时才会向数据库发起查询请求;如果被查询的数据不存在,
    load方法会抛出异常org.hibernate.ObjectNotFoundException。
    如果使用延迟加载,在使用对象之前不能关闭session,否则就会出现no session异常。
    load方法返回的是代理对象。
1
2
3
4
5
@Test
public void testLoadStudents() {
Students s = (Students)session.load(Students.class, 1);
System.out.println(s);
}

Update方法

1
2
3
4
5
6
@Test
public void testUpdateStudents() {
Students s = (Students)session.get(Students.class, 1);
s.setGender("女");
session.update(s);
}

Delete方法

1
2
3
4
5
@Test
public void testDeleteStudents() {
Students s = (Students)session.get(Students.class, 1);
session.delete(s);
}