我知道关于延迟加载的 SO 有很多不同的问题,但我的问题有点不同。
假设我有一个实体 A,其中我有实体 B 的集合。同样,在实体 B 中,我有 A 的集合。在这两种情况下,都使用了 lazy="true" 选项。
实体 A的实例 aA 具有 --> Set<B>===(此集合包含实体 B 的实例 bB)
实体 B的实例 bB 具有 --> Set<A>===(此集合包含实体 A 的实例 aA)
现在,如果我加载实体 A 的集合(即Set<B>)。它现在已初始化,即完成 A 的 aA 实例,包括集合。我现在期望的是实体 B 的实例 bB 也已完全初始化但不,它没有,当我引用具有实体 A 实例 aA 的实体 B 的集合时,我得到了延迟初始化异常。
如果从数据库加载两次,hibernate 是否加载同一个实例的两个单独副本?如果是这样,有没有办法同步会话中所有副本的更改?
希望我足够清楚并且没有用乱七八糟的信息把事情搞砸:)
如果从数据库加载两次,hibernate 是否加载同一个实例的两个单独副本?
不,它不会在同一个会话中两次加载同一个对象(为了我们的理智)。
我创建了一个简单的Spring Boot 项目来查看这一点。
EntityA#setOfB(B1,B2)
EntityB#setOfA(A1)
Run Code Online (Sandbox Code Playgroud)
在通过 ID 将 EntityA 1 和 EntityB 加载到 Session 后,我们强制 A1.setOfB 初始化。在下面的日志中,我们可以看到,尽管它必须查询获取两行(B1 和 B2)的集合,但它只会隐藏一个对象(B2),因为 B1 是在会话缓存中找到的。参见测试 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 ##########
Run Code Online (Sandbox Code Playgroud)
Hibernate 检查对象是否已经在会话缓存中,询问 StatefulPersistenceContext
我现在期望的是实体 B 的实例 bB 也已完全初始化,但不,它没有,当我引用具有实体 A 实例 aA 的实体 B 的集合时,我得到了延迟初始化异常。
真正未初始化的是 bB 的 A 集。在执行以下操作后:
EntityA aA = session.get("A",a) aA.setOfB.size() // 强制初始化惰性集合。此时 bB 是 hydratate 并放入内存中,但他的 A 集合未初始化。
如果您尝试访问集合的元素,Hibernate 需要初始化集合(到目前为止,它所拥有的只是一个代理,具有在需要时从数据库加载集合的智能,例如请求元素或集合的大小) . 参见测试 3 (mvn spring-boot:run -Drun.arguments="2")
// outside of the transaction
EntityB bB = aA.setOfB().get(0)
bB.setOfA().size() // LazyInitializationExample
Run Code Online (Sandbox Code Playgroud)
如果您在事务内部,则集合将被初始化,并且与 aA 对应的行将再次从基数中检索,但不会被水合。参见测试 3 (mvn spring-boot:run -Drun.arguments="3")
| 归档时间: |
|
| 查看次数: |
3716 次 |
| 最近记录: |