NullPointerException when use multi-tenancy and TableGenerator

Description

Im using schema based multi-tenancy and entity id generation strategy is TABLE.When I save a new entity into database, NullPointerException occur.

java.lang.NullPointerException
at org.hibernate.engine.transaction.internal.jdbc.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:68)
at org.hibernate.id.TableGenerator.generateHolder(TableGenerator.java:148)
at org.hibernate.id.TableHiLoGenerator$1.getNextValue(TableHiLoGenerator.java:84)
at org.hibernate.id.enhanced.OptimizerFactory$LegacyHiLoAlgorithmOptimizer.generate(OptimizerFactory.java:393)
at org.hibernate.id.TableHiLoGenerator.generate(TableHiLoGenerator.java:81)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:118)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:204)
at org.hibernate.event.internal.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:55)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:189)
at org.hibernate.event.internal.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:49)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:757)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:749)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:745)

Then I dig into hibernate source code, and find that:
When hibernate's MultiTenancyStrategy is not NONE, JdbcServicesImpl.connectionProvider will must be null.And when id generation strategy is table, hibernate will use hilo algorithm to generate id, and use JdbcIsolationDelegate.delegateWork do this work.But dJdbcIsolationDelegate.delegateWork get connection from JdbcServicesImpl.connectionProvider, then NullPointerException occur.

hibernate's source code:

public class JdbcServicesImpl implements ... {

...
private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues) {
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues );

if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) {
connectionProvider = serviceRegistry.getService( ConnectionProvider.class );
return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
}
else {
connectionProvider = null;
final MultiTenantConnectionProvider multiTenantConnectionProvider = serviceRegistry.getService( MultiTenantConnectionProvider.class );
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
}
}
...
}

public class JdbcIsolationDelegate implements IsolationDelegate {
public <T> T delegateWork(WorkExecutorVisitable<T> work, boolean transacted) throws HibernateException {
boolean wasAutoCommit = false;
try {
// todo : should we use a connection proxy here?
Connection connection = connectionProvider().getConnection();
....
}

Activity

Brett MeyerMarch 3, 2014 at 3:40 PM

Bulk rejecting issues lacking a test case or recent response.

Brett MeyerDecember 19, 2013 at 10:31 PM

Note: In an attempt to clean up the HHH JIRA, we will be rejecting any ticket that sits in the "Awaiting Test Case" state for 2-3 months with no response. So, if this issue is critical to you, please attach a reproducing test case ASAP. Thanks!

Lukasz AntoniakNovember 28, 2013 at 10:39 AM

Can you submit a runnable test case reproducing the issue? I am testing current master branch and everything works as expected. Note that MultipleHiLoPerTableGenerator executes SQL statements against JDBC connection provided down the line by MultiTenantConnectionProvider (skipped few layers; look at JdbcIsolationDelegate#delegateWork(WorkExecutorVisitable, boolean), JdbcIsolationDelegate#jdbcConnectionAccess() should evaluate to ContextualJdbcConnectionAccess). TableGenerator has nothing to do with multi-tenancy.

Hendy IrawanNovember 28, 2013 at 7:53 AM

The error happens regardless of the multitenant connection provider & tenant identifier resolver settings.

I'm using multitenancy and it works, so the problem isn't with with Hibernate's basic multitenancy support, but that there are two issues:

1. TableGenerator doesn't support multitenancy
2. SchemaExport doesn't support multitenancy

but yeah, if these settings are missing/misconfigured then Hibernate should throw a better exception instead of NPE.

Lukasz AntoniakNovember 28, 2013 at 7:41 AM

I have been able to reproduce reported exception. You are missing the configuration of hibernate.multi_tenant_connection_provider property. Refer to documentation sections "16.3. Multi-tenancy in Hibernate" (Additionally, a MultiTenantConnectionProvider must be specified.) and "16.3.1. MultiTenantConnectionProvider" (http://docs.jboss.org/hibernate/core/4.3/devguide/en-US/html/ch16.html#d5e4722). There is already a test case covering reported scenario: https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/test/java/org/hibernate/test/multitenancy/schema/SchemaBasedMultiTenancyTest.java. I will submit pull request validating such misconfiguration and raising an exception.

Rejected

Details

Assignee

Reporter

Components

Affects versions

Priority

Created June 14, 2012 at 3:58 AM
Updated March 3, 2014 at 3:40 PM
Resolved March 3, 2014 at 3:40 PM