數(shù)據(jù)庫(kù)使用的是Mysql5.5浊洞,原來(lái)使用了hibernate4。
最近同事在更新時(shí)热康,將hibernate4升級(jí)為hibernate5 并加入了c3p0沛申,升級(jí)后發(fā)現(xiàn)連原來(lái)的數(shù)據(jù)庫(kù),運(yùn)行時(shí)有如下報(bào)錯(cuò)姐军,此外,業(yè)務(wù)功能一切都正常尖淘。
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:524)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:470)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.createTable(AbstractSchemaMigrator.java:273)
at org.hibernate.tool.schema.internal.GroupedSchemaMigratorImpl.performTablesMigration(GroupedSchemaMigratorImpl.java:71)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:203)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:110)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:176)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:65)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:478)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:423)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:711)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:727)
.......
Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Table 'aaaa' already exists
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3277)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3206)
at com.mysql.jdbc.Statement.execute(Statement.java:727)
at com.mchange.v2.c3p0.impl.NewProxyStatement.execute(NewProxyStatement.java:909)
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54)
... 30 more
修改后的hibernate配置如下,除了新增了c3p0部分的配置外奕锌,其他項(xiàng)與修改前相同
<!--C3P0配置 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="c3p0.max_size">20</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.initialPoolSize">1</property>
<property name="c3p0.timeout">120</property>
<property name="c3p0.max_statements">100</property>
<property name="c3p0.idle_test_period">120</property>
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.validate">true</property>
<property name="c3p0.maxIdleTime">60</property>
<property name="c3p0.checkoutTimeout">100</property>
<!-- Database connection settings -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/xxx</property>
<property name="hibernate.connection.username">xxx</property>
<property name="hibernate.connection.password">xxx</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="hibernate.connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- <property name="dialect">com.cetc7.dao.utils.dialect.SQLiteDialect</property> -->
<!-- Disable the second-level cache -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="hibernate.show_sql">false</property>
<property name="hibernate.format_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.current_session_context_class">thread</property>
...
事實(shí)上hibernate已經(jīng)配置了hbm2ddl.auto為update,不應(yīng)該再去新建表的村生。
順著Error executing DDL via JDBC Statement找了一圈惊暴,發(fā)現(xiàn)都是大家都是因?yàn)榉窖訫ySQL5Dialect寫(xiě)錯(cuò)為MySQLDialect引起的問(wèn)題,然而這里也不存在趁桃。
懷疑要么是hibernate5與hibernate4的可能有些沒(méi)注意到的差異辽话,要么是c3p0部分的配置有誤,嘗試將c3p0去除卫病,問(wèn)題修復(fù)油啤。
對(duì)c3p0的配置項(xiàng)過(guò)了一遍,將checkoutTimeout從100改為3000蟀苛,問(wèn)題修復(fù)益咬。
猜測(cè)同事是沒(méi)注意到單位是毫秒。
<!--當(dāng)連接池用完時(shí)客戶端調(diào)用getConnection()后等待獲取新連接的時(shí)間帜平,超時(shí)后將拋出SQLException,如設(shè)為0則無(wú)限期等待幽告。單位毫秒。Default: 0 -->
<!--<property name="c3p0.checkoutTimeout">100</property>100毫秒太短會(huì)引發(fā)database schema無(wú)法update的錯(cuò)誤-->
<property name="c3p0.checkoutTimeout">3000</property>
將這項(xiàng)配置去除裆甩,問(wèn)題也修復(fù)冗锁,從日志中看到checkoutTimeout默認(rèn)為0。
回頭又看了一遍出錯(cuò)日志嗤栓,發(fā)現(xiàn)出錯(cuò)日志的最前面就有下邊這個(gè)建立連接超時(shí)的WARN冻河,卻被我直接忽略了。
2019-01-11 22:15:08:365 WARN [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService:132] HHH000342: Could not obtain connection to query metadata : An attempt by a client to checkout a Connection has timed out.
2019-01-11 22:15:08:378 INFO [org.hibernate.dialect.Dialect.<init>:156] HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
2019-01-11 22:15:08:399 INFO [org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl.makeLobCreatorBuilder:63] HHH000422: Disabling contextual LOB creation as connection was null
嗯,就是系統(tǒng)運(yùn)行時(shí)芋绸,update配置有效耙厚,但由于建立連接時(shí)超時(shí)時(shí)間太短唉俗,連接失敗,未查詢到Table已經(jīng)存在,就新建熄求,然后也失敗。