Hibernate 3.6 - session.get()vs session.load()

rap*_*apt 10 orm hibernate java-ee

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

来自javadoc:

得到():

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

加载():

假定实例存在,返回给定实体类的持久实例和给定标识符.当访问非标识符方法时,此方法可能会返回按需初始化的代理实例.

我有三个问题:

  1. javadoc没有说什么时候load()可能会返回一个代理 - 有没有办法提前知道它?

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

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

谢谢!

UPDATE

以下是否正确?

(A)我认为两者load()get()会首先尝试才去DB检查会话缓存-所以它不会是正确的说,任何人总是打DB或总是返回的代理.

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

Ken*_*han 19

(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());
Run Code Online (Sandbox Code Playgroud)

如果它是代理,则打印的类名称将与实际的实体类名称不同.只需更改to的执行顺序load()get()查看效果即可.

(2):

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

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

例如:

/**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
Run Code Online (Sandbox Code Playgroud)

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

如果要确保ID在运行时有效,则应使用get()并检查返回的实例是否为空.load()在设置外键约束时很有用.看到这个