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

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

问题描述

我试图了解 Hibernate 3.6 session.get()session.load() 的返回对象和行为的区别.

来自 javadoc:>

get():

<块引用>

返回给定实体类的持久化实例给定标识符,如果没有这样的持久实例,则为 null.(如果实例已经与会话关联,返回实例.此方法从不返回未初始化的实例.)

加载():

<块引用>

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

我有三个问题:

  1. javadoc 没有说明 load() 何时可能返回代理 - 有没有办法提前知道?

  2. load() 返回代理时 - 这意味着 load() 没有访问数据库,我说得对吗?那么如果我为 load() 提供了一个数据库中不存在的标识符呢?我现在将在会话中拥有一个具有无效 ID 的代理(不会出现异常).现在我想让另一个持久实例指向该代理 - 它会起作用吗?对于这种情况,我不需要初始化代理,我只需要它的 id(即使它无效,因为它不在数据库中,我也有).所以我想我是在问我的描述是否正确,我是否总是需要在 load() 之后使用 isInitialized() 检查返回的对象以确保它代表一个有效的实体(或至少是一个有效的代理),即具有有效的 ID.

  3. 此外,如果 load() 返回代理会发生什么 - 所以代理是已经与会话关联的实例.然后根据get()的描述:如果实例已经与会话关联,则返回该实例."- 那么 get() 会返回代理吗?由于根据 get() 的描述:此方法永远不会返回未初始化的实例."

谢谢!

更新

以下正确吗?

(A) 我认为 load()get() 都会在去数据库之前先尝试检查会话缓存 - 所以这是不对的说它们中的任何一个总是命中数据库,或者总是返回一个代理.

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

解决方案

(1) , (3) :

是的.你是对的.load()get() 都会首先检查会话中是否存在具有相同 PK 的实例.

如果是,则从会话中返回该实例.(可能是代理或实际的实体类实例)

如果没有,load() 将创建并返回一个代理,而 get() 将命中 DB 并返回实际实体类的实例.

这两个方法返回的对象将在之后的会话中关联并持久化.

所以,get()load() 返回代理还是实际的实体类取决于你是使用 get() 还是 load() 来获取实例第一次在当前会话中使用相同的 PK.

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

Session session = HibernateUtil.getSessionFactory().openSession();项目 loadItem= (项目) 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()就可以看到效果了.

(2):

如果 load() 返回一个代理,它不会在 load() 期间访问数据库.如果除了 PK 之外的映射属性被访问并且没有实例,代理才会访问数据库具有相同 PK 值的会话关联.

代理访问数据库后,与代理PK相同的实例将与该会话相关联.因此,当您再次从代理获取另一个属性或使用get()获取相同 PK 的实例,不会访问数据库,因为可以从会话中找到值.

例如:

/**会话开始***/Item item = (Item) session.load(Item.class, new Long(1));item.getId();//不会访问数据库,因为只有标识符属性是访问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() 并检查返回的实例是否为 null .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() 与 session.load()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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