ejb + JPA多租户与hibernate4,无法完成架构更新:java.lang.NullPointerException

时间:2023-01-19 21:36:06

Now I have an application with jpa(hibernate4) mutlitenancy, but there are some exceptions, I use ejb3+jpa+wildfly, I don't know where is wrong, only one message java lang nullponinterexception:

现在我有一个jpa(hibernate4)mutlitenancy的应用程序,但也有一些例外,我使用的是ejb3 + jpa + wildfly,我不知道哪里出错了,只有一条消息java lang nullponinterexception:

Could not complete schema update: java.lang.NullPointerException
    at org.hibernate.tool.hbm2ddl.SuppliedConnectionProviderConnectionHelper.prepare(SuppliedConnectionProviderConnectionHelper.java:51) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:194) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:178) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:522) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850) [hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843) [hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:397) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842) [hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
    at org.jboss.as.jpa.hibernate4.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44) [jipijapa-hibernate4-3-1.0.1.Final.jar:]
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:154) [wildfly-jpa-8.1.0.Final.jar:8.1.0.Final]
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:117) [wildfly-jpa-8.1.0.Final.jar:8.1.0.Final]
    at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.8.0_25]
    at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:474) [wildfly-security-manager-1.0.0.Final.jar:1.0.0.Final]
    at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:182) [wildfly-jpa-8.1.0.Final.jar:8.1.0.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]
    at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.1.1.Final.jar:2.1.1.Final]


there are my persistence.xml 、 MultiTenantConnectionProviderImpl and CurrentTenantIdentifierResolverImpl

persistence.xml

      <persistence-unit name="basic-entity"
        transaction-type="JTA">

        <!-- <provider>net.bull.javamelody.JpaPersistence</provider> -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>




        <jta-data-source>java:jboss/datasources/JcMysqlDS</jta-data-source>

        <properties>
            <property name="hibernate.connection.username" value="root" />
            <property name="hibernate.connection.password" value="123456" />
            <property name="hibernate.connection.autocommit" value="true"/>
            <property name="hibernate.transaction.flush_before_completion"        value="true"/>
            <property name="hibernate.c3p0.min_size" value="5"/>
            <property name="hibernate.c3p0.max_size" value="32"/>
            <property name="hibernate.c3p0.timeout" value="15"/>
            <property name="hibernate.c3p0.max_statements" value="10"/>
            <property name="hibernate.c3p0.idle_test_period" value="300"/>
            <property name="hibernate.c3p0.unreturnedConnectionTimeout" value="95"/>
            <property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces" 
                value="true"/>

            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" 
                />
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/itoo_basic" 
                />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
            <!-- <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/> -->
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />

<property name="hibernate.default_schema" value="public"/>
            <property name="hibernate.multi_tenant_connection_provider"
            value="com.my.multi.MultiTenantConnectionProviderImpl"/>


            <property name="hibernate.tenant_identifier_resolver"
            value="com.my.multi.CurrentTenantIdentifierResolverImpl" 
                />
            <property name="hibernate.multiTenancy" value="SCHEMA" />
        </properties>
    </persistence-unit>

CurrentTenantIdentifierResolverImpl

       public class CurrentTenantIdentifierResolverImpl implements   CurrentTenantIdentifierResolver  {

       @Override
      public String resolveCurrentTenantIdentifier() {
         return "public";
      }

      @Override
      public boolean validateExistingCurrentSessions() {
        return false;
     }
}

class MultiTenantConnectionProviderImpl 

     public class MultiTenantConnectionProviderImpl implements
        MultiTenantConnectionProvider, Stoppable, ServiceRegistryAwareService     {
    /**
     * 
     */
      private static final long serialVersionUID = -5121435319787325293L;
      private  C3P0ConnectionProvider connectionProvider =null;

      @Override
      public boolean isUnwrappableAs(Class arg0) {
        // TODO Auto-generated method stub
        return false;
      }

      @Override
      public <T> T unwrap(Class<T> arg0) {
        // TODO Auto-generated method stub
        return null;
      }

      @Override
      public void stop() {
        // TODO Auto-generated method stub

      }

      @Override
      public Connection getAnyConnection() throws SQLException {
        return connectionProvider.getConnection();
       }

      @Override
      public Connection getConnection(String tenantIdentifier)
            throws SQLException {
         final Connection connection = getAnyConnection();
         try {
            connection.createStatement().execute("USE itoo_basic "  );
        } catch (SQLException e) {
            throw new HibernateException(
                    "Could not alter JDBC connection to specified schema ["
                            + tenantIdentifier + "]", e);
        }
        return connection;
    }

      @Override
       public void releaseAnyConnection(Connection connection) throws   SQLException {
        // TODO Auto-generated method stub
        connectionProvider.closeConnection(connection);
        //lazyDatasource.getConnection().close();
     }

      @Override
      public void releaseConnection(String tenantIdentifier, Connection   connection)
            throws SQLException {
        try {
            connection.createStatement().execute("USE master");
        } catch (SQLException e) {
            // on error, throw an exception to make sure the connection is   not
            // returned to the pool.
            // your requirements may differ`enter code here`
            throw new HibernateException(
                    "Could not alter JDBC connection to specified schema ["
                            + tenantIdentifier + "]", e);
        }
        connectionProvider.closeConnection(connection);
        //lazyDatasource.getConnection().close();

       }

      @Override
      public boolean supportsAggressiveRelease() {
        // TODO Auto-generated method stub
        return false;
      }

      @Override
      public void injectServices(ServiceRegistryImplementor serviceRegistry)        {
        // TODO Auto-generated method stub

          Map lSettings =     serviceRegistry.getService(ConfigurationService.class).getSettings();

        connectionProvider = new C3P0ConnectionProvider();
         connectionProvider.injectServices(serviceRegistry);
          connectionProvider.configure(lSettings);
       }

       }

I use schema. Can anybody help me?

我使用架构。有谁能够帮我?

1 个解决方案

#1


If you look at the code in org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(Map) you can see that it fills the "default" connection provider with the value null. So the schema update with Hibernate fails and throws this nasty NullPointerException.

如果查看org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(Map)中的代码,可以看到它使用值null填充“默认”连接提供程序。因此,使用Hibernate的架构更新失败并抛出这个令人讨厌的NullPointerException。

This is because it would only update the default schema when starting the application -- and if you switch to another one it might not be updated.

这是因为它只会在启动应用程序时更新默认架构 - 如果切换到另一个架构,它可能不会更新。

So the solution is to disable the line <property name="hibernate.hbm2ddl.auto" value="update" /> and update the schemas on your own.

因此解决方案是禁用行 并自行更新模式。

#1


If you look at the code in org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(Map) you can see that it fills the "default" connection provider with the value null. So the schema update with Hibernate fails and throws this nasty NullPointerException.

如果查看org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(Map)中的代码,可以看到它使用值null填充“默认”连接提供程序。因此,使用Hibernate的架构更新失败并抛出这个令人讨厌的NullPointerException。

This is because it would only update the default schema when starting the application -- and if you switch to another one it might not be updated.

这是因为它只会在启动应用程序时更新默认架构 - 如果切换到另一个架构,它可能不会更新。

So the solution is to disable the line <property name="hibernate.hbm2ddl.auto" value="update" /> and update the schemas on your own.

因此解决方案是禁用行 并自行更新模式。