NullPointerException when use multi-tenancy and TableGenerator
Description
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.
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();
....
}