hibernate Multi-tenancy多租户为什么connection总是空指针?
运行错误详情
Exception in thread "main" java.lang.NullPointerException
at org.hibernate.c3p0.internal.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:73)
at com.qzd.hibernate.MultiTenantConnectionProviderImpl.getAnyConnection(MultiTenantConnectionProviderImpl.java:65)
at com.qzd.hibernate.MultiTenantConnectionProviderImpl.getConnection(MultiTenantConnectionProviderImpl.java:78)
at org.hibernate.internal.AbstractSessionImpl$ContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:429)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded(LogicalConnectionManagedImpl.java:84)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection(LogicalConnectionManagedImpl.java:109)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getConnectionForTransactionManagement(LogicalConnectionManagedImpl.java:227)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:234)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:214)
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:52)
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1525)
at com.qzd.hibernate.TestMultiTenancy.main(TestMultiTenancy.java:40)
hibernate.cfg.xml配置
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_structured_entries">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>
<property name="net.sf.ehcache.configurationResourceName">ehcache.xml</property>
<property name="hibernate.connection.provider_class">
org.hibernate.c3p0.internal.C3P0ConnectionProvider
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="hibernate.connection.url">
jdbc:mysql://localhost:3306/hibernate
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">
,an.123;kun
</property>
<property name="hibernate.c3p0.min_size">3</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.timeout">1500</property>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQL5Dialect
</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="myeclipse.connection.profile">mysql</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/hibernate
</property>
<property name="connection.username">root</property>
<property name="connection.password">,an.123;kun</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.multiTenancy">shema</property>
<property name="hibernate.multi_tenant_connection_provider">com.qzd.hibernate.MultiTenantConnectionProviderImpl</property>
<mapping resource="com/qzd/hibernate/People.hbm.xml" />
<mapping resource="com/qzd/hibernate/Wife.hbm.xml" />
<mapping resource="com/qzd/hibernate/Child.hbm.xml" />
<mapping resource="com/qzd/hibernate/Address.hbm.xml" />
<mapping resource="com/qzd/hibernate/Person.hbm.xml" />
<mapping resource="com/qzd/hibernate/Tempbook.hbm.xml" />
<mapping resource="com/qzd/hibernate/Tempkind.hbm.xml" />
</session-factory>
</hibernate-configuration>
package com.qzd.hibernate;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.hibernate.HibernateException;
import org.hibernate.c3p0.internal.C3P0ConnectionProvider;
import org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl;
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.Stoppable;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider,Configurable,Stoppable,ServiceRegistryAwareService{
private C3P0ConnectionProvider connectionProvider=new C3P0ConnectionProvider();
@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 {
Connection conn = null;
try {
conn = connectionProvider.getConnection();
} catch (SQLException e) {
throw new SQLException(e);
} finally {
System.out.println("222222222222222222888888888::" + (conn == null));
}
return connectionProvider.getConnection();
}
@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
final Connection connection = getAnyConnection();
try {
connection.createStatement().execute( "USE " + tenantIdentifier );
}
catch ( SQLException exception ) {
throw new HibernateException(
"Could not alter JDBC connection to specified schema [" +tenantIdentifier + "]",
exception
);
}
return connection;
}
@Override
public void releaseAnyConnection(Connection connection) throws SQLException {
connectionProvider.closeConnection(connection);
}
@Override
public void releaseConnection(String tenantIdentifier, Connection connection)throws SQLException {
try {
connection.createStatement().execute( "USE antest" );
}
catch ( SQLException exception) {
throw new HibernateException(
"Could not alter JDBC connection to specified schema [" +
tenantIdentifier + "]",
exception
);
}
connectionProvider.closeConnection( connection );
}
@Override
public boolean supportsAggressiveRelease() {
// TODO Auto-generated method stub
return false;
}
@Override
public void configure(Map props) {
Properties c3props = new Properties();
Map allProps = new HashMap();
allProps.putAll( props );
allProps.putAll( c3props );
}
@Override
public void injectServices(ServiceRegistryImplementor arg0) {
// TODO Auto-generated method stub
}
}
测试文件代码
package com.qzd.hibernate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.envers.query.AuditEntity;
import org.hibernate.envers.query.AuditQuery;
import com.qzd.shop.web.bean.Book;
public class TestMultiTenancy {
public static void main(String args[]) {
Configuration config = new Configuration();
StandardServiceRegistryBuilder standardRegistryBuilder = new StandardServiceRegistryBuilder();
standardRegistryBuilder.configure("hibernate.cfg.xml").applySetting(
"hibernate.multiTenancy",
org.hibernate.MultiTenancyStrategy.SCHEMA);
StandardServiceRegistry standardRegistry = standardRegistryBuilder
.build();
SessionFactory sessionFactory = config
.buildSessionFactory(standardRegistry);
Session session = sessionFactory.withOptions()
.tenantIdentifier("hibernate").openSession();
Transaction trans = session.beginTransaction();
try {
Query query=session.createQuery("select new list(book.bookName,book.author,book.price) from Book book where book.bookId=3");
query.list().forEach((c)->System.out.println(c));
trans.commit();
} catch (Exception ex) {
try {
trans.rollback();
} catch (HibernateException e) {
System.out.print(e.getMessage());
}
System.out.println(ex.getMessage());
} finally {
session.close();
sessionFactory.close();
}
}
}
求大神解答,不胜感激。
c3p0报错
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<!-- 配置属性文件位置 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean>
<!-- 连接池配置 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="autoCommitOnClose" value="true" />
<property name="checkoutTimeout" value="${cpool.checkoutTimeout}" />
<property name="initialPoolSize" value="${cpool.minPoolSize}" />
<property name="minPoolSize" value="${cpool.minPoolSize}" />
<property name="maxPoolSize" value="${cpool.maxPoolSize}" />
<property name="maxIdleTime" value="${cpool.maxIdleTime}" />
<property name="acquireIncrement" value="${cpool.acquireIncrement}" />
<property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.sql_format">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value></value>
</list>
</property>
</bean>
<!-- 事务配置 -->
<!--Step1.事务管理器配置-->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!--Step2.交给SPRING事务管理的一些方法.-->
<aop:config>
<!-- 指定切面是哪个范围类,比如你项目的SERVICE的所有方法-->
<aop:pointcut id="serviceMethods" expression="execution(* service..*.*(..))" />
<!-- 一个通知的集合,这个集合都用上的POINTCUT-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
</aop:config>
<!--定义通知集合,以TX开头,是有事务的 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!--
所有的以ADD开头的方法名的方法都用事务 REQUIRED
表示,比如方法A有更新操作,A中调用了B方法,那么B到底是重新起一个事务还是用A方法的事务,
REQUIRED标识不起就用当前事务,如果有就用A的,如果没有就起一个
-->
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<!--
加入只读,说明以GET或者LOAD开头的方法名的方法都是只读事务,说明这个
方法内没有UPDATE操作,这样声明一下可以提高该查询方法的效率
-->
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="query*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
</beans>
#mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/b2c
jdbc.username=root
jdbc.password=
#ms sql
#jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
#jdbc.url=jdbc:sqlserver://localhost:1433;database=hibernate
#jdbc.username=sa
#jdbc.password=sa
#oracle
jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.username=scott
jdbc.password=tiger
cpool.checkoutTimeout=25000
cpool.minPoolSize=1
cpool.maxPoolSize=5
cpool.maxIdleTime=25200
cpool.maxIdleTimeExcessConnections=1800
cpool.acquireIncrement=5
你参考下,