5.1 Configuration接口
5.1.1加载hibernate.cfg.xml并完成系统的配置
Configuration接口的作用是对Hibernate进行配置、并启动Hibernate和连接数据库系统。
在Hibernate的启动过程中,Configuration类的实例首先定位缺省XML配置文件(hibernate.cfg.xml),并读取关的配置项目,然后创建出一个SessionFactory对象。根5.1.2据Configuration对象创建一个SessionFactory对象。
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
5.1.3 也可以采用自定义的XML配置文件(少用)
可以指定开发者自己的*.hbm.xml文件的位置,而不是使用默认的classpath下面的hibernate.cfg.xml。但需要在代码中指示开发者自定义的XML配置文件。
cfg.configure("hibernate2.cfg.xml");
5.2 SessionFactory接口
5.2.1 利用工厂类SessionFactory中取得Session的实例
Session session = sessionFactory.openSession();
5.2.2 SessionFactory并不是轻量级的
但要注意的是SessionFactory并不是轻量级的!(占内存)
实际上它的设计者的意图是让它能在整个应用中共享。
5.2.3 每个数据存储源对应创建一个SessionFactory(单例)
5.2.4 SessionFactory的缓存
可分为两类:内置缓存和外置缓存。
5.2.4.1 SessionFactory的内置缓存中存放了Hibernate配置信息和映射元数据信息、同时也缓存了Hibernate自动生成的SQL语句等;
5.2.4.2 SessionFactory的外置缓存是一个可配置的缓存插件
在默认情况下,SessionFactory不会启用这个缓存插件。
外置缓存能存放大量数据库数据的拷贝,外置缓存的物理介质可以是内存或者硬盘。
5.3 Session接口
5.3.1轻量级的类
在Hibernate中,实例化的Session是一个轻量级的类,创建和销毁它都不会占用很多资源。
这在实际项目中确实很重要,因为在客户程序中,可能会不断地创建以及销毁Session对象,如果Session的开销太大,会给系统带来不良影响。
5.3.2非线程安全的(一请求---一线程----一session---一事务)
值得注意的是Session对象是非线程安全的,因此最好是一个线程只创建一个Session对象(将它设计为局部对象)。
private static ThreadLocal threadSession = new ThreadLocal();
public static Session getThreadLocalSession(){
Session s = (Session) threadSession.get();
if(s == null){
s = sessionFactory.openSession();
threadSession.set(s);
}
return s;
}
5.3.3 Session看作介于数据连接与事务管理一种中间接口
我们可以将session想象成一个持久对象的缓冲区,Hibernate能检测到这些持久对象的改变,并及时刷新数据库。
5.3.4 每一个Session实例和一个数据库事务绑定
通常将每一个Session实例和一个数据库事务绑定,也就是说,每执行一个数据库事务(操作),都应该先创建一个新的Session实例。
如果事务执行中出现异常,应该撤销事务;同时不论事务执行成功与否,最后都应该调用Session的close()方法,从而释放Session实例占用的资源。
5.3.5如何获得Session对象
首先创建SessionFactory对象,应用程序如果访问多个数据源时,则应该产生多个SessionFactory;但是仅仅为了服务于某个请求时,不要创建一个新的 SessionFactory,因为创建SessionFactory 需要耗费大量的资源。
然后根据SessionFactory再创建Session对象
5.3.6 Session的编程规则---需要随时更新和释放
注意:应该要session.close()语句放在finally语句块中。
5.3.7 Sessin 接口中针对单条记录的基本的CURD操作方法
1、save();session.save(Object);//session的save方法是向数据库中保存一个对象
2、delete()
session.delete(Object);//Object对象需要有ID。对象删除后,对象状态为Transistent状态
3、load() Session.load(Class arg0, Serializable arg1) throws HibernateException
* arg0:需要加载对象的类,例如:User.class
* arg1:查询条件(实现了序列化接口的对象):例"4028818a245fdd0301245fdd06380001"字符串已经实现了序列化接口。如果是数值类类型,则hibernate会自动使用包装类,例如 1
* 此方法返回类型为Object,但返回的是代理对象。
* 执行此方法时不会立即发出查询SQL语句。只有在使用对象时,它才发出查询SQL语句,加载对象。
* 因为load方法实现了lazy(称为延迟加载、赖加载)
* 延迟加载:只有真正使用这个对象的时候,才加载(才发出SQL语句)
* hibernate延迟加载实现原理是代理方式。
* 采用load()方法加载数据,如果数据库中没有相应的记录,则会抛出异常对象不找到(org.hibernate.ObjectNotFoundException)
try {
session = sf.openSession();
session.beginTransaction();
User user = (User)session.load(User.class,1);
//只有在使用对象时,它才发出查询SQL语句,加载对象。
System.out.println("user.name=" + user.getName());
//因为此的user为persistent状态,所以数据库进行同步为龙哥。
user.setName("发哥");
session.getTransaction().commit();
} catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally{
if (session != null){
if (session.isOpen())
session.close();
}
4、Get()
Session.get(Class arg0, Serializable arg1)方法
* arg0:需要加载对象的类,例如:User.class
* arg1:查询条件(实现了序列化接口的对象):
例"4028818a245fdd0301245fdd06380001"字符串已经实现了序列化接口。如果是基数类型,则hibernate会自动转换成包装类,如 1
返回值: 此方法返回类型为Object,也就是对象,然后我们再强行转换为需要加载的对象就可以了。
如果数据不存在,则返回null;
注:执行此方法时立即发出查询SQL语句。加载User对象
加载数据库中存在的数据,代码如下:
try {
session = sf.openSession();
session.beginTransaction();
/ * 此方法返回类型为Object,也就是对象,然后我们再强行转换为需要加载 的对象就可以了。如果数据不存在,则返回null
* 执行此方法时立即发出查询SQL语句。加载User对象。
*/
User user = (User)session.get(User.class, 1);
//数据加载完后的状态为persistent状态。数据将与数据库同步。
System.out.println("user.name=" + user.getName());
//因为此的user为persistent状态,所以数据库进行同步为龙哥。
user.setName("龙哥");
session.getTransaction().commit();
} catch (HibernateException e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally{
if (session != null){
if (session.isOpen()){
session.close();
}
}
5、load()与get()区别
不存在对应记录时表现不一样;
load返回的是代理对象,等到真正使用对象的内容时才发出sql语句,这样就要求在第一次使用对象时,要求session处于open状态,否则出错
get直接从数据库加载,不会延迟加载
get()和load()只根据主键查询,不能根据其它字段查询,如果想根据非主键查询,可以使用HQL
6、update()
用来更新detached对象,更新完成后转为为persistent状态(默认更新全部字段)
更新transient对象会报错(没有ID)
更新自己设定ID的transient对象可以(默认更新全部字段)
persistent状态的对象,只要设定字段不同的值,在session提交时,会自动更新(默认更新全部字段)
更新部分更新的字段(更改了哪个字段就更新哪个字段的内容)
方法1:update/updatable属性
xml:设定<property>标签的update属性,设置在更新时是否参数更新
<property name="name" update="false"/>
注意:update可取值为true(默认):参与更新;false:更新时不参与更新
annotateon:设定@Column的updatable属性值,true参与更新,false:不参与更新
@Column(updatable=false)
public String getTitle() {return title;}
注意:此种方法很少用,因为它不灵活
方法二:dynamic-update属性
注意:此方法目前只适合xml方式,JAP1.0 annotation没有对应的
在实体类的映射文件中的<class>标签中,使用dynamic-update属性,true:表示修改了哪个字段就更新哪个字段,其它字段不更新,但要求是同一个session(不能跨session),如果跨了session同样会更新所有的字段内容。
<class name="com.bjsxt.Student" dynamic-update="true">
代码:
@Test
public void testUpdate5() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Student s = (Student)session.get(Student.class, 1);
s.setName("zhangsan5");
//提交时,会只更新name字段,因为此时的s为persistent状态
session.getTransaction().commit();
s.setName("z4");
Session session2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
//更新时,会更新所有的字段,因为此时的s不是persistent状态
session2.update(s);
session2.getTransaction().commit();}
如果需要跨session实现更新修改的部分字段,需要使用session.merget()方法,合并字段内容
@Test
public void testUpdate6() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Student s = (Student)session.get(Student.class, 1);
s.setName("zhangsan6");
session.getTransaction().commit();
s.setName("z4");
Session session2 = sessionFactory.getCurrentSession();
session2.beginTransaction();
session2.merge(s);
session2.getTransaction().commit()}
这样虽然可以实现部分字段更新,但这样会多出一条select语句,因为在字段数据合并时,需要比较字段内容是否已变化,就需要从数据库中取出这条记录进行比较
使用HQL(EJBQL)面向对象的查询语言(建议)
@Test
public void testUpdate7() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query q = session.createQuery(
"update Student s set s.name='z5' where s.id = 1");
q.executeUpdate();
session.getTransaction().commit();
}
7、saveOrUpdate()
在执行的时候hibernate会检查,如果对象在数据库中已经有对应的记录(是指主键),则会更新update,否则会添加数据save
8、clear()
清除session缓存
无论是load还是get,都会首先查找缓存(一级缓存,也叫session级缓存),如果没有,才会去数据库查找,调用clear()方法可以强制清除session缓存
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Teacher t = (Teacher)session.load(Teacher.class, 1);
System.out.println(t.getName());
session.clear();
Teacher t2 = (Teacher)session.load(Teacher.class, 1);
System.out.println(t2.getName());
session.getTransaction().commit();
注意:这样就会发出两条SELECT语句,如果把session.clear()去除,则只会发出一条SELECT语句,因为第二次load时,是使用session缓存中ID为1的对象,而这个对象已经在第一次load到缓存中 了。
9、flush()
在hibernate中也存在flush这个功能,在默认的情况下session.commit()之前时,其实执行了一个flush命令。
Session.flush功能:
清理缓存;
执行sql(确定是执行SQL语句(确定生成update、insert、delete语句等),然后执行SQL语句。)
Session在什么情况下执行flush:
默认在事务提交时执行;
注意:flush时,可以自己设定,使用session.setFlushMode(FlushMode)来指定。
<pre name="code" class="java" session.setFlushMode(FlushMode);
FlushMode的枚举值:
FlushMode.ALWAYS:任务一条SQL语句,都会flush一次
FlushMode.AUTO :自动flush(默认)
FlushMode.COMMIT: 只有在commit时才flush
FlushMode.MANUAL:手动flush。
FlushMode.NEVER :永远不flush 此选项在性能优化时可能用,比如session取数据为只读时用,这样就不需要与数据库同步了
注意:设置flush模式时,需要在session开启事务之前设置。
可以显示的调用flush;
在执行查询前,如:iterate.
注:如果主键生成策略是uuid等不是由数据库生成的,则session.save()时并不会发出SQL语句,只有flush时才会发出SQL语句,但如果主键生成策略是native由数据库生成的,则session.save的同时就发出SQL语句。
10、evict()
例如:session.evict(user)
作用:从session缓存(EntityEntries属性)中逐出该对象
但是与commit同时使用,会抛出异常
session = HibernateUtils.getSession();
tx = session.beginTransaction();
User1 user = new User1();
user.setName("李四");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
//利用Hibernate将实体类对象保存到数据库中,因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理,不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false
session.save(user);
session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象
//无法成功提交,因为hibernate在清理缓存时,在session的临时集合(insertions)中取出user对象进行insert操作后需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session中逐出了,所以找不到相关数据,无法更新,抛出异常。
tx.commit();
解决在逐出session缓存中的对象不抛出异常的方法:
//在session.evict()之前进行显示的调用session.flush()方法就可以了。
session.save(user);
//flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象清除,并且会设置session中的existsInDatabase状态为false
session.flush();
session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象
//可以成功提交,因为hibernate在清理缓存时,在Session的insertions中集合中无法找到user对象所以不会发出insert语句,也不会更新session中existsInDatabase的状态。
tx.commit();
5.4 Transaction接口
Transaction tx = null;
try{
tx = session.beginTransaction();
session.save(obj);
tx.commit();
}catch(HibernateException e){
if(tx != null){
tx.rollback();
}
throw e;
}finally{
if(session != null){
session.close();
}
}
}
分享到:
相关推荐
这篇文档和学习笔记将深入介绍Hibernate的核心概念、API用法以及最佳实践。 1. **Hibernate核心概念** - **对象关系映射(ORM)**: Hibernate是ORM的一种实现,它允许开发者使用面向对象的方式来操作数据库,而...
**Hibernate API 使用指南** `Hibernate 中文API文档.chm`提供了详尽的API参考,包括以下关键接口和类: 1. `SessionFactory`: 创建和管理Session的工厂类。 2. `Session`: 数据库会话,执行CRUD操作的主要接口。 ...
总结起来,Hibernate中文API开发文档提供了详尽的指导,涵盖了从配置、实体映射到查询和事务处理的所有关键知识点,对于理解和使用Hibernate进行Java Web开发具有极大的帮助。通过深入学习和实践,开发者可以充分...
**Hibernate3.2 API** 是Hibernate框架的第三个主要版本的API文档,中文版的出现旨在方便中国开发者理解和使用。这个版本引入了许多新特性和改进,以提高性能、稳定性和易用性。以下是对Hibernate3.2 API中关键知识...
在这个"hibernate-3.2API.zip"压缩包中,包含的是Hibernate 3.2版本的API文档和可能的示例代码,这对于理解和使用Hibernate 3.2具有重要的参考价值。 1. **对象关系映射(ORM)**:Hibernate的核心功能是通过ORM...
本资源包含Hibernate 3.3.2 GA版本的中文参考手册和英文API文档,对于学习和使用Hibernate具有极大的帮助。 中文参考手册详细阐述了Hibernate的核心概念和用法,包括以下主要知识点: 1. **实体映射**:Hibernate...
《Hibernate 3.6.10 Final 官方文档》是Java开发中极其重要的参考资料,它详尽地阐述了Hibernate框架在3.6.10版本中的各项功能、配置和使用方法。Hibernate作为一款强大的对象关系映射(ORM)工具,能够帮助开发者将...
10. **缓存机制**:介绍Hibernate的缓存策略,包括一级缓存和二级缓存,以及第三方缓存集成,如Ehcache和Infinispan的使用。 11. **性能优化**:讲解如何通过优化查询、延迟加载、缓存策略等手段提高Hibernate应用...
2. **Hibernate核心组件**:Hibernate3的核心组件包括`hibernate-core.jar`,这个包包含了Hibernate的主要API,如SessionFactory、Session、Query等。它提供了对实体对象的管理、事务处理、缓存管理等功能。 3. **...
通过学习《精通Hibernate》这本书,读者可以深入了解Hibernate的这些核心概念,并掌握如何在实际项目中有效地使用Hibernate进行数据库操作,提升Web应用的开发效率。在阅读过程中,应重点关注实例代码,理解其背后的...
5. HQL(Hibernate Query Language): - Hibernate的面向对象查询语言,类似于SQL,但更贴近于Java对象。 - HQL支持聚合函数、分组、子查询等复杂查询。 6. Criteria API: - 提供了一种更加面向对象的方式来...
1. Hibernate核心概念: - Session:是Hibernate的主要工作单元,它提供了与数据库交互的接口,负责对象的创建、更新、删除和查询。 - Transaction:处理数据库的事务,确保数据的一致性。 - Query:提供SQL语句...
1. **对象关系映射(ORM)**: Hibernate的核心功能是将Java对象与数据库表之间建立映射关系,使得开发者可以使用对象的方式来操作数据库,而无需直接编写SQL语句。 2. **配置Hibernate**: 包括设置数据库连接信息...
5. **HQL(Hibernate Query Language)**:HQL是Hibernate提供的面向对象的查询语言,类似于SQL,但操作的是对象和对象集合。它可以更直观地进行对象查询,减少对SQL的依赖。 6. **Criteria查询**:Criteria API是...
5. **Criteria查询**和**HQL**:Hibernate提供了两种查询语言,一种是面向对象的Criteria API,另一种是面向SQL的Hibernate Query Language (HQL)。两者都能实现对数据库的查询,但HQL更接近SQL,而Criteria API更加...
5. **缓存策略**: Hibernate提供了二级缓存机制,可以集成第三方缓存提供商如Ehcache,提高应用程序的性能。同时,它还支持查询缓存,将查询结果缓存起来,避免重复执行相同的SQL语句。 6. **实体生命周期**: ...
会话工厂(SessionFactory)是Hibernate的核心组件,用于创建会话(Session)。会话是与数据库交互的接口,提供了增删改查(CRUD)操作。会话工厂通常在应用启动时创建,会话在需要操作数据库时打开,并在操作完成后...
1. **对象关系映射(ORM)**:Hibernate的核心功能是将Java对象映射到数据库中的表,使得开发人员可以使用对象而非SQL语句来操作数据。它提供了一种灵活的方式,使得数据库操作与业务逻辑分离,提高了代码的可读性...
它消除了 SQL 语句的编写,转而使用 HQL(Hibernate 查询语言)或 Criteria API 进行数据检索。 2. **配置**:文档会详细介绍如何配置 Hibernate,包括 hibernate.cfg.xml 文件的设置,如数据库连接参数、JDBC 驱动...
5. **事务(Transaction)**:Hibernate支持JTA(Java Transaction API)和JDBC事务管理,确保数据操作的原子性和一致性。 6. **查询语言(HQL)**:Hibernate提供了自己的查询语言,类似于SQL,但面向对象,可以...