- 浏览: 662264 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
HkEndless:
不好意思,请问这确定是回调机制吗。你的例子中只是将接口的实现类 ...
Spring CallBack回调机制介绍 -
hanmiao:
写的真乱啊,完全不知所云...
Java如何调用可执行文件和批处理命令 -
junia_1:
junia_1 写道 shock: ...
为什么要使用EJB -
junia_1:
shock:
为什么要使用EJB -
coollifer:
不错
SQL Server数据导入到Oracle中的方法
Loading Entities with Hibernate
In an earlier tutorial, we looked at the hypothetical example where you had the primary key of an entity, and wanted to query the database and have Hibernate return the unique User instance associated with that primary key. The Haitian Voodoo required to perform that retrieval task looked something like this:
public static User retrieveFromId(int idValue) { AnnotationConfiguration config = new AnnotationConfiguration(); config.addAnnotatedClass(User.class); SessionFactory factory; factory = config.configure().buildSessionFactory(); Session session = factory.getCurrentSession(); session.beginTransaction(); String queryString = "from User where id = :id"; Query query = session.createQuery(queryString); query.setInteger("id", idValue); Object queryResult = query.uniqueResult(); User user = (User)queryResult; session.getTransaction().commit(); System.out.print(user.getPassword()); return user; }
Taking a primary key, and using it to demonstrate variable injection and the retrieval of a unique entity was very androgologically sound, but the fact of the matter is, if you actually have the primary key of an entity, there is a much easier, or should I say "a couple of much easier ways" to retrieve the corresponding entity from the database. We'll demonstrate those ways by coding a few methods into a new class called the LoadRunner .
The LoadRunner Class
The LoadRunner class is going to have a runnable main method, and two static methods, named callGet and callLoad, which will be used to demonstrate the two different ways you can get at an entity given its associated primary key. For now, I've coded in all the redundant code we need to have each method connect to the database, create a session, and start a transaction. I know that all of this Hibernate plumbing code is getting repetitive; we'll factor it out into a HibernateUtil class soon enough.
package com.examscam; import org.hibernate.*;
import com.examscam.model.User; import org.hibernate.cfg.AnnotationConfiguration; public class LoadRunner { public static void callLoad(){ AnnotationConfiguration config = new AnnotationConfiguration(); config.addAnnotatedClass(User.class); SessionFactory factory= config.configure().buildSessionFactory(); Session session = factory.getCurrentSession(); session.beginTransaction(); /***** load code will go here *****/ session.getTransaction().commit(); } public static void callGet() { AnnotationConfiguration config = new AnnotationConfiguration(); config.addAnnotatedClass(User.class); SessionFactory factory= config.configure().buildSessionFactory(); Session session = factory.getCurrentSession(); session.beginTransaction(); /***** get code will go here *****/ session.getTransaction().commit(); } public static void main(String[] args) { LoadRunner.callLoad(); LoadRunner.callGet(); } }
The callGet Method
Within the session.beginTransaction() and the session.getTransaction().commit methods, we want to use the Hibernate Session to take a given primary key, and provide our program with the entity associated with that primary key in the database. It's all a pretty simple process. To get an entity from the underlying persistence store, all you have to do is call the Hibernate Session's get method, and provide two arguments: the Java class associated with the entity that your are retrieving, which in this case would be the User.class , and the actual primary key associated with the record. I know that I have a user in the database with a primary key of 1, so the number one will be used to test my methods.
Here's all the code you need to resurrect a User instance from the database using the Hibernate Session's load method:
session.beginTransaction(); User user = (User)session.get(User.class, new Long(1)); System.out.println(user.getPassword()); session.getTransaction().commit();
And that's about it! You simply call the load method of the Hibernate Session, provide the class type and the primary key as parameters, and then cast the object that is returned from Hibernate back into the appropriate Java type. From there, you can do just about anything with your JavaBean that you want. In this case, I simply print out the password of the User instance. It's all just so easy.
Now, as I mentioned, there are two ways to pull an entity from the database, one of which is to use the get method of the Hibernate Session, and the other way is to use the load method. Compare and contrast the following code snippet that invokes the Session's load method to the code snippet that invoked the Session's get method. The difference is subtle, to say the least.
session.beginTransaction(); User user = (User)session.load(User.class, new Long(1)); System.out.println(user.getPassword()); session.getTransaction().commit();
Hibernate load vs. Hibernate get Methods
Well, if you were to compare the load and get methods of the Hibernate Session, you'd think that they looked pretty darned similar; and you'd be correct, but there are subtle and very important differences.
First of all, the get method hits the database as soon as it is called. So, using the Hibernate Session's get method will always trigger a database hit. On the other hand, the load method only hits the database when a particular field of the entity is accessed. So, if we use the load method to retrieve an entity, but we never actually access any of the fields of that entity, we never actually hit the database. Pretty kewl, eh?
Well, actually, as kewl as the load method might sound, it actually triggers more problems than it solves, and here's why. If you initialize a JavaBean instance with a load method call, you can only access the properties of that JavaBean, for the first time, within the transactional context in which it was initialized. If you try to access the various properties of the JavaBean after the transaction that loaded it has been committed, you'll get an exception, a LazyInitializationException, as Hibernate no longer has a valid transactional context to use to hit the database.
So, while this code will work just fine?..
session.beginTransaction(); User user=(User)session.load(User.class, new Long(1)); System.out.println(user.getPassword()); session.getTransaction().commit();
.. this code will fail ?..
session.beginTransaction(); User user=(User)session.load(User.class, new Long(1)); session.getTransaction().commit(); System.out.println(user.getPassword());
.. and generate the following er ror , telling you that since the transaction was committed, there was no valid Session in which a read transaction against the database could be issued:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
So, the big thing to take away from this is that with the load method, you can't really use your loaded JavaBeans after the transaction has been committed, whereas, with the get method you can, because all of the various properties of a JavaBean retrieved through the get method are initialized right away.
Loading Non-Existent Records
An important scenario under which you need to contrast the load and get methods of the Hibernate Session has to do with what happens when you provide a primary key that doesn't actually exist in the database. Well, with the get method, you are simply returned a null object, which is no big deal.
With the load method, there's also no initial problem when you provide an invalid primary key to the method. From what you can tell, Hibernate appears to hand you back a valid, non-null instance of the class in which you are interested. However, the problems start when you actually try to access a property of that instance - that's where you run into trouble.
Remember how I said the load method doesn't hit the database until a property of the bean is requested? Well, if you've provided a primary key that doesn't exist in your database to the load method, when it does go to the database for the first time, it won't be able to find the non-existent, associated record, and your code will cough up big time. In fact, looking up a field based upon a non-existent primary key with the Hibernate Session's load method triggers the following error:
org.hibernate.ObjectNotFoundException:
No row with the given identifier exists: [User#123]
public Object get (Class clazz,
Serializable id) throws HibernateException
--Return the persistent instance of the given entity class with the
given identifier, or null if there is no such persistent instance. (If
the instance is already associated with the session, return that
instance or proxy.)
public Object load (Class
theClass,Serializable id) throws HibernateException
--Return the persistent instance of the given entity class with the
given identifier, assuming that the instance exists. You should not
use this method to determine if an instance exists (use get()
instead). Use this only to retrieve an instance that you assume
exists, where non-existence would be an actual error.
-Regurgitated Hibernate API JavaDoc
package com.examscam; import org.hibernate.*; import com.examscam.model.User; import org.hibernate.cfg.AnnotationConfiguration; public class LoadRunner { public static void main(String[] args) { LoadRunner.callLoad(); LoadRunner.callGet(); } public static void callLoad(){ AnnotationConfiguration config = new AnnotationConfiguration(); config.addAnnotatedClass(User.class); SessionFactory factory= config.configure().buildSessionFactory(); Session session = factory.getCurrentSession(); session.beginTransaction(); try { User user= (User)session.load(User.class,new Long(1)); System.out.println(user.getPassword ()); } catch (ObjectNotFoundException e) { e.printStackTrace(); } session.getTransaction().commit(); /* System.out.println(user.getPassword()); This would fail!!! */ } public static void callGet() { AnnotationConfiguration config = new AnnotationConfiguration(); config.addAnnotatedClass(User.class); SessionFactory factory= config.configure().buildSessionFactory(); Session session = factory.getCurrentSession(); session.beginTransaction(); User user= (User)session.get(User.class,new Long(1)); System.out.println(user.getPassword()); session.getTransaction().commit(); /* no problem!!!*/ System.out.println(user.getPassword ()); } }
When to use get? When to use load?
So, after comparing and contrasting the load and get methods, the natural question that arises is "when do I use the get, and when do I use loa d?" It's a good question.
For the most part, you'll probably use the get method most often in your code. If you ever want to use the JavaBean that you are retrieving from the database after the database transaction has been committed, you'll want to use the get method, and quite frankly, that tends to be most of the time. For example, if you load a User instance in a Servlet, and you want to pass that instance to a Java Server Page for display purposes, you'd need to use the get method, otherwise, you'd have a LazyInitializationException in your JSP.
On the other hand, if your goal is largely transactional, and you are only going to be accessing the JavaBean of interest within a single unit of work that will pretty much end once the transaction is committed, you'll want to use the load method. For that matter, if you want to ensure that the JavaBean of interest is completely in sync with the database when it is used, you'll want to be using the load method as well, as this will ensure the fields of the JavaBean are being loaded in from the database, and are not just being loaded from the memory of the Java Virtual Machine on which you are running.
Furthermore, the load method may be the method of choice if you know, and are absolutely sure, that the entity you are searching for exists in the database with the primary key you are providing. If you don't know for sure that an entity bearing your primary key exists in the database, you can use the get method, and check to see if the instance that gets returned from the method call returns null.
Hibernate's get and load methods tend to cause plenty of problems for new Hibernate developers. But with a good understanding of the differences between the two, you shouldn't have any problem avoiding LazyInitialization and ObjectNotFound Exceptions.
发表评论
-
hibernate Restrictions用法 MatchMode.ANYWHERE
2012-07-14 15:50 3983方法 说明 Res ... -
hibernate3 大批量更新/删除数据 (update/delete)
2011-11-10 12:15 1378Hibernate3.0 采用新的基 ... -
hibernate lazy(延迟加载)
2011-10-12 02:20 947hibernate lazy策略可以使用在: * < ... -
一些关于Hibernate延迟加载的误区
2011-09-12 23:13 902首先是第一个误区:延迟加载只能作用于关联实体 看到这个是 ... -
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling
2011-08-12 19:17 1254Hi I am facing a problem wit ... -
Criteria Condition: Match Mode End
2011-07-02 11:05 1016//////////////////////////// ... -
Criteria: Group By Criteria
2011-07-02 11:03 1361/////////////////////////////// ... -
Query Criteria Equal
2011-07-02 11:02 931/////////////////////////////// ... -
Criteria: Order
2011-07-02 10:59 807//////////////////////////// ... -
Criteria: Associations Sorting Criteria
2011-07-02 10:57 943//////////////////////////// ... -
hibernate的Query有没有setResultTransformer这个方法
2011-07-01 23:24 3123可以对原生SQL 查询使用ResultTransformer。 ... -
Hibernate中一级缓存、二级缓存及查询缓存的技术性总结
2011-06-21 17:31 1242一、 一级缓存 1. ... -
hibernate 保存 oracle 10g大数据字段
2011-06-14 04:01 1457Java代码 要点如下: ... -
Hibernate 错误原因总结
2011-06-14 00:10 14441、错误: object references an unsa ... -
MappingException提示Association references unmapped class错误的解决方法
2011-06-12 17:09 10出现如下错误信息时 Caused by: org.hibe ... -
Hibernate一对多关联映射的配置及其级联删除问题
2011-06-12 17:07 9首先举一个简单的一对多双向关联的配置: 一的一端:Quest ... -
Hibernate多对一关联映射原理、映射方法和数据的保存
2011-06-12 17:06 13Hibernate的多对一关联映射实现的基本原理就是: 在多 ... -
Hibernate一对多单向关联和双向关联映射方法及其优缺点
2011-06-12 17:05 11一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在 ... -
inverse = “true” example and explanation
2011-06-11 22:18 1135In Hibernate, only the “relatio ... -
ibatis和hibernate区别
2011-04-13 17:34 836ibatis:sql需要自己写 hibe ...
相关推荐
Application Centric Infrastructure ACI LiveLessons
matlab提取股票数据代码Comparing_humans_vs_DPGMM_zh_CN 模型 我准备了训练dpgmm模型的功能: 1如果只希望使用mfcc,则可以使用脚本'script_create_feature_file'(具有name_of_features_wanted = mfccs)从.wav...
“Analyzing and Comparing Montgomery Multiplication Algorithms”(分析与比较蒙哥马利模乘算法)这篇文章旨在深入探讨并对比不同的蒙哥马利模乘算法实现方法。蒙哥马利模乘算法是一种在计算机科学中广泛应用的...
下面将详细阐述哈希码(hashCode)和比较(Comparing)在Java中的作用以及它们在对象比较中的应用。 首先,哈希码是一个整数值,由对象的内部状态计算得出,通常用于快速查找。`hashCode()`方法是每个Java对象的...
在讨论低功耗无线技术时,本文将对比包括Bluetooth低功耗(BLE)、ANT、ANT+、ZigBee、ZigBee RF4CE、Wi-Fi、Nike+、IrDA和近场通信(NFC)标准在内的多种无线技术。首先,我们将详细解析每种技术的特性、优点以及在...
在内容部分中,提到的文章“Characterizing and Comparing Phylogenies from their Laplacian Spectrum”发表在系统生物学杂志(Systematic Biology)上,卷号为65,期号为3,页码范围495-507。文章是通过拉普拉斯谱...
标题 "JDBC_sorting_Comparing_" 暗示了这个主题是关于在Java环境中使用JDBC(Java Database Connectivity)进行数据排序,并且涉及到对象的`equals`和`hashCode`方法的重写。`equals`和`hashCode`方法是Java中的...
本文《Attention Flows:Analyzing and Comparing Attention Mechanisms in Language Models》是一篇研究论文,主要关注于深度学习领域内语言模型的注意力机制。随着自然语言处理(NLP)技术的发展,基于注意力机制...
CAN FD 传统CAN之比较 CAN-FD比CAN总线的带宽更高,具有与CAN总线相似的控制器接口,这种相似性使ECU供应商不需要对ECU的软件部分做大规模修改,降低了开发难度和成本。CAN-FD是CAN总线的升级换代设计,它继承了CAN...
Comparing Realism and Idealism as Classic Schools of Thought
2002年发表的论文《Comparing Linear Discriminant Analysis and Support Vector Machine》对比了这两种算法在分类任务中的表现和特点。由于文档内容是由OCR扫描技术处理,可能包含文字识别错误或遗漏。不过,我们仍...
Fixed comparing against disconnected mapped network drives to prompt for username/password and reconnect.
在IT行业中,数据库操作是应用开发的核心部分,而IBatis和Hibernate作为两个流行的ORM(对象关系映射)框架,极大地简化了数据访问层的开发。本文将深入探讨JQuery的启发,以及如何利用这些思想来优化对这两个框架的...
在探讨ORB和AKAZE两种特征提取算法的比较时,首先要了解这些算法在无人机视觉里程计中的应用背景。无人机(UAV)近年来发展迅速,在航空摄影、监测、娱乐等多个领域中都得到了广泛的应用。为了实现无人机的自主导航...
Technical+Presentation+Comparing+Citrix+XenApp+to+ThinApp.pdf
Comparing-KerasCV-YOLOv8-Models-on-the-Global-Wheat-Data
context.getRequest().setAttribute("blog", blog); // 将数据设置到请求范围内 return new ForwardResolution("/viewBlogEntries.jsp"); // 返回视图 } } ``` #### 代码详解 - **接口实现**:首先,该类实现了`...
Comparing financial systems (Franklin Allen, Douglas Gale) (z-lib.org).chm
在当今的IT行业中,电机技术作为自动化和驱动系统的核心要素,为现代科技提供了不可或缺的支持。尤其是在当前互联网飞速发展的时代背景下,电机技术的每一次进步都极大地推动了自动化、物联网(IoT)和工业4.0的向前...
标题中的“nslations as Manipulation and Rewriting- Comparing the Different Translations”涉及的是翻译研究的一个重要领域,即翻译的操纵与改写,并通过比较不同的翻译版本来探讨这一主题。这篇论文可能深入...