【问题标题】:ejb+JPA Multi-tenancy with hibernate4, could not complete schema update: java.lang.NullPointerException使用 hibernate4 的 ejb+JPA 多租户,无法完成架构更新:java.lang.NullPointerException
【发布时间】:2015-08-07 00:45:03
【问题描述】:

现在我有一个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);
       }

       }

我使用架构。有人可以帮帮我吗?

【问题讨论】:

  • 谁能帮帮我,谢谢!

标签: hibernate jpa persistence.xml multi-tenant


【解决方案1】:

如果您查看org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(Map) 中的代码,您会发现它使用值null 填充“默认”连接提供程序。所以使用 Hibernate 的模式更新失败并抛出这个讨厌的NullPointerException。

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

因此解决方案是禁用&lt;property name="hibernate.hbm2ddl.auto" value="update" /&gt; 行并自行更新架构。

【讨论】:

  • 无论如何设置默认模式以保证使用而不是删除属性选项?我试过hibernate.default_schema,但还是一样。 hbm2ddl.auto 和 hibernate.hbm2ddl.auto 之间还有什么区别吗??
猜你喜欢
  • 2013-05-02
  • 1970-01-01
  • 2015-04-16
  • 2012-05-29
  • 1970-01-01
  • 2021-05-18
  • 2017-07-18
  • 2015-01-05
  • 2014-06-19
相关资源
最近更新 更多