Hibernate (一)
1 JDBC的优缺点
- 优点:
- 直接底层操作,提供了简单、便捷的访问数据库的方法,跨平台比较强。
- 灵活性比较强,可以写复杂的SQL。
- 缺点:
- JDBC没有做到面向对象的编程,使得程序员的思考还停留在SQL之上。
- 操作比较频繁,很多代码需要重复的写很多次。
- 如果遇到批量操作,频繁的和数据库进行交互,容易造成效率的下降。
2 Hibernate的优缺点
- 优点:
- 面向对象编程
- 缓存
- 一级缓存
- 二级缓存
- 查询缓存
- 代码操作比较简单
- 平台的移植性比较强
- 缺点:
- 如果该项目对SQL的优化要求比较高,不适合用Hibernate。
- 如果数据库的数据量比较大,也不适合用Hibernate。
- 如果表和表之间的关系比较复杂,也不能用Hibernate。
3 Hibernate的使用场合
- 表的关系不是很复杂
- 数据量不是很大
4 Hibernate的入门案例
4.1 导入jar包

4.2 编写hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--
一个sessionFactory就代表一个数据库的描述
-->
<session-factory>
<!-- 链接数据库的用户名 -->
<property name="connection.username">root</property>
<!-- 链接数据库的密码 -->
<property name="connection.password">root</property>
<!-- 链接数据库的驱动 -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- 链接数据库的url -->
<property name="connection.url">
jdbc:mysql://localhost:3306/hibernate
</property>
<!--
方言
告诉hibernate用什么样的数据库,将来会生成什么样的sql语句
-->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!--
hibernate对表的策略
validate 在hibernate容器启动的时候,根据映射文件和持久化类校验表
create 每次当hibernate启动的时候,都会根据持久化类和映射文件创建表
create-drop 每次当hibernate启动的时候,都会根据持久化类和映射文件创建表,销毁的时候删除表
update 检查,如果和映射文件不一致,则更新表的结构,如果没有表,则会创建表
-->
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
</session-factory>
</hibernate-configuration>
4.3 编写持久化类和映射文件
- Person.java
package com.xuweiwei.vo;
import java.io.Serializable;
/**
* 实体类
*/
public class Person implements Serializable {
private Long pid;
private String name;
private String sex;
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
- Person.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping >
<!--
class元素代表持久化类
name属性为类的全名
table属性为表的名字,默认值类名
-->
<class name="com.xuweiwei.vo.Person" table="person">
<!--
id为主键元素
name 标识符属性
column 对应表的字段
type 类型
length 数据库中pid的长度
-->
<id name="pid" column="pid">
<!--
主键生成策略
需要通过什么样的方式产生主键
-->
<generator class="native"/>
</id>
<!--
property代表普通的属性
-->
<property name="name" column="name"/>
<property name="sex" column="sex"/>
</class>
</hibernate-mapping>
- hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--
一个sessionFactory就代表一个数据库的描述
-->
<session-factory>
<!-- 链接数据库的用户名 -->
<property name="connection.username">root</property>
<!-- 链接数据库的密码 -->
<property name="connection.password">root</property>
<!-- 链接数据库的驱动 -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- 链接数据库的url -->
<property name="connection.url">
jdbc:mysql://localhost:3306/hibernate
</property>
<!--
方言
告诉hibernate用什么样的数据库,将来会生成什么样的sql语句
-->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!--
hibernate对表的策略
validate 在hibernate容器启动的时候,根据映射文件和持久化类校验表
create 每次当hibernate启动的时候,都会根据持久化类和映射文件创建表
create-drop 每次当hibernate启动的时候,都会根据持久化类和映射文件创建表,销毁的时候删除表
update 检查,如果和映射文件不一致,则更新表的结构,如果没有表,则会创建表
-->
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<mapping resource="com/xuweiwei/vo/Person.hbm.xml"/>
</session-factory>
</hibernate-configuration>
4.4 测试
- 示例:
package com.xuweiwei.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class TestPerson {
@Test
public void testCreateTable(){
//创建Configuration对象并加载hibernate.cfg.xml文件
Configuration configuration = new Configuration().configure();
//创建SessionFactory对象
SessionFactory sessionFactory = configuration.buildSessionFactory();
}
}
- 如果你想看的仔细的话,可以在类路径下加入log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout
#log4j.logger.org.hibernate=info
log4j.logger.org.hibernate=debug
### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug
### log just the SQL
#log4j.logger.org.hibernate.SQL=debug
### log JDBC bind parameters ###
log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug
### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug
### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug
### log cache activity ###
#log4j.logger.org.hibernate.cache=debug
### log transaction activity
#log4j.logger.org.hibernate.transaction=debug
### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug
### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
4.5 CRUD操作
- 示例:增加
package com.xuweiwei.test;
import com.xuweiwei.vo.Person;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class TestPerson {
@Test
public void testCreateTable(){
//创建Configuration对象并加载hibernate.cfg.xml文件
Configuration configuration = new Configuration().configure();
//创建SessionFactory对象
SessionFactory sessionFactory = configuration.buildSessionFactory();
}
@Test
public void testInsert(){
//创建Configuration对象并加载hibernate.cfg.xml文件
Configuration configuration = new Configuration().configure();
//创建SessionFactory对象
/**
* 1.SessionFactory是单例的
* 2.Hibernate的配置文件的信息、映射文件的信息、持久化类的信息全部在SessionFactory中
* 3.sessionFactory封装的信息是公共的数据
* 4.sessionFactory本身是线程安全的
*/
SessionFactory sessionFactory = configuration.buildSessionFactory();
//创建session对象
Session session = sessionFactory.openSession();
//开启事务
Transaction tx = session.beginTransaction();
Person p = new Person();
p.setName("丁希希");
p.setSex("女");
session.save(p);
//提交事务
tx.commit();
session.close();
sessionFactory.close();
}
}
- 示例:根据指定的id查询对象
@Test
public void testQuery(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = (Person) session.get(Person.class,1L);
System.out.print(p.getPid()+":"+p.getName()+":"+p.getSex());
tx.commit();
session.close();
sessionFactory.close();
}
- 示例:查询所有的对象
@Test
public void testAllQuery(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from Person");
List<Person> list = query.list();
for(Person p :list){
System.out.print(p.getPid()+":"+p.getName()+":"+p.getSex());
}
tx.commit();
session.close();
sessionFactory.close();
}
@Test
public void testAllQuery(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
SQLQuery query = session.createSQLQuery("select * from person");
query.addEntity(Person.class);
List<Person> list = query.list();
for(Person p :list){
System.out.print(p.getPid()+":"+p.getName()+":"+p.getSex());
}
tx.commit();
session.close();
sessionFactory.close();
}
@Test
public void testAllQuery(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Person.class);
List<Person > peoples = criteria.list();
for(Person p :peoples){
System.out.println(p.getPid()+":"+p.getName()+":"+p.getSex());
}
tx.commit();
session.close();
sessionFactory.close();
}
- 示例:更新
@Test
public void testUpdate(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = (Person) session.get(Person.class,1L);
p.setName("丁希希是我公司的前端妹子");
tx.commit();
session.close();
sessionFactory.close();
}
- 示例:删除
@Test
public void testDelete(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = (Person) session.get(Person.class,1L);
session.delete(p);
tx.commit();
session.close();
sessionFactory.close();
}
4.6 主键生成策略(在*.hbm.xml中配置)
- 封装Hibernate工具类:HibernateUtil.java
package com.xuweiwei.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Hibernate工具类
*/
public class HibernateUtil {
public static SessionFactory sessionFactory;
static{
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
}
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
}
- increment
/**
* select max(pid) from person
* insert into person(name, sex, pid) values (?, ?, ?)
* 1.先查询表中主键的最大值
* 2.把最大值+1作为新的主键 * 即便在程序中设置主键也不起作用,原因参考1和2
*
* 主键必须是数字类型
*/
@Test
public void testIncrement(){
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = new Person();
p.setName("许威威");
p.setSex("男");
session.save(p);
tx.commit();
session.close();
sessionFactory.close();
}
- assigned
/**
* 该策略必须通过程序设置
*/
@Test
public void testAssigned(){
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = new Person();
p.setPid(1L);
p.setName("许威威");
p.setSex("男");
session.save(p);
tx.commit();
session.close();
sessionFactory.close();
}
- identity
/**
* 利用数据库的主键自动增长,数据库的类型必须支持自动增长才行
*/
@Test
public void testIdentity(){
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = new Person();
p.setName("许威威");
p.setSex("男");
session.save(p);
tx.commit();
session.close();
sessionFactory.close();
}
- native:会根据不同的数据库判断底层的主键生成策略
- uuid:是由Hibernate内部产生的
/**
* uuid
*/
@Test
public void testUuid(){
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = new Person();
p.setName("许威威");
p.setSex("男");
session.save(p);
tx.commit();
session.close();
sessionFactory.close();
}
- sequence:Oracle中支持的自动增长机制
5 各个类或接口的作用
5.1 Configuration
- 用来加载hibernate.cfg,xml文件。
5.2 SessionFactory
- SessionFactory是单例的。
- Hibernate的配置文件的信息、映射文件的信息、持久化类的信息全部在SessionFactory中。
- SessionFactory封装的信息是公开的数据。
- SessionFactory本身是线程安全的。
5.3 Session
- CRUD操作都是由Session来完成的。
- Session是一个接口,实现类是SessionImpl。
- 在创建SessionImpl的时候,传递了一个参数为Connection,所以在Hibernate编程的时候,创建Session就相当于打开了一个连接。
- 当关闭Session的时候,相当于关闭了一个连接。
5.4 Transaction
- 事务是由Session来产生的
- 事务默认是关闭的,必须手动开启
6 Hibernate的加载流程

