Hibernate 3.6 - session.get()vs session.load() [英] Hibernate 3.6 - session.get() vs session.load()

查看:88
本文介绍了Hibernate 3.6 - session.get()vs session.load()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解Hibernate 3.6 session.get() session.load()的返回对象和行为有什么区别。



javadoc


$ b

get():


返回给定实体类的持久化实例,给定标识符为
;如果没有这种持久化实例,则返回null。 (如果
实例已与会话关联,则返回该
实例。此方法永远不会返回未初始化的实例。)

load():


返回给定实体类的持久化实例,其中
给定的标识符,假设实例存在。这个方法可能
返回一个代理实例,当一个
非标识符方法被访问时,这个代理实例被按需初始化。


我有三个问题:


  1. javadoc在 load() / code>可能会返回一个代理 - 有什么办法可以提前知道它吗?

  2. 返回一个代理 - 这意味着 load()没有访问数据库,我正确吗?那么,如果我提供带有数据库中不存在的标识符的 load()呢?我现在将在会话中使用无效ID代理(无需获得例外)。现在我想让另一个持久实例指向那个代理 - 它会工作吗?对于这种情况,我不需要初始化代理,我只需要它的id(即使它是无效的,因为它不在数据库中)。所以我想我是问我的描述是否正确,我是否总是需要在 load()>返回的对象之后签出 isInitialized() 为了确保它代表一个有效的实体(或者至少一个有效的代理),即有一个有效的ID。
  3. 此外,如果 load()返回一个代理会发生什么 - 因此代理是已经与会话关联的实例。然后根据 get()的描述:如果实例已经与会话关联,则返回该实例。 - get()返回代理?由于根据 get()的描述:此方法永远不会返回未初始化的实例。


谢谢!

更新

(A)我认为 load()得到以下内容正确吗?

()在进入数据库之前首先会尝试检查会话缓存 - 所以不能说它们中的任何一个总是碰到数据库,或者总是返回一个代理。

(B)初始化的代理与原始实例不一样,你可以在这里阅读: http://blog.xebia.com/2008/03/08/advanced-hibernate-proxy-pitfalls/

解决方案

(1),(3):

你是对的。 load() get()将首先检查是否有一个实例PK坚持在会议中。

如果是,只需从会话中返回该实例即可。 (它可能是代理或实际的类实例)

如果不是, load()将创建并返回一个代理,而 get()将打到DB并返回实际实体类的实例。

返回的对象这两个方法都会被关联并在会话后继续存在。



因此,无论是 get()还是 load() return proxy或实际的实体类取决于您是使用get()还是load()来首次获取当前会话中相同PK的实例。



您可以通过执行以下测试来证明此行为:

 会话会话= HibernateUtil.getSessionFactory()。openSession(); 

Item loadItem =(Item)session.load(Item.class,1);
System.out.println(loadItem.getClass()。getName());

Item getItem =(Item)session.get(Item .class,1);
System.out.println(getItem .getClass()。getName());

如果它是一个代理,则打印的类名称将与实际的实体类名称不同。只需将执行顺序改为 load() get()以查看效果。


$ b

(2):

如果load()返回一个代理,它将不会在 load()。如果只访问除PK之外的映射属性,并且没有具有相同PK值的实例与会话关联,则代理将只访问DB。



在代理访问数据库之后,具有相同代理PK的实例将与该会话相关联。因此,当您再次从代理获取其他属性时,或者您使用 get()来获取同一个PK的实例,DB将不会被访问,因为可以从会话中找到值。



例如:

  / **会话开始*** / 
Item item = (Item)session.load(Item.class,new Long(1));
item.getId(); //不会访问DB,因为只有标识符属性访问
item.getDescription(); //访问数据库并初始化代理。在那之后,物品代理被称为初始化
item.getPrice(); //不会访问数据库,因为可以从会话中获取PK 1的项目
Item item2 = session.get(Item.class,new Long(1))//不会访问DB作为项目PK 1可以从会话中获得

