Hello,
1.We used org.hibernate : hibernate-core : 5.2.12.Final, and we use multi-tenancy and lazy loading in our project.
2.We use objects that have a longer life cycle,not suitable for solving the problem by extending the session time,So we used the method of enabling hibernate.enable_lazy_load_no_trans to handle it.
3.We may switch the tenant identifier in the thread, so we did not put the tenant identifier in the CurrentTenantIdentifierResolver.
We think of a modification:
We intend to place the tenant identifier in the proxy object when lazy loading,then the tenant identifier is passed to the session when the lazy loading automatically creates the session, and the hibernate source code is modified as follows:
1.Add multi-tenant identifier attributes in the AbstractLazyInitializer class
//Add the properties of the multi-tenant identifier in this class.
private String multiTenanctKey;
public String getMultiTenanctKey()
{
return multiTenanctKey;
}
public void setMultiTenanctKey(String multiTenanctKey)
{
this.multiTenanctKey = multiTenanctKey;
}
2.Add a tenant identifier when automatically creating a session in the AbstractLazyInitializer class
/*
*Pass in the tenant identifier when the session is automatically *created.
*/
SharedSessionContractImplementor Session = (SharedSessionContractImplementor)sf.withOptions()
.tenantIdentifier(multiTenanctKey).openSession();
3.Adding a tenant identifier to a parent class when a proxy object is automatically created in the JavassistLazyInitializer class invoke method
/*
*When creating a proxy object, assign values to the multi-tenant identity *of the parent class in the subclass.
*/
setMultiTenanctKey(session.getTenantIdentifier());
We use objects that have a longer life cycle,not suitable for solving the problem by extending the session time,So we used the method of enabling hibernate.enable_lazy_load_no_trans to handle it.
This sounds like the source of your problems. You don’t need to use the enable_lazy_load_no_trans. Using this setting might indicate that you are fetching entities even when DTO projections would be more suitable.
Entities are only needed when you plan to modify them. They are not universal data holders that should suit every possible use case in your application.
We may switch the tenant identifier in the thread, so we did not put the tenant identifier in the CurrentTenantIdentifierResolver.
It sounds like you are not using Hibernate properly, as it was designed to be used for multi tenancy.
We think of a modification:
We intend to place the tenant identifier in the proxy object when lazy loading,then the tenant identifier is passed to the session when the lazy loading automatically creates the session
You tell about some Hibernate core modifications without providing the reason for having such change. More, your post says about some problems that you have omitted to elaborate.
Try to restructure your post to explain the actual problem. It might be that you are not not using Hibernate properly, as already indicated.
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.hibernatemaptostringtest.SAccount.additionalInfo, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:561)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132)
at org.hibernate.collection.internal.PersistentMap.toString(PersistentMap.java:250)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.hibernatemaptostringtest.SAccount.toString(SAccount.java:252)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at com.hibernatemaptostringtest.HIbernateMapToStringTest.hibernateLazyLoadingTest(HIbernateMapToStringTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
So we used the method of enabling hibernate.enable_lazy_load_no_trans to handle it.
But we used multi tenancy.Show as below
org.hibernate.HibernateException: SessionFactory configured for multi-tenancy, but no tenant identifier specified
at org.hibernate.internal.AbstractSharedSessionContract.<init>(AbstractSharedSessionContract.java:154)
at org.hibernate.internal.AbstractSessionImpl.<init>(AbstractSessionImpl.java:29)
at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:252)
at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1218)
at org.hibernate.internal.SessionFactoryImpl.openSession(SessionFactoryImpl.java:450)
at org.hibernate.collection.internal.AbstractPersistentCollection.openTemporarySessionForLoading(AbstractPersistentCollection.java:275)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:198)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:561)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132)
at org.hibernate.collection.internal.PersistentMap.toString(PersistentMap.java:250)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.hibernatemaptostringtest.SAccount.toString(SAccount.java:252)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at com.hibernatemaptostringtest.HIbernateMapToStringTest.hibernateLazyLoadingTest(HIbernateMapToStringTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
One solution is to use CurrentTenantIdentifierResolver, but we may use many tenant in the business. e.g : load one object from db1 , and then load another object from db2. CurrentTenantIdentifierResolver can not resolve this problem.