Skip to content

Commit 02f085e

Browse files
jrenaatbeikov
authored andcommitted
HHH-17972 - Allow changing tenant identifier in SharedSessionBuilder
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
1 parent 11d2253 commit 02f085e

File tree

3 files changed

+65
-17
lines changed

3 files changed

+65
-17
lines changed

hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ public interface SessionFactoryBuilder {
362362
/**
363363
* Specifies whether multi-tenancy is enabled
364364
*
365-
* @param enabled True if multi-tenancy in use.
365+
* @param enabled True if multi-tenancy in use through a {@link org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider}.
366366
*
367367
* @return {@code this}, for method chaining
368368
*/

hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,14 +2063,20 @@ private SharedSessionBuilderImpl(SessionImpl session) {
20632063

20642064
@Override @Deprecated
20652065
public SharedSessionBuilderImpl tenantIdentifier(String tenantIdentifier) {
2066-
// todo : is this always true? Or just in the case of sharing JDBC resources?
2067-
throw new SessionException( "Cannot redefine tenant identifier on child session" );
2066+
if ( !session.getSessionFactory().getSessionFactoryOptions().isMultiTenancyEnabled() ) {
2067+
throw new SessionException( "Cannot redefine tenant identifier on child session" );
2068+
}
2069+
super.tenantIdentifier( tenantIdentifier );
2070+
return this;
20682071
}
20692072

20702073
@Override
20712074
public SharedSessionBuilderImpl tenantIdentifier(Object tenantIdentifier) {
2072-
// todo : is this always true? Or just in the case of sharing JDBC resources?
2073-
throw new SessionException( "Cannot redefine tenant identifier on child session" );
2075+
if ( session.getSessionFactory().getSessionFactoryOptions().isMultiTenancyEnabled() ) {
2076+
throw new SessionException( "Cannot redefine tenant identifier on child session" );
2077+
}
2078+
super.tenantIdentifier( tenantIdentifier );
2079+
return this;
20742080
}
20752081

20762082
@Override

hibernate-core/src/test/java/org/hibernate/orm/test/tenantid/TenantIdTest.java

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,23 @@
88

99
import org.hibernate.HibernateError;
1010
import org.hibernate.PropertyValueException;
11+
import org.hibernate.Session;
1112
import org.hibernate.StatelessSession;
13+
import org.hibernate.Transaction;
1214
import org.hibernate.boot.SessionFactoryBuilder;
1315
import org.hibernate.boot.spi.MetadataImplementor;
1416
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
1517
import org.hibernate.dialect.SybaseASEDialect;
1618
import org.hibernate.engine.spi.SessionFactoryImplementor;
1719
import org.hibernate.testing.orm.junit.DomainModel;
20+
import org.hibernate.testing.orm.junit.JiraKey;
1821
import org.hibernate.testing.orm.junit.ServiceRegistry;
1922
import org.hibernate.testing.orm.junit.SessionFactory;
2023
import org.hibernate.testing.orm.junit.SessionFactoryProducer;
2124
import org.hibernate.testing.orm.junit.SessionFactoryScope;
2225
import org.hibernate.testing.orm.junit.Setting;
2326
import org.hibernate.binder.internal.TenantIdBinder;
27+
import org.hibernate.query.Query;
2428
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
2529
import org.hibernate.query.criteria.JpaCriteriaQuery;
2630
import org.hibernate.query.criteria.JpaRoot;
@@ -57,11 +61,15 @@ public class TenantIdTest implements SessionFactoryProducer {
5761

5862
@AfterEach
5963
public void cleanup(SessionFactoryScope scope) {
60-
scope.inTransaction( session -> {
61-
session.createQuery("delete from Account").executeUpdate();
62-
session.createQuery("delete from Client").executeUpdate();
63-
session.createQuery("delete from Record").executeUpdate();
64-
});
64+
// Use the root tenant to clean up all partitions
65+
currentTenant = "root";
66+
scope.inTransaction(
67+
session -> {
68+
session.createMutationQuery( "delete from Account" ).executeUpdate();
69+
session.createMutationQuery( "delete from Client" ).executeUpdate();
70+
session.createMutationQuery( "delete from Record" ).executeUpdate();
71+
}
72+
);
6573
}
6674

6775
@Override
@@ -96,25 +104,25 @@ public void test(SessionFactoryScope scope) {
96104
} );
97105
scope.inTransaction( session -> {
98106
assertNotNull( session.find(Account.class, acc.id) );
99-
assertEquals( 1, session.createQuery("from Account").getResultList().size() );
107+
assertEquals( 1, session.createQuery("from Account", Account.class).getResultList().size() );
100108
} );
101109
assertEquals("mine", acc.tenantId);
102110

103111
currentTenant = "yours";
104112
scope.inTransaction( session -> {
105113
assertNotNull( session.find(Account.class, acc.id) );
106-
assertEquals( 0, session.createQuery("from Account").getResultList().size() );
114+
assertEquals( 0, session.createQuery("from Account", Account.class).getResultList().size() );
107115
session.disableFilter(TenantIdBinder.FILTER_NAME);
108116
assertNotNull( session.find(Account.class, acc.id) );
109-
assertEquals( 1, session.createQuery("from Account").getResultList().size() );
117+
assertEquals( 1, session.createQuery("from Account", Account.class).getResultList().size() );
110118
} );
111119
}
112120

113121
@Test
114122
public void testRoot(SessionFactoryScope scope) {
115123
currentTenant = "root";
116124
scope.inTransaction( session -> {
117-
assertEquals( 0, session.createQuery( "from Account" ).getResultList().size() );
125+
assertEquals( 0, session.createQuery( "from Account", Account.class ).getResultList().size() );
118126
} );
119127

120128
currentTenant = "mine";
@@ -127,14 +135,14 @@ public void testRoot(SessionFactoryScope scope) {
127135
assertEquals( "mine", acc.tenantId );
128136
scope.inTransaction( session -> {
129137
assertNotNull( session.find( Account.class, acc.id ) );
130-
assertEquals( 1, session.createQuery( "from Account" ).getResultList().size() );
138+
assertEquals( 1, session.createQuery( "from Account", Account.class ).getResultList().size() );
131139
} );
132140

133141
currentTenant = "root";
134142
// Root tenants should find entities from other tenants
135143
scope.inTransaction( session -> {
136144
assertNotNull( session.find( Account.class, acc.id ) );
137-
assertEquals( 1, session.createQuery( "from Account" ).getResultList().size() );
145+
assertEquals( 1, session.createQuery( "from Account", Account.class ).getResultList().size() );
138146
} );
139147

140148
// Root tenants should find entities from their own tenant
@@ -147,7 +155,7 @@ public void testRoot(SessionFactoryScope scope) {
147155
assertEquals( "root", rootAcc.tenantId );
148156
scope.inTransaction( session -> {
149157
assertNotNull( session.find( Account.class, rootAcc.id ) );
150-
assertEquals( 2, session.createQuery( "from Account" ).getResultList().size() );
158+
assertEquals( 2, session.createQuery( "from Account", Account.class ).getResultList().size() );
151159
} );
152160
}
153161

@@ -292,6 +300,40 @@ public void tenantFilterWithStatelessSession(SessionFactoryScope scope) {
292300
} );
293301
}
294302

303+
@Test
304+
@JiraKey( value = "HHH-17972")
305+
public void testChangeTenantId(SessionFactoryScope scope) {
306+
currentTenant = "mine";
307+
scope.inSession(
308+
session -> {
309+
Query<Client> sessionQuery = session.createQuery( "from Client", Client.class );
310+
311+
Transaction t = session.beginTransaction();
312+
session.persist( new Client("Gavin") );
313+
t.commit();
314+
assertEquals(1, sessionQuery.getResultList().size() );
315+
assertEquals( "mine", sessionQuery.getResultList().get( 0 ).tenantId );
316+
317+
Session newSession = session.sessionWithOptions().tenantIdentifier( "yours" ).connection().openSession();
318+
Query<Client> newSessionQuery = newSession.createQuery( "from Client", Client.class );
319+
t = newSession.beginTransaction();
320+
newSession.persist( new Client("Jan") );
321+
t.commit();
322+
323+
assertEquals(1, newSessionQuery.getResultList().size() );
324+
assertEquals( "yours", newSessionQuery.getResultList().get( 0 ).tenantId );
325+
326+
session.disableFilter( TenantIdBinder.FILTER_NAME );
327+
assertEquals(2, sessionQuery.getResultList().size() );
328+
329+
newSession.disableFilter( TenantIdBinder.FILTER_NAME );
330+
assertEquals(2, newSessionQuery.getResultList().size() );
331+
332+
newSession.close();
333+
}
334+
);
335+
}
336+
295337
private static List<Record> listAllRecordsForTenant(StatelessSession session) {
296338
HibernateCriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
297339
JpaCriteriaQuery<Record> criteriaQuery = criteriaBuilder.createQuery( Record.class );

0 commit comments

Comments
 (0)