Hibernate入门

1. 什么是Hibernate

既然大家已经点击进入了该博文,想必大家已经听闻了Hibernate的大名了,那么什么是Hibernate呢?它能干什么?我们使用它有什么好处呢?下面且听老王细细道来。(如对Hibernate了解的同学可以忽略该段)

使用传统的JDBC开发应用系统时,如果是小型应用系统,并不觉得有什么麻烦,但是对于大型应用系统的开发,使用JDBC就会显得力不从心。例如对几十、几百张包含几十个字段的表进行插入操作时,编写的SQL语句不但很长,而且繁琐,容易出错。在读取数据时,需要写多条getXxx语句从结果集中取出各个字段的信息,不但枯燥重复,并且工作量非常大。为了提高数据访问层的编程效率,Gavin King开发出了一个当今最流行的的ORM框架,它就是Hibernate框架。

所谓的ORM就是利用描述对象和数据库表之间映射的元数据,自动把Java应用程序中的对象,持久化到关系型数据库的表中。通过操作Java对象,就可以完成对数据库表的操作。可以把ORM理解为关系型数据和对象的一个纽带,开发人员只需要关注纽带一端映射的对象即可。ORM原理如下图所示。
在这里插入图片描述
与其它操作数据库的技术相比,Hibernate具有以下几点优势:

  • Hibernate对JDBC访问数据库的代码做了轻量级封装,大大简化了数据访问层繁琐的重复性代码,并且减少了内存消耗,加快了运行效率。
  • Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现,它很大程度的简化了DAO(Data Access Object,数据访问对象)层编码工作。
  • Hibernate的性能非常好,映射的灵活性很岀色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系。
  • 可扩展性强,由于源代码的开源以及API的开放,当本身功能不够用时,可以自行编码进行扩展。

2. Hibernate快速入门

2.1 创建表结构

