Skip to content

Commit 4866201

Browse files
jrenaatbeikov
authored andcommitted
HHH-17972 - Allow changing tenant identifier with restrictions when a MultiTenantConnectionProvider is in use
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
1 parent 02f085e commit 4866201

File tree

2 files changed

+84
-7
lines changed

2 files changed

+84
-7
lines changed

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,32 +2050,39 @@ private static class SharedSessionBuilderImpl
20502050
implements SharedSessionBuilder, SharedSessionCreationOptions {
20512051
private final SessionImpl session;
20522052
private boolean shareTransactionContext;
2053+
private boolean tenantIdChanged;
20532054

20542055
private SharedSessionBuilderImpl(SessionImpl session) {
20552056
super( (SessionFactoryImpl) session.getFactory() );
20562057
this.session = session;
20572058
super.tenantIdentifier( session.getTenantIdentifierValue() );
20582059
}
20592060

2061+
@Override
2062+
public SessionImpl openSession() {
2063+
if ( session.getSessionFactory().getSessionFactoryOptions().isMultiTenancyEnabled() ) {
2064+
if ( tenantIdChanged && shareTransactionContext ) {
2065+
throw new SessionException( "Cannot redefine the tenant identifier on a child session if the connection is reused" );
2066+
}
2067+
}
2068+
return super.openSession();
2069+
}
2070+
20602071
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20612072
// SharedSessionBuilder
20622073

20632074

20642075
@Override @Deprecated
20652076
public SharedSessionBuilderImpl tenantIdentifier(String tenantIdentifier) {
2066-
if ( !session.getSessionFactory().getSessionFactoryOptions().isMultiTenancyEnabled() ) {
2067-
throw new SessionException( "Cannot redefine tenant identifier on child session" );
2068-
}
20692077
super.tenantIdentifier( tenantIdentifier );
2078+
tenantIdChanged = true;
20702079
return this;
20712080
}
20722081

20732082
@Override
20742083
public SharedSessionBuilderImpl tenantIdentifier(Object tenantIdentifier) {
2075-
if ( session.getSessionFactory().getSessionFactoryOptions().isMultiTenancyEnabled() ) {
2076-
throw new SessionException( "Cannot redefine tenant identifier on child session" );
2077-
}
20782084
super.tenantIdentifier( tenantIdentifier );
2085+
tenantIdChanged = true;
20792086
return this;
20802087
}
20812088

hibernate-core/src/test/java/org/hibernate/orm/test/multitenancy/AbstractMultiTenancyTest.java

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,18 @@
1717
import jakarta.persistence.Id;
1818

1919
import org.hibernate.Session;
20+
import org.hibernate.SessionException;
2021
import org.hibernate.SessionFactory;
2122
import org.hibernate.Transaction;
2223
import org.hibernate.boot.Metadata;
2324
import org.hibernate.boot.MetadataSources;
2425
import org.hibernate.boot.SessionFactoryBuilder;
25-
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
2626
import org.hibernate.cfg.AvailableSettings;
2727
import org.hibernate.cfg.Environment;
2828
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
2929
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
3030
import org.hibernate.internal.util.PropertiesHelper;
31+
import org.hibernate.query.Query;
3132
import org.hibernate.service.spi.ServiceRegistryImplementor;
3233
import org.hibernate.service.spi.Stoppable;
3334
import org.hibernate.tool.schema.internal.HibernateSchemaManagementTool;
@@ -37,11 +38,17 @@
3738

3839
import org.hibernate.testing.AfterClassOnce;
3940
import org.hibernate.testing.junit4.BaseUnitTestCase;
41+
import org.hibernate.testing.orm.junit.JiraKey;
4042
import org.hibernate.testing.util.ServiceRegistryUtil;
4143

4244
import org.hibernate.orm.test.util.DdlTransactionIsolatorTestingImpl;
45+
46+
import org.junit.After;
47+
import org.junit.Assert;
4348
import org.junit.Test;
4449

50+
import static org.junit.Assert.assertEquals;
51+
4552
/**
4653
* @author Vlad Mihalcea
4754
*/
@@ -82,6 +89,12 @@ public void destroy() {
8289
}
8390
}
8491

92+
@After
93+
public void cleanup() {
94+
doInSession(FRONT_END_TENANT, session -> session.createMutationQuery( "delete from Person" ).executeUpdate() );
95+
doInSession(BACK_END_TENANT, session -> session.createMutationQuery( "delete from Person" ).executeUpdate() );
96+
}
97+
8598
//tag::multitenacy-hibernate-MultiTenantConnectionProvider-example[]
8699

87100
protected void registerConnectionProvider(String tenantIdentifier) {
@@ -116,6 +129,63 @@ public void testBasicExpectedBehavior() {
116129
//end::multitenacy-multitenacy-hibernate-same-entity-example[]
117130
}
118131

132+
@Test
133+
@JiraKey( value = "HHH-17972")
134+
public void testChangeTenantWithoutConnectionReuse() {
135+
Person person = new Person();
136+
person.setId( 1L );
137+
person.setName( "John Doe" );
138+
Person person2 = new Person();
139+
person2.setId( 2L );
140+
person2.setName( "Jane Doe" );
141+
142+
Transaction t;
143+
Session session = null;
144+
Session newSession = null;
145+
try {
146+
session = sessionFactory.withOptions().tenantIdentifier( FRONT_END_TENANT ).openSession();
147+
t = session.beginTransaction();
148+
session.persist( person );
149+
t.commit();
150+
151+
Query<Person> sessionQuery = session.createQuery( "from Person", Person.class );
152+
assertEquals( 1, sessionQuery.getResultList().size() );
153+
assertEquals( "John Doe", sessionQuery.getResultList().get( 0 ).getName() );
154+
155+
newSession = session.sessionWithOptions().tenantIdentifier( BACK_END_TENANT ).openSession();
156+
t = newSession.beginTransaction();
157+
newSession.persist( person2 );
158+
t.commit();
159+
160+
Query<Person> newSessionQuery = newSession.createQuery( "from Person", Person.class );
161+
assertEquals( 1, newSessionQuery.getResultList().size() );
162+
assertEquals( "Jane Doe", newSessionQuery.getResultList().get( 0 ).getName() );
163+
}
164+
finally {
165+
if (session != null) {
166+
session.close();
167+
}
168+
if (newSession != null) {
169+
newSession.close();
170+
}
171+
}
172+
}
173+
174+
@Test
175+
@JiraKey( value = "HHH-17972")
176+
public void testChangeTenantWithConnectionReuse() {
177+
try (Session session = sessionFactory.withOptions().tenantIdentifier( FRONT_END_TENANT ).openSession()) {
178+
Assert.assertThrows( "Cannot redefine the tenant identifier on a child session if the connection is reused",
179+
SessionException.class,
180+
() -> session.sessionWithOptions().tenantIdentifier( BACK_END_TENANT ).connection().openSession()
181+
);
182+
Assert.assertThrows( "Cannot redefine the tenant identifier on a child session if the connection is reused",
183+
SessionException.class,
184+
() -> session.sessionWithOptions().connection().tenantIdentifier( BACK_END_TENANT ).openSession()
185+
);
186+
}
187+
}
188+
119189
protected Properties properties() {
120190
Properties properties = new Properties();
121191
URL propertiesURL = Thread.currentThread().getContextClassLoader().getResource("hibernate.properties");

0 commit comments

Comments
 (0)