使用 Hibernate 在 JPA 中 调用 generateSchema 会出现执行两次 SQL 语句问题的解决方法
2017-02-16 17:18
1081 查看
1 描述问题
使用的 Hibernate 版本:5.1.0.Final今天发现在使用 Hibernate 实现的 JPA 中 调用 generateSchema 后,所有的 SQL 语句都会被执行两次:
public void generateSchema(String action){ //Take exiting EMF properties, override the schema generation setting on a copy Map<String,String> createSchemaProperties=new HashMap<>(properties); createSchemaProperties.put( "javax.persistence.schema-generation.database.action", action ); Persistence.generateSchema(getPersistenceUnitName(),createSchemaProperties); }
虽然可以通过单元测试,但总是觉得很奇怪,报错的原因是因为同一张表创建了两次:
... Hibernate: drop table if exists hibernate_sequence Hibernate: drop table if exists Item Hibernate: drop table if exists hibernate_sequence Hibernate: drop table if exists Item 二月 16, 2017 4:54:20 下午 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation INFO: HHH000204: Processing PersistenceUnitInfo [ name: SimpleXMLCompletePU ...] 二月 16, 2017 4:54:20 下午 org.hibernate.dialect.Dialect <init> INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL57InnoDBDialect 二月 16, 2017 4:54:20 下午 org.hibernate.envers.boot.internal.EnversServiceImpl configure INFO: Envers integration enabled? : true 二月 16, 2017 4:54:20 下午 org.hibernate.cfg.annotations.reflection.JPAOverriddenAnnotationReader checkForOrphanProperties WARN: HHH000207: Property net.deniro.hibernate.model.simple.Item.id not found in class but described in <mapping-file/> (possible typo error) 二月 16, 2017 4:54:20 下午 org.hibernate.cfg.annotations.reflection.JPAOverriddenAnnotationReader checkForOrphanProperties WARN: HHH000207: Property net.deniro.hibernate.model.simple.Item.category not found in class but described in <mapping-file/> (possible typo error) Hibernate: create table hibernate_sequence ( next_val bigint ) ENGINE=InnoDB Hibernate: insert into hibernate_sequence values ( 1 ) Hibernate: create table Item ( id bigint not null, auctionEnd datetime(6), name varchar(255) not null, primary key (id) ) ENGINE=InnoDB 二月 16, 2017 4:54:20 下午 org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@6b04acb2' 二月 16, 2017 4:54:20 下午 org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService INFO: HHH000397: Using ASTQueryTranslatorFactory 二月 16, 2017 4:54:20 下午 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Unable to execute command [ create table hibernate_sequence ( next_val bigint ) ENGINE=InnoDB] org.hibernate.tool.schema.spi.CommandAcceptanceException: Unable to execute command [ create table hibernate_sequence ( next_val bigint ) ENGINE=InnoDB] at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:63) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:423) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings(SchemaCreatorImpl.java:408) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:310) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:165) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:134) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:120) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:122) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:64) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.generateSchema(EntityManagerFactoryBuilderImpl.java:862) at org.hibernate.jpa.HibernatePersistenceProvider.generateSchema(HibernatePersistenceProvider.java:155) at javax.persistence.Persistence.generateSchema(Persistence.java:87) at net.deniro.hibernate.env.JPASetup.generateSchema(JPASetup.java:93) at net.deniro.hibernate.env.JPASetup.createSchema(JPASetup.java:79) at net.deniro.hibernate.env.JPATest.beforeMethod(JPATest.java:61) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84) at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:564) at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213) at org.testng.internal.Invoker.invokeMethod(Invoker.java:653) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111) at org.testng.TestRunner.privateRun(TestRunner.java:767) at org.testng.TestRunner.run(TestRunner.java:617) at org.testng.SuiteRunner.runTest(SuiteRunner.java:334) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291) at org.testng.SuiteRunner.run(SuiteRunner.java:240) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224) at org.testng.TestNG.runSuitesLocally(TestNG.java:1149) at org.testng.TestNG.run(TestNG.java:1057) at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175) at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:125) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'hibernate_sequence' already exists at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.jdbc.Util.handleNewInstance(Util.java:377) at com.mysql.jdbc.Util.getInstance(Util.java:360) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:978) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3887) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3823) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2526) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2484) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:848) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:742) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at bitronix.tm.resource.jdbc.BaseProxyHandlerClass.invoke(BaseProxyHandlerClass.java:64) at com.sun.proxy.$Proxy28.execute(Unknown Source) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:51) ... 46 more Hibernate: create table hibernate_sequence ( next_val bigint ) ENGINE=InnoDB Hibernate: insert into hibernate_sequence values ( 1 ) Hibernate: create table Item ( id bigint not null, auctionEnd datetime(6), name varchar(255) not null, primary key (id) ) ENGINE=InnoDB 二月 16, 2017 4:54:20 下午 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException WARN: GenerationTarget encountered exception accepting command : Unable to execute command [ create table Item ( id bigint not null, auctionEnd datetime(6), name varchar(255) not null, primary key (id) ) ENGINE=InnoDB] org.hibernate.tool.schema.spi.CommandAcceptanceException: Unable to execute command [ create table Item ( id bigint not null, auctionEnd datetime(6), name varchar(255) not null, primary key (id) ) ENGINE=InnoDB] at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:63) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlString(SchemaCreatorImpl.java:423) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.applySqlStrings(SchemaCreatorImpl.java:408) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.createFromMetadata(SchemaCreatorImpl.java:310) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.performCreation(SchemaCreatorImpl.java:165) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:134) at org.hibernate.tool.schema.internal.SchemaCreatorImpl.doCreation(SchemaCreatorImpl.java:120) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:122) at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:64) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.generateSchema(EntityManagerFactoryBuilderImpl.java:862) at org.hibernate.jpa.HibernatePersistenceProvider.generateSchema(HibernatePersistenceProvider.java:155) at javax.persistence.Persistence.generateSchema(Persistence.java:87) at net.deniro.hibernate.env.JPASetup.generateSchema(JPASetup.java:93) at net.deniro.hibernate.env.JPASetup.createSchema(JPASetup.java:79) at net.deniro.hibernate.env.JPATest.beforeMethod(JPATest.java:61) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84) at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:564) at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213) at org.testng.internal.Invoker.invokeMethod(Invoker.java:653) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111) at org.testng.TestRunner.privateRun(TestRunner.java:767) at org.testng.TestRunner.run(TestRunner.java:617) at org.testng.SuiteRunner.runTest(SuiteRunner.java:334) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291) at org.testng.SuiteRunner.run(SuiteRunner.java:240) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224) at org.testng.TestNG.runSuitesLocally(TestNG.java:1149) at org.testng.TestNG.run(TestNG.java:1057) at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175) at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:125) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'item' already exists at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.jdbc.Util.handleNewInstance(Util.java:377) at com.mysql.jdbc.Util.getInstance(Util.java:360) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:978) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3887) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3823) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2526) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2484) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:848) at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:742) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at bitronix.tm.resource.jdbc.BaseProxyHandlerClass.invoke(BaseProxyHandlerClass.java:64) at com.sun.proxy.$Proxy28.execute(Unknown Source) at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:51) ... 46 more ... =============================================== Custom suite Total tests run: 1, Failures: 0, Skips: 0 =============================================== Process finished with exit code 0
2 分析问题
打开源代码看看,一路跟踪到org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl:
@Override public void generateSchema() { // This seems overkill, but building the SF is necessary to get the Integrators to kick in. // Metamodel will clean this up... try { SessionFactoryBuilder sfBuilder = metadata().getSessionFactoryBuilder(); populate( sfBuilder, standardServiceRegistry ); sfBuilder.build(); SchemaManagementToolCoordinator.process( metadata, standardServiceRegistry, configurationValues, DelayedDropRegistryNotAvailableImpl.INSTANCE ); } catch (Exception e) { throw persistenceException( "Error performing schema management", e ); } // release this builder cancel(); }
这里面的
sfBuilder.build()
与
SchemaManagementToolCoordinator.process(...)都会执行一次定义的 SQL 语句。
3 解决问题
sfBuilder.build()与
SchemaManagementToolCoordinator.process(...)任意注释掉一个就解决问题啦 O(∩_∩)O~
相关文章推荐
- 使用 Navicat for MySQL 执行 SQL 语句时,出现 out of memory 问题的解决方法
- 执行SQL语句时出现问题操作必须使用一个可更新的查询错误的解决方法
- 使用Hibernate 5.0、4.0、3.0 createSQLQuery执行原生Sql语句 遇到问题及解决办法集锦
- 当Dao层继承了HibernateDaoSupport,使用底层SQL语句,session获取的方法,以及解决关联查询no session的问题
- "执行SQL语句时出现问题操作必须使用一个可更新的查询"错误的解决方法
- mysql使用kill命令解决死锁问题,杀死某条正在执行的sql语句
- mysql使用kill命令解决死锁问题,杀死某条正在执行或没有响应的sql语句,
- Oracle的SQL语句执行效率问题查找与解决方法
- Mysql使用kill命令解决死锁问题(杀死某条正在执行的sql语句)
- hibernate使用原生sql查询Hibernate原生SQL多表查询字段名重复问题以及解决方法
- hibernate4中使用createSQLQuery方法执行sql语句的用法
- mysql导入导出数据中文乱码解决方法小结(1、navicat导入问题已解决,创建连接后修改连接属性,选择高级->将使用Mysql字符集复选框去掉,下拉框选择GBK->导入sql文件OK;2、phpmyadmin显示乱码的问题也解决,两步:1.将sql文件以utf8的字符集编码另存,2.将文件中sql语句中的字段字符集编码改成utf8,导入OK)
- Oracle的SQL语句执行效率问题查找与解决方法
- MySQL中limit使用动态参数的解决方法(拼接SQL字符串语句来执行SQL)
- oracle的SQL语句执行效率问题查找与解决方法
- Oracle执行计划 SQL语句执行效率问题查找与解决方法
- Oracle的SQL语句执行效率问题查找与解决方法
- jboss7.1.1下使用log4j输出mybatis3.2.2的SQL语句问题与解决方法
- 使用<a>标签提交action会执行两次后台方法的原因(反射机制小实例问题的解决)
- mysql使用kill命令解决死锁问题,杀死某条正在执行的sql语句