CREATE TABLE `cst_customer` (
	`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
	`cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
	`cust_user_id` bigint(32) DEFAULT NULL COMMENT '负责人id',
	`cust_create_id` bigint(32) DEFAULT NULL COMMENT '创建人id',
	`cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
	`cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
	`cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
	`cust_linkman` varchar(64) DEFAULT NULL COMMENT '联系人',
	`cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
	`cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
	PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=94 DEFAULT CHARSET=utf8;

2.2 创建实体(持久化类)

public class Customer {
	private Long cust_id;
	private String cust_name;
	private Long cust_user_id;
	private Long cust_create_id;
	private String cust_source;
	private String cust_industry;
	private String cust_level;
	private String cust_linkman;
	private String cust_phone;
	private String cust_mobile;
	
	// 省略get和set方法
	
}

2.3 创建映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!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.joker.demo1.Customer" table="cst_customer">
		<!-- 建立类中的属性与表中的主键对应 -->
		<id name="cust_id" column="cust_id" >
			<generator class="native"/>
		</id>
		
		<!-- 建立类中的普通的属性和表的字段的对应 -->
		<property name="cust_name" column="cust_name" length="32" />
		<property name="cust_source" column="cust_source" length="32"/>
		<property name="cust_industry" column="cust_industry"/>
		<property name="cust_level" column="cust_level"/>
		<property name="cust_phone" column="cust_phone"/>
		<property name="cust_mobile" column="cust_mobile"/>
	</class>
</hibernate-mapping>

2.4 创建Hibernate核心的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!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.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///hibernateDemo</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">123456</property>
		<!-- 配置Hibernate的方言 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		
		<!-- 可选配置================ -->
		<!-- 打印SQL -->
		<property name="hibernate.show_sql">true</property>
		<!-- 格式化SQL -->
		<property name="hibernate.format_sql">true</property>
		<!-- 自动创建表 -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		
		<!-- 配置C3P0连接池 -->
		<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
		<!--在连接池中可用的数据库连接的最少数目 -->
		<property name="c3p0.min_size">5</property>
		<!--在连接池中所有数据库连接的最大数目 -->
		<property name="c3p0.max_size">20</property>
		<!--设定数据库连接的过期时间,以秒为单位,
				如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
		<property name="c3p0.timeout">120</property>
		<!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
		<property name="c3p0.idle_test_period">3000</property>
		
		<!--Hibernate加载映射-->
		<mapping resource="com/joker/demo1/Customer.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

2.5 编写测试代码

public class HibernateDemo1 {

	@Test
	// 保存客户的案例
	public void demo1(){
		// 1.加载Hibernate的核心配置文件
		Configuration configuration = new Configuration().configure();
		// 手动加载映射
		// configuration.addResource("com/joker/demo1/Customer.hbm.xml");
		// 2.创建一个SessionFactory对象:类似于JDBC中连接池
		SessionFactory sessionFactory = configuration.buildSessionFactory();
		// 3.通过SessionFactory获取到Session对象:类似于JDBC中Connection
		Session session = sessionFactory.openSession();
		// 4.手动开启事务:
		Transaction transaction = session.beginTransaction();
		// 5.编写代码
		Customer customer = new Customer();
		customer.setCust_name("joker");
		
		session.save(customer);
		
		// 6.事务提交
		transaction.commit();
		// 7.资源释放
		session.close();
		sessionFactory.close();
	}
}

3. Hibernate的常见配置

3.1 映射文件的配置

映射文件通常是一个XML文件,但一般命名为:类名.hbm.xml。该文件用于向Hibernate提供持久化类到关系型数据库的映射,每个映射文件的的结构基本都是相同的,其普遍的代码形式如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<!-- 映射文件的dtd信息 -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<!-- name代表的是实体类名,table代表的是表名 -->
	<!-- c1ass标签:用来建立类和表的映射
			* name属性:类中的全踏径
			* table属性:表名(如果类名和表名是一致的,那么 table属性客户省略)
			* catalog属性:数据库名称,可以省略
		-->
	<class name="com.joker.demo1.Customer" table="cst_customer">
		<!-- name=id代表的是Xxx类中属性,column=id代表的是xxx表中的字段 -->
		<!-- id标签:用来建立类中的属性与表中的主键宇段对应
					* name属性:类中的属性名
					* column属性:表中字段名(如果类中的属性名和表中的字段名一致,那么省略 column)
					* length属性:字段的长度,
					* type属性:类型。写Java数据类型,Hibernate数据类型(默认),SQL类型
				-->
		<id name="cust_id" column="cust_id" >
			<!-- 主键生成策略 -->
			<generator class="native"/>
		</id>
		
		<!-- 其它属性使用 property标签来映射 -->
		<!-- property标签:用来建立类中的普通属性与表中的字段对应
					* name属性:类中的属性名
					* column属性:表中字段名(如果类中的属性名和表中的字段名一致,那么省略 column)
					* length属性:字段的长度,
					* type属性:类型。写Java数据类型,Hibernate数据类型(默认),SQL类型
				-->
		<property name="cust_name" column="cust_name" length="32" />
		<property name="cust_source" column="cust_source" length="32"/>
		<property name="cust_industry" column="cust_industry"/>
		<property name="cust_level" column="cust_level"/>
		<property name="cust_phone" column="cust_phone"/>
		<property name="cust_mobile" column="cust_mobile"/>
	</class>
</hibernate-mapping>

3.2 核心配置文件

Hibernate的配置文件,包含了连接持久层与映射文件所需的基本信息,其配置文件有两种格式,一种是properties属性文件格式的配置文件,它使用键值对的形式存放信息,默认文件名称为hibernate.properties。另一种是XML格式的配置文件,XML配置文件的默认名称为hibernate.cfg.xml。两种格式的配置文件是等价的,具体使用哪个可以自由选择。XML格式的配置文件更易于修改,配置能力更强,当改变底层应用配置时不需要改变和重新编译代码,只修改配置文件的相应属性即可,而properties格式的文件则不具有此优势,因此,在实际开发项目中,大多数情况会使用XML格式的配置文件。下面将对XM格式的配置文件进行详细介绍。

<?xml version="1.0" encoding="UTF-8"?>
<!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.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///hibernateDemo</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">123456</property>
		<!-- 配置Hibernate的方言(根据配置的方言生成相应的SQL语句) -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		
		<!-- 可选配置================ -->
		<!-- 打印SQL -->
		<property name="hibernate.show_sql">true</property>
		<!-- 格式化SQL -->
		<property name="hibernate.format_sql">true</property>
		<!-- 自动创建表 -->
		<!-- hbm2ddl.auto的取值
					* none:不用 Hibernate自动生成表
					* create:每次都会创建一个新的表
					* create-drop:每次都会创建一个新的表,执行程序结束后删除这个表
					* update:如果数据库中有表,使用原来的表,如果没有表,创建一个新表,可以更新表结构
					* validate:只会使用原有的表,对映射关系进行校验
				-->
		<property name="hibernate.hbm2ddl.auto">update</property>
				
		<!--Hibernate加载映射-->
		<mapping resource="com/joker/demo1/Customer.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

4. Hibernate的相关API

4.1 Configuration

  1. 加载核心配置文件:
    在使用Hibernate时,首先要创建Configuration实例,Configuration实例主要用于启动、加载、管理Hibernate的配置文件信息。在启动Hibernate的过程中,Configuration实例首先确定Hibernate配置文件的位置,然后读取相关配置,最后创建一个唯一的SessionFactory实例。Configuration对象只存在于系统的初始化阶段,它将SessionFactory创建完成后,就完成了自己的使命。Hibernate通常使用
    Configuration config = new Configuration().configure();
    
    的方式创建实例,此种方式默认会去src下读取hibernate.cfg.xml配置文件。如果不想使用默认的hibernate.cfg.xml配置文件,而是使用指定目录下(或自定义)的配置文件,则需要向configure方法中传递一个文件路径的参数,其代码写法如下:
    Configuration config = new Configuration().configure("xml文件位置");
    
    此种写法Hibernate会去指定位置查找配置文件,例如,想要使用src下config包中的hibernate.cfg.xml文件,只需将文件位置加入configure()中即可,其代码如下所示:
    Configuration config = new Configuration().configure("/config/hibernate.cfg.xml");
    
  2. 加载映射文件:
    Hibernate除了可以使用Configuration对象加载核心配置文件以外,还可以利用该对象加载映射文件。因为如果使用properties文件作为Hibernate的核心配置文件,其他的属性可以使用key = value的格式来设置,但是映射没有办法加载。这时这个对象就有了用武之地。可以在手动编写代码的时候去加载映射文件。
    Configuration config = new Configuration().configure("xml文件位置");
    configuration.addResource("cn/joker/Customer.hbm.xml");
    

4.2 SessionFactory

SessionFactory接口负责Hibernate的初始化和建立Session对象。它在Hibernate中起到一个缓冲区作用,Hibernate可以将自动生成的SQL语句、映射数据以及某些可重复利用的的数据放在这个缓冲区中。同时它还保存了对数据库配置的所有映射关系,维护了当前的二级缓存。SessionFactory实例是通过Configuration对象获取的,其获取方法如下所示:

SessionFactory sessionFactory = configuration.buildSessionFactory();

它具有以下特点:

  • 它是线程安全的,它的同一个实例能够供多个线程共享。
  • 它是重量级的,不能随意的创建和销毁它的实例。

由于SessionFactory的这些特点,一般情况下,一个项目中只需要一个SessionFactory,只有当应用中存在多个数据源时,才为每个数据源建立一个SessionFactory实例。SessionFactory内部还维护了一个连接池,如果我们需要使用第三方的连接池如C3P0,那么需要我们自己手动进行配置。

4.3 Session

Session是应用程序与数据库之间交互操作的一个单线程对象,是Hibernate运作的中心,它的主要功能是为持久化对象提供创建、读取和删除的能力,所有持久化对象必须在Session的管理下才可以进行持久化操作。创建Sessionfactory实例后,就可以通过它获取Session实例。获取Session实例有两种方式一种是通过openSession方法,另一种是通过getCurrentSession方法。两种方法获取Session的代码如下所示:

// 采用openSession()方法创建session
Session session = sessionFactory.openSession();
// 采用getCurrentSession()方法创建session
Session session = sessionFactory.getCurrentSession();

以上两种获取Session实例方式的主要区别是,采用openSession方法获取Session实例时,SessionFactory直接创建一个新的Session实例,并且在使用完成后需要调用close方法进行手动关闭。而getCurrentSession方法创建的Session实例会被绑定到当前线程中,它在提交或回滚操作时会自动关闭。

Session是线程不安全的,多个并发线程同时操作一个Session实例时,就可能导致Session数据存取的混乱(方法内部定义和使用Session时,不会出现线程问题)。因此设计软件架构时,应避免多个线程共享一个Session实例。同时它也是轻量级的,实例的创建和销毁不需要消耗太多的资源。它还有一个缓存,即Hibernate的一级缓存,这个缓存主要用于存放当前工作单元加载的对象。在Session中提供了大量的常用方法,具体如下:

  • save()、update()、saveOrUpdate()方法:用于增加和修改对象。
  • delete()方法:用于删除对象。
  • get()和load()方法:根据主键查询。
  • createQuery()和createSQLQuery()方法:用于数据库操作对象。
  • createCriteria()方法:条件查询。

4.4 Transaction

Transaction接口主要用于管理事务,它是Hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是通过Session对象开启的,其开启方式如下所示:

Transaction transaction = session.beginTransaction();

在Transaction接口中,提供了事务管理的常用方法,具体如下:

  • commit()方法:提交相关联的session实例。
  • rollback()方法:撤销事务操作。

Session执行完数据库操作后,要使用Transaction接口的commit方法进行事务提交,才能真正的将数据操作同步到数据库中。发生异常时,需要使用rollback方法进行事务回滚,以避免数据发生错误。因此,在持久化操作后,必须调用Transaction接口的commit方法和rollback方法。如果没有开启事务,那么每个Session的操作,都相当于一个独立的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值