如果从数据库加载两次,那么hibernate是否会加载同一实例的两个seprate副本? [英] Does hibernate load two seprate copies of same instance if they are loaded twice from database?

查看:161
本文介绍了如果从数据库加载两次,那么hibernate是否会加载同一实例的两个seprate副本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道关于懒惰负载的SO有很多不同的问题,但我的一个有点不同。



假设我有一个实体A,其中我有收集同样,在实体B中,我有A的集合。在这两种情况下,使用lazy =true选项。



实体A 的实例aA有 - > 设置< B> = ==(此集合包含实体B的实例bB)



实体B 的实例bB具有 - > 设置< ; A> ===(此集合包含实体A的实例aA)



现在,如果我加载实体A的集合(其中<$ c) $ c>设置< B> )。它现在已初始化,即完成A的aA实例,包括集合。我现在期望的是实体B的实例bB也被完全初始化但是没有,当我引用具有实体A的实例aA的实体B的集合时,它不会和我得到延迟初始化异常。



如果从数据库加载两次,那么hibernate是否会加载同一实例的两个seprate副本?如果是这样,有没有办法同步会话中所有副本的更改?



希望我足够清楚并且没有弄乱杂乱信息:)

解决方案


如果从数据库加载两次,那么hibernate会加载同一个实例的两个单独副本吗?


不,它不会在同一个Session中加载同一个对象两次(为了我们的理智)。



我创建了一个简单的



如果你试图访问集合中的一个元素,Hibernate需要初始化集合(到目前为止,它只是一个代理,具有在需要时从数据库加载集合的智能,例如要求元素或集合的大小)。请参阅测试3(mvn spring-boot:run -Drun.arguments =2)

  //在交易$之外b $ b EntityB bB = aA.setOfB()。get(0)
bB.setOfA()。size()// LazyInitializationExample



如果您在交易中,则会初始化该集合并且将再次从基座检索对应于aA的行,但是它不会被水合。参见测试3(mvn spring-boot:run -Drun.arguments =3)




I know there are many different question on SO regarding lazy load but mine one is a bit different.

Lets say i have an entity A in which i have collection of Entity B. Similarly, in Entity B, i have collection of A. In both case, lazy="true" option is used.

Entity A's instace aA has -->Set<B>===(This set contains Entity B's instance bB)

Entity B's instace bB has -->Set<A>===(This set contains Entity A's instance aA)

Now if i load Entity A's collection(Which is Set<B> ).Its initialized now, i.e. complete A's aA instance including collection. What i expect now is Entity B's instance bB is also completely initialized but no, its not and i get lazy initialization exception when i refer Entity B's collection which has Entity A's instance aA.

Does hibernate load two seprate copies of same instance if they are loaded twice from database? if so, is there a way to synchronize changes in all copies within session?

Hope i am clear enough and haven't messed things up with messy info:)

解决方案

Does hibernate load two seprate copies of same instance if they are loaded twice from database?

No, it won't load the same object twice (for our sanity's sake) in the same Session.

I've created a simple Spring Boot project to see this.

EntityA#setOfB(B1,B2)
EntityB#setOfA(A1)

After load EntityA 1 and EntityB to Session by ID, we force A1.setOfB initialization. In the log below we can see that altough it has to query the collection obtaining both rows (B1 & B2), it will only hidrate one object (B2) because B1 is found in the Session Cache. See test 1 (mvn spring-boot:run -Drun.arguments="1")

