Hibernate框架学习(一)

来源:互联网 发布:人工智能资讯app 编辑:程序博客网 时间:2024/06/06 05:57

一、简介

使用Hibernate可以以面向对象的方式来操作数据库,而不需要书写sql语句。

Hibernate是一种ORM(Object relation mapping):使用映射文件来配置实体类对象与表之间的映射关系,对象名对应表明,属性对应列。使用中只需要操作实体类对象即可,不需要操作表。
ORM分四个等级:Hibernate为4级ORM;MyBatis为2级ORM;DBUtils为1级ORM

二、环境搭建

1、导包(hibernate必须的包+驱动包)
2、创建数据库,准备表
3、准备实体类以及书写ORM元数据(对象与表的映射配置文件)
(1)导入约束(可以存在本地或者从网上导入——preferences中XML catalog)
(2)实体
(3)ORM元数据
4、书写主配置文件
5、书写代码测试

三、配置文件详解

orm元数据(xxx.hbm.xml)

<hibernate-mapping package=""><!--    class元素: 配置实体与表的对应关系的    name: 完整类名    table:数据库表名-->    <class name="" table="" >        <id name=""  >            <!-- 主键生成策略 -->            <generator class=""></generator>        </id><!--    property元素:除id之外的普通属性映射    name: 填写属性名    column(可选): 填写列名    type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.            每个类型有三种填法: java类型(java.lang.String)|hibernate类型(string)|数据库类型(如下注释中的指定方法)    not-null(可选):配置该属性(列)是否不能为空. 默认值:false    length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度--><!--    <column name="cust_name" sql-type="varchar" ></column>-->        <property name="cust_name" column="cust_name" ></property>        <property name="cust_source" column="cust_source" ></property>        <property name="cust_industry" column="cust_industry" ></property>        <property name="cust_level" column="cust_level" ></property>        <property name="cust_linkman" column="cust_linkman" ></property>        <property name="cust_phone" column="cust_phone" ></property>        <property name="cust_mobile" column="cust_mobile" ></property>    </class></hibernate-mapping>

hibernate.cfg.xml

<hibernate-configuration><session-factory>必须配置:        <property name="hibernate.connection.driver_class">xxxxxxxx</property>        <property name="hibernate.connection.url">xxxxxxx</property>        <property name="hibernate.connection.username">xxxxxxx</property>        <property name="hibernate.connection.password">xxxxxxx</property>        <!-- 数据库方言 -->        <!-- 不同数据库中,sql语句略有不同,指定数据库方言可以让hibernate框架在生成sql语句时针对数据库方言生成。  -->        <!-- 选择mysql方言时选择最短的那条  -->        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>可选配置:        <property name="hibernate.show_sql">true</property>        <property name="hibernate.format_sql">true</property>        <!-- 自动生成表的策略 --><!--        #hibernate.hbm2ddl.auto create              自动建表。每次框架运行都会创建新的表,以前表将会被覆盖,表数据会丢失。        #hibernate.hbm2ddl.auto create-drop         自动建表。每次框架运行结束都会将所有表删除。        #hibernate.hbm2ddl.auto update              自动生成表。如果已经存在则不会生成,若表有变动,则更新。        #hibernate.hbm2ddl.auto validate            校验。不自动生成表。每次启动会校验数据库中表是否正确。校验失败:抛异常。-->        <property name="hibernate.hbm2ddl.auto">update</property>orm元数据引入:        <!-- 路径填写:填写src下的相对路径 -->        <mapping resource=""/></session-factory></hibernate-configuration>

四、API详解

读取配置:Configuration
创建session:SessionFactory
获得事务操作对象,执行增删改查操作:session
控制事务:Transaction

五、Hibernate中的实体规则

1、实体类创建的注意事项

(1)持久化类提供无参的构造(因为在Hibernate底层需要使用反射生成类的实例)
(2)成员变量私有化,提供get/set方法来对外提供属性。
(3)持久化类中的属性,应尽量使用包装类型。
(4)持久化类需要提供oid,与数据库中主键列对应。
(5)不要用final修饰实体类。(由于hibernate中使用的cglib对象代理是通过继承实现的)

