`
neeleon
  • 浏览: 183450 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

hibernate入门(十二)一些细节问题分析

阅读更多

1. 实体配置文件中的类型问题

在前面的多个实例中配置<property> 映射类型时,我们都采取的是hibernate 默认的配置,即是说没有在<property> 中配置type 属性:其实基本类型一般不需要映射文件中配置,只有在一个java 类型与多个数据库类型相对应时,交且我们不希望使用默认的配置才会用type 来指明类型。 举例:java.util.Date 与数据库中的DATETIMEDATETIME,TIMESTAMP 相对应,如果我们不希望映射成默认的DATATIME, 而想映成DATE ,便配置成type=DATE”, 另需要说明的是我们也可配置成我们自定义的类型,但前提是我们自定义的类型必须实现 org.hibernate.UserType org.hibernate.CompositeUserType 中的任何一个接口。且在配置时指定类的完整名

2.Session SessionFactory

Session 是非线程安全的,生命周期较短,代表一个数据库的连接,在B/S 系统中一般不会超过一个请求,内部维护一级缓存和数据库连接。通常一个Session 的生成也就意味着即将结束。

SessionFactory 是线程安全的,一个数据库对应一个SessionFactoy, 一般会在整个系统生命周期内有效:SessionFactory 保存着和数据库连接相关的信息(user,password,url) 和映射信息,以及hibernate 运行时用到的一些信息。

3.Session 中的flush 方法

此方法的作用是将一级缓存与数据库同步,通常在查询数据或者是提交前( 可能会采取批量更新的方式到数据库) 会实现同步,这样可有效保证一级缓存中的数据是有效的数据。这个方法是由hibernate 自身来维护调用的,因为它的调用意味着与数据库交互,所以不建议我们手工调用,而事实上hibernate 对它的调用主要是为了提升性能和保证数据的有效性且hibernate 自身的对它的维护调用已近完美。

4. 巧用flush 解决内存溢出问题

当我们进行类似如下的操作时: for ( int i = 0; i < 10000000; i++) s.save(obj); i 足大到我们的内存不足以承受时,便会出现内存溢出问题,对于此可以这样解决:

for ( int i = 0; i < 10000000; i++) {

    s.save(obj );

    if (i % 30 == 0) {

    s.flush();

    s.clear();

    }

} 分析 :当每保存30 个数据时,我们便清掉一级缓存中的内容,但是在清掉内容前我们必须让一级缓存中的数据与数据库进行一次交互,这样可以保证数据能被保存到数据库中。 试想下,如果不flush, 那么在一级缓存中的数据是不能同步到数据库中的,所以这里flush 是非常重要得。 其实只要再来回忆前面所说的一级缓存中的一些知识,便可以发现如果保存的对象的主键是以 increme 的方式生成的,可以不用flush 也能实现数据及时同步到数据库中

5. StatelessSession 接口解决批量更新问题:

在进行如上的批量操作时,我们通过flush 来解决和数据库的同步更新,但是这样会造成缓存的不断更新,因此在进行类似的批量操作时,我们通常会选择使用StatelessSession 接口来代替Session ,由于这种无状态的Session 具有以下特点:它不和一级缓存、二级缓存交互,也不触发任何事件,监听器,拦截器,通过该接口能把这些批量更新直接发送到数据库。说明:StatelessSession 的方法也Session 的方法相似。 除了此方法外,我们使用Query.executeUpdate (), 也可以执行批量更新,但是此方法会清除相关联的类的二级缓存,也可能造成级联,甚至是和乐观锁不相容。

6. 离线查询DetachedCriteria:

package com.asm.hibernate.test;

public class DetachedCriteriaTest {

    public static void main(String[] args) {

       add ();

        DetachedCriteria dec = DetachedCriteria.forClass (User. class );

       String name = "jack" ;

       dec.add(Restrictions.eq ( "name" , name));

       List<User> list = detaCri (dec);

       for (User u : list)

           System. out .println(u);

    }

    static List detaCri(DetachedCriteria dec) {

       Session s = HibernateUtil.getSession ();

       Criteria cr = dec.getExecutableCriteria(s);

       List list = cr.list();

       s.close();

       return list;

    }

 

    static void add() {

       ... 省略内容:主要作用是在数据库中插入两条名为“ jack ”的记录,以使查询操作可以进行。

    }

}

分析 为会么要使用这种离线查询,比如我们可以在业务逻辑层构造出一个DetachedCriteria 对象,且它不会依赖于Session ,这样当们把这个对象作为参数来传递给M 的方法时便可以实现连库查询。这样可以有效的使用Session ,避免与数据库的频繁交互。

7. 监听器的使用:

下面首通过一个简单的例子来说明此问题:

>> 步骤一、编写监听类:

package com.asm.hibernate.event;

public class SaveUserListener implements SaveOrUpdateEventListener {

    public void onSaveOrUpdate(SaveOrUpdateEvent event)

           throws HibernateException {

       if (event.getObject() instanceof com.asm.hibernate.domain.User) {

           User user = (User) event.getObject();

           System. out .println( "find save User:" + user.getName());

           user.setDate( new Date());

       }

    }

}

分析:当有保存/ 更新事件发生时,便被此监听类监听到,而我们处理的只是保存/ 更新User 对象,即是说当发生保存/ 更新一个User 对象时,才会被这个监听器监听操作;其它对象的保存/ 更新操作尽管也会被它监听,但不会有处理动作。

>> 步骤二、编写测试类:

package com.asm.hibernate.event;

public class TestListener {

    public static void main(String[] args) {

       addUser ();

    }

    static void addUser() {

       Session s = null ;

       Transaction tx = null ;

       try {

           User u = new User();

           u.setName( "jack" );

           s = HibernateUtil.getSession ();

           tx = s.beginTransaction();

           s.save(u);

           tx.commit();

       } finally {

           if (s != null )

              s.close();

       }

    }

}      分析 :执行后,发现没有任何作用。原因是未配置监听器,联想到gui 程序监听时,总会在程序中给出相应的代码,而这里我们只需要在主配置文件中配置这个监听器,在由hibernate 把这个监听器写成代码到程序中去。在主配置文件中配置的内容如下

< event type = "save" >

           < listener class = "com.asm.hibernate.event.SaveUserListener" />

</ event >

这样配置后,尽管监听器类中的方法能实现,但是发现这些数据没有保存到数据库中。因为当们配置一监听器时,相对应的默认监听器就失效了,即是说 org.hibernate.event.def.DefaultSaveOrUpdateEventListener 这个默认的监听器不起作用了,为了能继续使用默认的监听器,应再配置上这个监听器,即配置成这样:

< event type = "save" >

< listener class = "com.asm.hibernate.event.SaveUserListener" />

< listener class = "org.hibernate.event.def.DefaultSaveOrUpdateEventListener" />

</ event >

这样配置后,即可以让我们自己的监听器生效,又可以让默认监听器起作用。

8. 使用原始的sql 查询:

代码如下:

package com.asm.hibernate.test;

public class JdbcSqlSelectTest {

    public static void main(String[] args) {

       addUsers ();

       query ();

    }

    static void query() {

       Session s = HibernateUtil.getSession ();

       Query q = s.createSQLQuery( "select * from user" ).addEntity(User. class );

       List<User> rs = q.list();

       for (User u : rs) {

           System. out .println( "Result " +u.getName() + "---" + u.getDate());

       }

    }

    static void addUsers() {

       ... 增加一些记录,以检验查询

    }  

}    分析: 关键是看查询方法:中间用到的查询语句from user,user 是指表名,后面增加addEntity 方法的主要是了了保证返回的list 对象中保存的User, 这样方便foreach 遍历。 需要说明的是尽管hibernate 支持这种sql 查询,但是它不具有通用性,即是说我们在写这些查询语句时总会依赖于一个具体的数据库,一旦换了数据库就可能出现问题,因此最好不要使用这种JdbcSql 查询。

9. 命名查询:

>> 步骤一:在User 的实体配置文件 </ hibernate-mapping > 的元素下增加如下内容:

< query name = "selectUserbyId" >

       <![CDATA[ from User where id=:id ]]>

</ query >

>> 步骤二、编写测试:

static List namedQuery( int id) {

       Session s = HibernateUtil.getSession ();

       Query q = s.getNamedQuery( "selectUserbyId" );

       //Query q=s.getNamedQuery("com.asm.hibernate.domain.User.selectUserbyIdTheSecond");

       q.setInteger( "id" , id);

       return q.list();

    }   

说明 这种方式虽然简单,但是容易在整个系统中引起重名,所以最好的方式是在Use 的实体配置文件的<class> 元素下配置这个属性,比如我们在<class> 元素的最后增加如下内容:

< query name = "selectUserbyIdTheSecond" >

           <![CDATA[ from User where id=:id ]]>

</ query > 则在上面的代码中要想用到这个命名查询,则应写成注释掉的代码那样。如果项目中的命名查询不多,建议写在 </ hibernate-mapping > 元素下,这样引用较方便。

补充说明 :我们也可以配置SQl 的命名查询,步骤是先在 </ hibernate-mapping > 元素下配置如下内容:

< sql-query name = "selectUserSql" >

   

分享到:
评论

相关推荐

    02_传智播客hibernate教程_hibernate入门案例的细节分析

    【标题】:“02_传智播客hibernate教程_hibernate入门案例的细节分析” 在本教程中,我们将深入探讨Hibernate,一个流行的Java对象关系映射(ORM)框架,它简化了数据库操作,使开发者可以更加专注于业务逻辑而不是...

    Hibernate入门教程.pdf

    ### Hibernate入门教程知识点详解 #### 一、Hibernate框架简介 **Hibernate** 是一款开放源代码的**对象关系映射(Object-Relational Mapping,简称ORM)**框架,它为Java应用提供了一种高效的机制,用于处理Java...

    传智播客李勇hibernate源码1-20课

    02_hibernate入门案例的细节分析; 03_hibernate入门案例的代码优化; 04_Session接口及get|load|persist方法 05_实体对象的三种状态与saveOrUpdate方法 06_完善HibernateUtil类及hql查询入门 07_实体类或属性名...

    hibernate入门课件--introduce hibernate.pdf

    ### Hibernate入门知识点详解 #### 一、概述 在IT领域,特别是软件开发中,数据库与对象之间的交互一直是项目中的核心部分。为了更好地处理这一过程,众多框架和技术应运而生,其中Hibernate作为一款优秀的对象...

    03_传智播客hibernate教程_hibernate入门案例的代码优化

    "03_传智播客hibernate教程_hibernate入门案例的代码优化"主要关注如何通过优化Hibernate代码来提高应用程序的性能和效率。以下是关于Hibernate的一些关键知识点: 1. **Hibernate简介**:Hibernate是Java平台上的...

    hibernate入门文档

    ### Hibernate入门精要 #### Hibernate概述 Hibernate是一个开放源代码的ORM(Object Relational Mapping)框架,用于Java应用中实现数据库操作。它提供了一个高级的数据持久化层,简化了对象和关系型数据库之间的...

    jsp Hibernate入门教程第1 3页.docx

    ### jsp Hibernate 入门教程知识点详解 #### 一、Hibernate 概述 Hibernate 是一款开源的对象关系映射(Object Relational Mapping, ORM)框架,它简化了 Java 应用程序与数据库之间的交互过程。通过 Hibernate,...

    hibernate介绍与动手入门体验

    接下来,我们来看看一个简单的Hibernate入门案例,并对其进行详细分析。 ##### DomainObject限制 - **必需要有一个无参构造函数**:这是因为Hibernate在实例化对象时需要使用默认构造器。 - **有无意义的标示符id...

    hibernate实战 英文版

    ### Hibernate实战知识点解析 #### 一、书籍简介与评价概览 《Hibernate实战》是一部备受赞誉的关于Hibernate框架的专业书籍,被广泛认为是最权威的Hibernate著作之一。该书由Hibernate项目的核心开发者撰写,因此...

    hibernate3.2之helloword

    【标题】"Hibernate3.2之HelloWorld"是关于Java持久化框架Hibernate的一个入门教程,主要针对的是Hibernate3.2版本。在这个版本中,Hibernate引入了一些改进和优化,旨在提高性能和开发效率,同时保持其作为对象关系...

    struts2.0 spring2.0 hibernate3.0整合开发快速入门-3

    ### Struts2.0、Spring2.0与Hibernate3.0整合开发快速入门知识点解析 #### 一、Struts2.0与Hibernate3.0整合基础 **知识点1:Struts2.0简介** - **定义**: Struts2是Apache基金会下的一个开源项目,它是一个基于...

    Apress - Pro Hibernate3

    - **初级Java开发者**:对于刚接触Java或Hibernate的新手来说,《Pro Hibernate3》是一本很好的入门书籍。 - **中级开发者**:希望通过深入学习来提高自己在Hibernate方面的技能。 - **高级开发者**:寻求更深层次的...

    Hibernate开发指南___夏昕

    夏昕老师以其深入浅出的讲解风格,确保即使是编程新手也能轻松理解Hibernate的核心概念和技术细节,从而顺利上手。 #### 标签解析:“Hibernate 夏昕 开发指南” 标签进一步明确了书籍的主题和作者,同时也揭示了...

    Hibernate视频教程免费下载

    通过以上对Hibernate视频教程的知识点详细介绍,可以帮助读者更全面地理解Hibernate框架的核心概念和技术细节,并掌握如何在实际项目中应用这些技术。希望本篇总结能够为学习Hibernate的朋友提供有价值的参考。

    hibernate 3.2中文手册 中文文档

    #### 第1章:Hibernate入门 - **1.1 前言** - 介绍了Hibernate的基本概念及其重要性。 - 强调了学习Hibernate对于Java开发人员的重要性。 - **1.2 第一部分—第一个Hibernate应用程序** - **1.2.1 第一个Class*...

    hibernate quickly

    《Hibernate 快速入门》源码解析 在Java开发领域,Hibernate作为一个强大的对象关系映射(ORM)框架,极大地简化了数据库操作。本资源提供的"hibernate quickly"源码,旨在帮助开发者快速掌握Hibernate的核心概念和...

    夏昕《Hibernate开发指南》V3.0.4

    本书《Hibernate 开发指南》版本 V3.0.4 作为入门级的经典书籍,深入浅出地介绍了 Hibernate 的核心概念和技术细节。 #### 二、Hibernate的核心特性 1. **ORM 映射**:Hibernate 支持多种映射策略,包括一对一...

    hibernate框架源码

    当你下载并解压"hibernate框架源码",你将有机会深入到Hibernate的核心机制中,了解其实现的细节。例如,你可以看到Hibernate如何通过Session接口处理数据库交互,怎样使用Criteria API或HQL(Hibernate Query ...

    Hibernate源代码等相关资料

    **Hibernate 源代码分析与学习指南** Hibernate 是一个开源的对象关系映射(ORM)框架,它极大地简化了 Java 应用程序与数据库之间的交互。本文将深入探讨 Hibernate 源代码,帮助初学者理解其核心概念,并提供相关...

Global site tag (gtag.js) - Google Analytics