【问题标题】:Spring boot run script if spring.jpa.hibernate.ddl-auto is not "update"?如果 spring.jpa.hibernate.ddl-auto 不是“更新”,则 Spring Boot 运行脚本?
【发布时间】:2015-12-15 01:07:12
【问题描述】:

如果我设置了 application.properties,它会在加载时出错

spring.jpa.hibernate.ddl-auto = update
spring.datasource.data=classpath:/init.dml/TB_FR_LANGUAGE_INFO_INITDATA.sql,classpath:/init.dml/TB_FR_MESSAGE_INFO_INITDATA.sql

只有当 spring.jpa.hibernate.ddl-auto 是 create-drop 或 create 时,如何才能 spring boot 运行初始脚本?

更新

如何避免过去添加一次的初始数据插入脚本?

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory': Post-processing of FactoryBean's singleton object failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of resource class path resource [init.dml/TB_FR_LANGUAGE_INFO_INITDATA.sql]: INSERT INTO TB_FR_LANGUAGE_INFO ( LANGUAGE_SQ, LANGUAGE_ID, LANGUAGE_NM, USE_YN, ORDER_NO, CREATE_DT, CREATE_USR_ID) VALUES ('LAN_000001','KO', 'Korean', 'Y' , 0, NOW(),'superadmin'); nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'LAN_000001' for key 'PRIMARY'
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:116)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:314)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:565)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:531)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:697)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:670)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
    ... 120 more
Caused by: org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of resource class path resource [init.dml/TB_FR_LANGUAGE_INFO_INITDATA.sql]: INSERT INTO TB_FR_LANGUAGE_INFO ( LANGUAGE_SQ, LANGUAGE_ID, LANGUAGE_NM, USE_YN, ORDER_NO, CREATE_DT, CREATE_USR_ID) VALUES ('LAN_000001','KO', 'Korean', 'Y' , 0, NOW(),'superadmin'); nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'LAN_000001' for key 'PRIMARY'
    at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:472)
    at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:229)
    at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:48)
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.runScripts(DataSourceInitializer.java:153)
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.runDataScripts(DataSourceInitializer.java:112)
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.onApplicationEvent(DataSourceInitializer.java:105)
    at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.onApplicationEvent(DataSourceInitializer.java:46)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
    at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.postProcessAfterInitialization(DataSourceInitializedPublisher.java:69)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1719)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:113)
    ... 130 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'LAN_000001' for key 'PRIMARY'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    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:971)
    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 org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:457)
    ... 143 more

【问题讨论】:

  • 请分享错误堆栈跟踪以获取更多信息。
  • @Avis 此配置与生成错误无关。但是spring boot会尝试执行我设置属性的脚本,即使它已经插入了。

标签: spring-boot


【解决方案1】:

您使用的休眠 ddl-auto 顾名思义,仅适用于 DDL,即模式定义。要查看实际代码检查这个休眠文件:-

hibernate-orm/hibernate-core/src/main/java/org/hibernate/cfg/SettingsFactory.java

String autoSchemaExport = properties.getProperty( AvailableSettings.HBM2DDL_AUTO );
if ( "validate".equals(autoSchemaExport) ) {
    settings.setAutoValidateSchema( true );
}
else if ( "update".equals(autoSchemaExport) ) {
    settings.setAutoUpdateSchema( true );
}
else if ( "create".equals(autoSchemaExport) ) {
    settings.setAutoCreateSchema( true );
}
else if ( "create-drop".equals( autoSchemaExport ) ) {
    settings.setAutoCreateSchema( true );
    settings.setAutoDropSchema( true );
}
else if ( !StringHelper.isEmpty( autoSchemaExport ) ) {
    LOG.warn( "Unrecognized value for \"hibernate.hbm2ddl.auto\": " + autoSchemaExport );
}

Hibernate 不对这些表上插入/存在的数据以及您实际上想要的数据进行任何验证。解决您的问题的一种方法是让您的插入以以下形式检查数据是否不存在然后仅插入:-

INSERT INTO TB_FR_LANGUAGE_INFO ( LANGUAGE_SQ, LANGUAGE_ID, LANGUAGE_NM, USE_YN, ORDER_NO, CREATE_DT, CREATE_USR_ID) 
    VALUES ('LAN_000001','KO', 'Korean', 'Y' , 0, NOW(),'superadmin') 
WHERE NOT EXISTS 
    (select LANGUAGE_SQ from TB_FR_LANGUAGE_INFO where LANGUAGE_SQ = 'LAN_000001');

【讨论】:

  • 它没有用。即使我设置了属性“验证”的值,它也不起作用并得到了完整性约束违规异常。
  • 请添加完整的堆栈跟踪,以便我可以看到它在 Spring 中开始失败的点。
  • 再次更新。我希望你能解决这个问题:)我期待。
  • 我会尝试 :)。你能确认一下你在两个脚本文件上都有什么类型的脚本语句。我的理解是第一个脚本具有 DDL,而第二个脚本是在这些表上插入一些配置数据。
  • 当然,我写了两个脚本。但是有很多文件作为这个属性的值。但是每个脚本只构成插入脚本
猜你喜欢
  • 2021-04-09
  • 1970-01-01
  • 2017-12-25
  • 2020-08-02
  • 2019-03-17
  • 2021-03-13
  • 1970-01-01
  • 2017-06-27
  • 2022-08-11
相关资源
最近更新 更多