2、主键类型

(1)自然主键:表的业务列中,有某列符合非空且唯一的特征,则该列就可以作为主键使用,叫做自然主键。
(2)代理主键:表的业务列中没有符合非空且唯一的特征时,则创建一个没有业务意义的列作为主键,叫做代理主键。

3、主键生成策略

identity:主键自增,有数据库来维护主键值,录入时不需要手动指定
increment:主键自增,有hibernate维护,每次插入前会先查询表中id最大值,+1作为新主键值(有线程安全问题)
sequence:Oracle中的主键生成策略。
hilo:高低位算法(数据库中主键自增算法)。主键自增,有数据库来维护主键值
native:hilo+sequence+identity中自动选择一个合适的。
uuid:用来产生唯一的随机字符串作为主键。必须用String作为主键类型才能使用。
assigned:自然主键生成策略,hibernate不会管理主键值,由开发人员自己录入。

六、Hibernate中的对象状态

1、瞬时状态

没有id,没有与session关联(没有在session缓存中)。

2、持久化状态

有id,与session有关联(在session缓存中)。

3、游离(托管)状态

有id,没有与session关联(没有在session缓存中)。
状态转换图:
这里写图片描述

七、Hibernate实现。

1、Hibernate一级缓存

Hibernate中会有一个session缓存。会将实体对象存在缓存中。重复调用时只从缓存中拿。
这里写图片描述
这里写图片描述

2、Hibernate中的事务

在hibernate.cfg.xml中指定事务的隔离级别

## specify a JDBC isolation level#hibernate.connection.isolation 1|2|4|8        0001    1   读未提交        0010    2   读已提交        0100    4   可重复读        1000    8   串行化<property name="hibernate.connection.isolation">4</property>

事务都是要在业务层使用,在业务开始前打开事务,业务结束后提交事务,出错则回滚。

需要将session绑定在线程上,使得service层和dao层中使用的session是同一个session:
在Hibernate中,使用sessionFactory.getCurrentSession()方法即可获得与当前线程绑定的session对象。
注意:1.调用getCurrentSession方法必须配合主配置文件中的一段配置。
<property name="hibernate.current_session_context_class">thread</property>
2.通过getCurrentSession方法获得的session对象当事务提交时会自动关闭,因此不要手动调用close关闭。


补充学习:

之前学习中获取的connection对象也需要保证在不同的层获取到的是同一个,使用ThreadLocal对象。ThreadLocal对象实际上是一个map,它内部实现会默认使用执行它的线程作为key;我们只需要在连接池工具类中将获取的连接绑定到某个线程上,在同一线程中下次使用的时候就可以通过ThreadLocal对象中直接取出这个连接。
下面为相应的代码。

public class MyDataSourceUtils {    // 获得Connecton---------从连接池中获取    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();    // 创建ThreadLocal    private static ThreadLocal<Connection> tl = new ThreadLocal<>();    // 开启事务    public static void startTransaction() throws SQLException {        Connection conn = getCurrentConnection();        conn.setAutoCommit(false);    }    // 获得当前线程上绑定的conn    public static Connection getCurrentConnection() throws SQLException {        // 从ThreadLocal中寻找当前是否有现成的Connection        Connection conn = tl.get();// 执行这个代码需要某个线程执行,因此就相当于以该线程名为key,get到里面的value        if (conn == null) {            // 如果没有现成的Connection,就获取一个新的            conn = getConnection();            // 将connection资源绑定到ThreadLocal(map)上            tl.set(conn);        }        return conn;    }    public static Connection getConnection() throws SQLException {        return dataSource.getConnection();    }    // 回滚事务    public static void rollback() throws SQLException {        getCurrentConnection().rollback();    }    // 提交事务    public static void commit() throws SQLException {        Connection conn = getCurrentConnection();        conn.commit();        // 本次操作结束了,将Connection从ThreadLocal中移除        tl.remove();        conn.close();    }}
原创粉丝点击