DEBUG 6452 --- [           main] o.g.hiplay.app.HibernateService          : ########## Retrieving A1's set of B ##########
DEBUG 6452 --- [           main] org.hibernate.SQL                        : select setofb0_.id_a as id_a1_0_0_, setofb0_.id_b as id_b2_2_0_, entityb1_.id as id1_1_1_, entityb1_.description as descript2_1_1_ from relations setofb0_ inner join entityb entityb1_ on setofb0_.id_b=entityb1_.id where setofb0_.id_a=?
TRACE 6452 --- [           main] o.h.l.p.e.i.AbstractLoadPlanBasedLoader  : Bound [2] parameters total
DEBUG 6452 --- [           main] o.h.l.p.e.p.i.ResultSetProcessorImpl     : Preparing collection intializer : [oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Constructing collection load context for result set [rs3: org.h2.result.LocalResult@5c99abd7 columns: 4 rows: 2 pos: -1]
TRACE 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Starting attempt to find loading collection [[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]]
TRACE 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Collection not yet initialized; initializing
TRACE 6452 --- [           main] o.h.l.p.e.p.i.ResultSetProcessorImpl     : Processing result set
DEBUG 6452 --- [           main] o.h.l.p.e.p.i.ResultSetProcessorImpl     : Starting ResultSet row #0
DEBUG 6452 --- [           main] e.p.i.CollectionReferenceInitializerImpl : Found row of collection: [oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]
TRACE 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Starting attempt to find loading collection [[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]]
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Attempting to locate loading collection entry [CollectionKey[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]] in any result-set context
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Collection [CollectionKey[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]] located in load context
TRACE 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Found loading collection bound to current result set processing; reading row
TRACE 6452 --- [           main] o.h.e.internal.DefaultLoadEventListener  : Loading entity: [oss.gabrielgiussi.hiplay.entities.EntityB#1]
TRACE 6452 --- [           main] o.h.e.internal.DefaultLoadEventListener  : Attempting to resolve: [oss.gabrielgiussi.hiplay.entities.EntityB#1]
TRACE 6452 --- [           main] o.h.e.internal.DefaultLoadEventListener  : Resolved object in session cache: [oss.gabrielgiussi.hiplay.entities.EntityB#1]
DEBUG 6452 --- [           main] o.h.l.p.e.p.i.ResultSetProcessorImpl     : Starting ResultSet row #1
TRACE 6452 --- [           main] l.p.e.p.i.EntityReferenceInitializerImpl : hydrating entity state
TRACE 6452 --- [           main] l.p.e.p.i.EntityReferenceInitializerImpl : Initializing object from ResultSet: [oss.gabrielgiussi.hiplay.entities.EntityB#2]
TRACE 6452 --- [           main] o.h.p.entity.AbstractEntityPersister     : Hydrating entity: [oss.gabrielgiussi.hiplay.entities.EntityB#2]
DEBUG 6452 --- [           main] e.p.i.CollectionReferenceInitializerImpl : Found row of collection: [oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]
TRACE 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Starting attempt to find loading collection [[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]]
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Attempting to locate loading collection entry [CollectionKey[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]] in any result-set context
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Collection [CollectionKey[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]] located in load context
TRACE 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Found loading collection bound to current result set processing; reading row
TRACE 6452 --- [           main] o.h.e.internal.DefaultLoadEventListener  : Loading entity: [oss.gabrielgiussi.hiplay.entities.EntityB#2]
TRACE 6452 --- [           main] o.h.e.internal.DefaultLoadEventListener  : Attempting to resolve: [oss.gabrielgiussi.hiplay.entities.EntityB#2]
TRACE 6452 --- [           main] o.h.e.internal.DefaultLoadEventListener  : Resolved object in session cache: [oss.gabrielgiussi.hiplay.entities.EntityB#2]
TRACE 6452 --- [           main] o.h.l.p.e.p.i.ResultSetProcessorImpl     : Done processing result set (2 rows)
TRACE 6452 --- [           main] o.h.l.p.e.p.internal.AbstractRowReader   : Total objects hydrated: 1
DEBUG 6452 --- [           main] o.h.engine.internal.TwoPhaseLoad         : Resolving associations for [oss.gabrielgiussi.hiplay.entities.EntityB#2]
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Attempting to locate loading collection entry [CollectionKey[oss.gabrielgiussi.hiplay.entities.EntityB.setOfA#2]] in any result-set context
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Collection [CollectionKey[oss.gabrielgiussi.hiplay.entities.EntityB.setOfA#2]] not located in load context
TRACE 6452 --- [           main] org.hibernate.type.CollectionType        : Created collection wrapper: [oss.gabrielgiussi.hiplay.entities.EntityB.setOfA#2]
DEBUG 6452 --- [           main] o.h.engine.internal.TwoPhaseLoad         : Done materializing entity [oss.gabrielgiussi.hiplay.entities.EntityB#2]
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Attempting to locate loading collection entry [CollectionKey[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]] in any result-set context
TRACE 6452 --- [           main] o.h.e.loading.internal.LoadContexts      : Collection [CollectionKey[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]] located in load context
TRACE 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Removing collection load entry [org.hibernate.engine.loading.internal.LoadingCollectionEntry<rs=rs3: org.h2.result.LocalResult@5c99abd7 columns: 4 rows: 2 pos: 2, coll=[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]>@131c8e88]
DEBUG 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : 1 collections were found in result set for role: oss.gabrielgiussi.hiplay.entities.EntityA.setOfB
TRACE 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Ending loading collection [org.hibernate.engine.loading.internal.LoadingCollectionEntry<rs=rs3: org.h2.result.LocalResult@5c99abd7 columns: 4 rows: 2 pos: 2, coll=[oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]>@131c8e88]
DEBUG 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : Collection fully initialized: [oss.gabrielgiussi.hiplay.entities.EntityA.setOfB#1]
DEBUG 6452 --- [           main] o.h.e.l.internal.CollectionLoadContext   : 1 collections initialized for role: oss.gabrielgiussi.hiplay.entities.EntityA.setOfB
TRACE 6452 --- [           main] o.h.e.i.StatefulPersistenceContext       : Initializing non-lazy collections
DEBUG 6452 --- [           main] o.g.hiplay.app.HibernateService          : ########## The object hasn't been loaded twice ##########

Hibernate checks if the Object to hydrate is already in the Session Cache asking to the StatefulPersistenceContext

What i expect now is Entity B's instance bB is also completely initialized but no, its not and i get lazy initialization exception when i refer Entity B's collection which has Entity A's instance aA.

What is truly uninitialized is bB's set of A. After doing something like:

EntityA aA = session.get("A",a) aA.setOfB.size() // force initialization of lazy collection. At this point bB is hydratate and put in memory, but his collection of A is uninitalized.

If you try to access an element of the collection Hibernate needs to initialize the collection (all it has until now is a proxy with the intelligence of load the collection from database when is needed, e.g. asking for an element or the size of the collection). See test 3 (mvn spring-boot:run -Drun.arguments="2")

// outside of the transaction
EntityB bB = aA.setOfB().get(0)
bB.setOfA().size() // LazyInitializationExample

If you were inside of a transaction the collection will be initialized and the row corresponding to aA will be retrieved from the base again but it will not be hydrated. See test 3 (mvn spring-boot:run -Drun.arguments="3")

这篇关于如果从数据库加载两次,那么hibernate是否会加载同一实例的两个seprate副本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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