Hibernate 3.6-session.get()与session.load()的比较
我试图理解Hibernate 3.6的返回对象和行为的区别是什么Hibernate 3.6-session.get()与session.load()的比较,hibernate,jakarta-ee,orm,Hibernate,Jakarta Ee,Orm,我试图理解Hibernate 3.6的返回对象和行为的区别是什么session.get()和session.load() 从: get(): 返回给定实体类的持久实例 给定标识符,如果没有此类持久实例,则为null。(如果 实例已与会话关联,请返回 实例。此方法从不返回未初始化的实例。) load(): 返回给定实体类的持久实例 给定标识符,假设实例存在。这种方法可能会 当 访问非标识符方法 我有三个问题: javadoc没有说明何时load()可能会返回一个代理-有没有办法提前知道它 当loa
session.get()
和session.load()
从:
get():
返回给定实体类的持久实例
给定标识符,如果没有此类持久实例,则为null。(如果
实例已与会话关联,请返回
实例。此方法从不返回未初始化的实例。)
load():
返回给定实体类的持久实例
给定标识符,假设实例存在。这种方法可能会
当
访问非标识符方法
我有三个问题:
load()
可能会返回一个代理-有没有办法提前知道它load()
返回代理时-这意味着load()
没有访问数据库,对吗?那么,如果我为load()
提供了数据库中不存在的标识符,该怎么办?现在,我将在会话中使用一个ID无效的代理(不会出现异常)。现在,我想让另一个持久性实例指向该代理——它能工作吗?对于这个场景,我不需要初始化代理,我只需要它的id(虽然它不在数据库中,所以它无效,但我有id)。所以我想我是在问我的描述是否正确,我是否总是需要在load()
返回的对象isInitialized()
之后签出,以确保它代表一个有效的实体(或至少是一个有效的代理),即具有一个有效的IDload()
返回一个代理,那么会发生什么?因此,代理就是已经与会话关联的实例。然后根据get()
的描述:“如果实例已与会话关联,请返回该实例。”-那么get()
是否返回代理?因为根据get()
的描述:“此方法从不返回未初始化的实例。”load()
和get()
在进入数据库之前都会先检查会话缓存,所以说它们中的任何一个总是命中数据库,或者总是返回代理是不对的
(B) 初始化的代理与原始实例不同,您可以在此处阅读:(1)、(3):
对。你说得对。load()
和get()
将首先检查会话中是否存在具有相同PK的实例
如果是,则从会话返回该实例。(可能是代理或实际实体类实例)
如果否,load()
将创建并返回代理,而get()
将命中DB并返回实际实体类的实例
从这两个方法返回的对象将在以后的会话中关联并持久化
因此,是get()
还是load()
返回代理还是实际的实体类取决于您是使用get()还是load()首次在当前会话中获取相同PK的实例
您可以通过执行以下测试来证明此行为:
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());
如果是代理,打印的类名将与实际实体类名不同。只需将的执行顺序更改为load()
和get()
,即可查看效果
(2) :
如果load()返回一个代理,它将在load()
期间不访问数据库。只有在访问了数据库的PK以外的映射属性,并且没有与会话关联的PK值相同的实例时,代理才会访问数据库
代理访问DB后,具有相同代理PK的实例将与该会话关联。因此,当您再次从代理获取其他属性或使用get()
获取相同PK的实例时,将不会访问DB,因为可以从会话中找到值
例如:
/**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
如果load()
一个ID无效的实例,然后在此代理上访问属性或调用方法(如isInitialized()
),则将抛出ObjectNotFoundException
。因此,如果您可以捕获ObjectNotFoundException
,则表示代理加载了无效ID
如果要确保ID在运行时有效,应使用
get()
并检查返回的实例是否为null<代码>加载()在设置外键约束时非常有用。见1。但是如果我在会话中已经有一个初始化的实例(对于这个ID),它不会返回那个实例,而不是一个代理吗?另外,javadoc说:“这个方法可能会返回一个代理实例”——它没有说“这个方法将永远”。2.这是一种设计缺陷——因为根据你所说的,当我有一个代理时,我想确保它在DB中代表一个实际的ID(我总是想确保它——即使我只使用代理来指向它的其他实例)——那么我在初始化它之前无法知道我使用的ID是有效的,但是在这种情况下,为什么要使用代理呢?3。你是说load()
之后的get()
将返回一个初始化的代理,还是只返回一个初始化的实例?因为如果是后者,那么我们现在在会话中有两个具有相同ID的对象(代理和实例)。顺便说一句,我知道可能有两个代理代表相同的DB ID-正如您在这里看到的:在文本“第二,有可能破坏代理”下--请参阅我原始问题更新中的更多内容。是的。你说得对。你的问题帮助我澄清了一些错误