在做批量导入功能的时候,从页面导入excel文件,后台java程序读取文件内容存入一个List,然后将List数据做一些处理然后插入一张数据表,由于数据量较大,所以借助临时表,先将List做处理插入临时表,然后将临时表数据复制到要插入的数据表中。
整个过程分这样几步:
1.调用存储过程创建临时表
2.java程序将读取的excel文件内容放入List,将List做处理然后插入到临时表(这个过程是在java程序里面做的)
3.调用存储过程将临时表数据复制到要插入的数据表
4.调用存储过程删除临时表
思路是这样没错,但是实际操作的时候出现这样一个问题,创建临时表后,在后面的2、3、4步都随机性的报错临时表不存在。当时百思不得其解,因为公司另外一个项目里面也是这样做过的,功能一点问题也没有,后来我又仔细对比了两个项目的相关java代码,也没发现有什么不同,基本排除了java代码出问题的可能,那么就剩下数据连接的问题了,考虑到是不是数据连接池配置不同,然后又查看了数据连接池配置文件,果然,两个项目用的数据连接池是不同的,当前项目用的连接池是com.mchange.v2.c3p0.ComboPooledDataSource,原来那个项目用的连接池是org.apache.commons.dbcp.BasicDataSource,我把当前项目连接池配置修改成org.apache.commons.dbcp.BasicDataSource,重新测试就没有出现问题了
<!-- 会报错的数据连接池配置 -->
<!-- 加载数据库连接文件 -->
<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true" /> <!-- 设置数据库连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" parent="c3p0DataSource"> <property name="driverClass" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="c3p0DataSource" abstract="true"> 初始化连接池中的连接数,取值应在minPoolSize与maxPoolSize之间,默认为3 <property name="initialPoolSize" value="3" /> 连接池中保留的最小连接数,默认为:3 <property name="minPoolSize" value="3" /> 连接池中保留的最大连接数。默认值: 15 <property name="maxPoolSize" value="1000" /> 最大空闲时间,*秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0 <property name="maxIdleTime" value="60" /> 每360秒检查所有连接池中的空闲连接。默认值: 0,不检查 <property name="idleConnectionTestPeriod" value="60" /> 定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意: 测试的表必须在初始数据源的时候就存在。Default: null <property name="preferredTestQuery" value="select 1" /> 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 <property name="acquireIncrement" value="5" /> 定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ;小于等于0表示无限次 <property name="acquireRetryAttempts" value="50" /> 重新尝试的时间间隔,默认为:1000毫秒 <property name="acquireRetryDelay" value="1000" /> 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default: false <property name="breakAfterAcquireFailure" value="false" /> 当连接池连接耗尽时,客户端调用getConnection()后等待获取新连接的时间,超时后将抛出SQLException,如设为0则无限期等待。单位毫秒。默认: 0 <property name="checkoutTimeout" value="20000" /> 关闭连接时,是否提交未提交的事务,默认为false,即关闭连接,回滚未提交的事务 <property name="autoCommitOnClose" value="false" /> Strongly disrecommended. Setting this to true may lead to subtle and bizarre bugs. (文档原文)作者强烈建议不使用的一个属性 <property name="forceIgnoreUnresolvedTransactions" value="false" /> 自动超时回收Connection <property name="unreturnedConnectionTimeout" value="1000" /> c3p0全局的PreparedStatements缓存的大小。如果maxStatements与maxStatementsPerConnection均为0,则缓存不生效,只要有一个不为0,则语句的缓存就能生效。如果默认值: 0 <property name="maxStatements" value="0" /> maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。默认值: 0 <property name="maxStatementsPerConnection" value="0" /> 如果设为true那么在取得连接的同时将校验连接的有效性。Default: false <property name="testConnectionOnCheckin" value="true" /> 因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable 等方法来提升连接测试的性能。Default: false <property name="testConnectionOnCheckout" value="false" /> 早期的c3p0版本对JDBC接口采用动态反射代理。在早期版本用途广泛的情况下这个参数 允许用户恢复到动态反射代理以解决不稳定的故障。最新的非反射代理更快并且已经开始 广泛的被使用,所以这个参数未必有用。现在原先的动态反射与新的非反射代理同时受到 支持,但今后可能的版本可能不支持动态反射代理。Default: false <property name="usesTraditionalReflectiveProxies" value="false" /> c3p0是异步操作的,缓慢的JDBC操作通过帮助进程完成。扩展这些操作可以有效的提升性能 通过多线程实现多个操作同时被执行。Default: 3 <property name="numHelperThreads" value="5" />
</bean>
<!-- 修改后的数据连接池配置 -->
<!-- 加载数据库连接文件 -->
<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true" /> <!-- 设置数据库连接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="100"></property> <property name="maxIdle" value="30"></property> <property name="maxWait" value="500"></property> <property name="defaultAutoCommit" value="true"></property> </bean>
出现我这种问题,应该是这两种连接池本身对于临时表的机制不同,com.mchange.v2.c3p0.ComboPooledDataSource应该是在存储过程里面创建临时表,存储过程执行完就自动将临时表销毁了,而org.apache.commons.dbcp.BasicDataSource应该是在会话结束的时候才销毁临时表,不过这个只是个人猜想,没有经过验证,如果有哪位大神知道具体情况,麻烦评论里面告诉我一下