如果 load()带有无效ID的实例,然后访问该代理上的属性或调用方法(例如 isInitialized()), ObjectNotFoundException 将被抛出。因此,如果您可以捕获 ObjectNotFoundException ,这意味着代理将加载一个无效的ID。



如果您想要确保该ID在运行时有效,应使用 get()并检查返回的实例是否为空。 load()在设置外键约束时很有用。请参阅


I am trying to understand what the difference is in returned object and behavior of Hibernate 3.6 session.get() and session.load().

From the javadoc:

get():

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. This method never returns an uninitialized instance.)

load():

Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists. This method might return a proxied instance that is initialized on-demand, when a non-identifier method is accessed.

I have three questions:

  1. The javadoc does not say when load() might return a proxy - is there any way to know it in advance?

  2. When load() returns a proxy - this means load() did not access the database, am I correct? Then what if I provided load() with an identifier that does not exist in the database? I will now have in the session a proxy with an invalid ID (without getting an Exception). Now I want to let another persistent instance point to that proxy - is it going to work? For this scenario I do not need to initialize the proxy, I only need its id (which I have even though its invalid since it's not in the database). So I guess I am asking if my description is correct, and do I always need to check out after load() the returned object with isInitialized() in order to make sure it represents a valid entity (or at least a valid proxy), i.e. with a valid ID.

  3. Also, what happens if load() returns a proxy - so the proxy is the instance that is already associated with the session. Then according to the description of get(): "If the instance is already associated with the session, return that instance." - so does get() return the proxy? Since according to the description of get(): "This method never returns an uninitialized instance."

Thanks!

UPDATE

Are the following correct?

(A) I think both load() and get() will first try to check the session cache before going to the DB - so it would not be right to say that any of them always hits the DB, or always returns a proxy.

(B) An initialized proxy is not the same as the original instance, as you can read here: http://blog.xebia.com/2008/03/08/advanced-hibernate-proxy-pitfalls/

解决方案

(1) , (3) :

Yes. You are right .Both the load() and get() will first check if there is an instance with the same PK is persisted in the session.

If yes , just returns that instance from the session. (It may be the proxy or the actual entity class instance)

If no , load() will create and return a proxy while get() will hit DB and returns instance of the actual entity class .

The returned object from both methods will be associated and persisted in the session afterwards.

So , whether get() or load() return proxy or the actual entity class depends on whether you use get() or load() to get the instance of the same PK in the current session for the first time.

You can proof this behaviour by performing the following test:

Session session = HibernateUtil.getSessionFactory().openSession();

Item loadItem= (Item ) session.load(Item.class, 1);
System.out.println(loadItem.getClass().getName());

Item getItem = (Item ) session.get(Item .class, 1);
System.out.println(getItem .getClass().getName());

If it is an proxy , the printed class name will not be the same as the actual entity class name. Just change the execution order of to load() and get() to see the effect.

(2):

If load() returns a proxy , it will not access the DB during load() .The proxy will only accesses the DB if their mapped properties besides the PK are accessed and there are no instances with the same PK value is associated with the session.

After the proxy accesses the DB , the instance with the same PK of the proxy will be associated with that session .So when you get another properties from the proxy again or you use get() to get the instance for the same PK , the DB will not be accessed as the values can be found from the session.

For example:

/**Session starts***/
Item item = (Item) session.load(Item.class, new Long(1));
item.getId();  //Will not access DB as only the identifier property is access
item.getDescription(); // access the DB and initialize the proxy . After that , the item proxy is said to be initialized
item.getPrice(); //will not access DB as the item with the PK 1 can be get from the session
Item item2 = session.get(Item.class, new Long(1)) //will not access DB as the item with the PK 1 can be get from the session

If you load() an instance with the invalid ID and then access the properties or call a method (such as isInitialized()) on this proxy , ObjectNotFoundException will be thrown. So if you can catch ObjectNotFoundException , it means a proxy is loaded with an invalid ID.

If you want to ensure the ID is valid during the runtime , you should use get() and check if the returned instance is null . load() is useful when setting the foreign key constraint. See this

这篇关于Hibernate 3.6 - session.get()vs session.load()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