7 对象的状态
7.1 三种对象的定义和区别

- 【注意】如果一个对象的状态是持久态,那么数据库中不一定有对应的值。
- 比如:
session.save(p);
- 这个时候的对象的状态是持久态,但是数据库中是没有对应的值。
//提交事务 tx.commit();
- 这个时候对象的状态是持久态,但是数据库中有对应的值。
- 瞬时态对象和脱管态对象的区别:
- 瞬时太对象是从new创建的。
- 脱管态对象是从持久态转换过来的。
7.2 对象的状态转换

7.3 对象状态的示例
- 示例:
@Test
public void testInsert(){
//创建Configuration对象并加载hibernate.cfg.xml文件
Configuration configuration = new Configuration().configure();
//创建SessionFactory对象
/**
* 1.SessionFactory是单例的
* 2.Hibernate的配置文件的信息、映射文件的信息、持久化类的信息全部在SessionFactory中
* 3.sessionFactory封装的信息是公共的数据
* 4.sessionFactory本身是线程安全的
*/
SessionFactory sessionFactory = configuration.buildSessionFactory();
//创建session对象
Session session = sessionFactory.openSession();
//开启事务
Transaction tx = session.beginTransaction();
Person p = new Person();//顺时态对象
p.setName("许威威");//顺时态对象
p.setSex("男");//顺时态对象
session.save(p);//持久态对象
//提交事务
tx.commit();//持久态对象
session.close();//脱管态对象
sessionFactory.close();
}
- 示例:
@Test
public void testUpdate(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = (Person) session.get(Person.class,1L);//持久态对象
p.setName("呵呵");//持久态对象
//session.update(p); 将一个对象变为持久化状态,此时,p已经是持久态对象,所以可以不需要写update方法
tx.commit();
session.close();
sessionFactory.close();
}
- 示例:
@Test
public void testUpdate(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = (Person) session.get(Person.class,1L);//持久态对象
p.setName("呵呵");//持久态对象
session.evict(p);//把持久态对象变为了脱管态对象,所以不会更新
session.update(p);//把脱管态对象变为了持久态对象
tx.commit();
session.close();
sessionFactory.close();
}
- 示例:
@Test
public void testUpdate(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Person p = (Person) session.get(Person.class,1L);//持久态对象
p.setName("呵呵");//持久态对象
session.clear();//把person对象从hibernate中清空
session.update(p);
tx.commit();
session.close();
sessionFactory.close();
}
- 总结:
- 可以通过session的save/update/get等方法把一个对象变为持久态对象。持久态对象仅仅说明了该对象进入了Hibernate的区域,和数据库一点点关系也没有,和数据库有关系的是事务。
- 可以通过session的close/evict/clear等方法,将持久态对象变为脱管态对象。
Hibernate (一)的更多相关文章
- hibernate多对多关联映射
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- 解决 Springboot Unable to build Hibernate SessionFactory @Column命名不起作用
问题: Springboot启动报错: Caused by: org.springframework.beans.factory.BeanCreationException: Error creati ...
- hibernate多对一双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- Hibernate中事务的隔离级别设置
Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下
- Hibernate中事务声明
Hibernate中JDBC事务声明,在Hibernate配置文件中加入如下代码,不做声明Hibernate默认就是JDBC事务. 一个JDBC 不能跨越多个数据库. Hibernate中JTA事务声 ...
- spring applicationContext.xml和hibernate.cfg.xml设置
applicationContext.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans ...
- [原创]关于Hibernate中的级联操作以及懒加载
Hibernate: 级联操作 一.简单的介绍 cascade和inverse (Employee – Department) Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似 ...
- hibernate的基本xml文件配置
需要导入基本的包hibernate下的bin下的required和同bin下optional里的c3p0包下的所有jar文件,当然要导入mysql的驱动包了.下面需要注意的是hibernate的版本就 ...
- Maven搭建SpringMVC+Hibernate项目详解 【转】
前言 今天复习一下SpringMVC+Hibernate的搭建,本来想着将Spring-Security权限控制框架也映入其中的,但是发现内容太多了,Spring-Security的就留在下一篇吧,这 ...
- 1.Hibernate简介
1.框架简介: 定义:基于java语言开发的一套ORM框架: 优点:a.方便开发; b.大大减少代码量; c.性能稍高(不能与数据库高手相比,较一般数据库使用者 ...
随机推荐
- 如何使用webapi集成swagger
现在B/S开发中,前后端分离无疑已经成为一种新的时尚,但是如何把后端开发的接口更好的提供给前段开发呢?还用接口文档?low了吧.不仅要花时间开发接口,还得花时间写文档,白花花的时间不久浪费了吗.如果接 ...
- 登录模块的进化史,带大家回顾java学习历程(二)
接着前面的登录模块的进化史,带大家回顾java学习历程(一) 继续往下面讲 前面我们去实现登录功能,都是想着要完成这个功能,直接在处理实际业务的类中去开始写具体的代码一步步实现,也就是面向过程的编程. ...
- WEB相关系列
一.Nginx(web服务器) Nginx概述和安装(1) Nginx配置文件(2) Nginx日常维护操作(3) Nginx常用配置实例(4) Nginx常用功能(5) Nginx性能优化技巧(6) ...
- Zabbix实战-简易教程--技巧(本地化)
1.zabbix的logo图标替换(不建议修改) 3.0版本以下: 1.修改/usr/share/zabbix/include/page_header.php 2.修改/usr/share/zabbi ...
- 加载进度圈,带遮罩层(jquery)
如图: Js下载地址:http://files.cnblogs.com/files/holdon521/cvi_busy_lib.js 如下使用实例: <script src="/st ...
- 【LCT维护基环内向树森林】BZOJ4764 弹飞大爷
4764: 弹飞大爷 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 101 Solved: 52[Submit][Status][Discuss] ...
- Effective Java 第三版——22. 接口仅用来定义类型
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Eclipse卡顿,内存猛增解决方案
本文转载自http://rsy.iteye.com/blog/2095668/ PS:所有校验都去除后,对如下版本来说,内存一直猛增,解决办法参照上放博客:修改项目的.project文件,特此备注记录 ...
- Codeforces Round #408 (Div. 2)(A.水,B,模拟)
A. Buying A House time limit per test:2 seconds memory limit per test:256 megabytes input:standard i ...
- 51Nod 1632 B君的连通(递归,快速幂)
1632 B君的连通 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 B国拥有n个城市,其交通系统呈树状结构,即任意两个城市存在且仅存在一条交通线将其连接.A国是B ...