首页 > 解决方案 > Spring Boot数据初始化获取异常

问题描述

在我的设置中,我datasource.initialization设置为始终。

问题

spring.jpa.hibernate.ddl-auto = create每次我启动应用程序或对应用程序进行更改时,它都会按设计工作,它会重新创建数据库,然后从data.sql

但是当我从 更改为时createupdate我得到了 MySQLIntegrityConstraintViolationException。更新意味着它只有在 Hibernate 检测到更改时才开始工作,对吗?那为什么我会重复输入?

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#configurations-hbmddl

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '10001' for key 'PRIMARY'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_144]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_144]
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3976) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3912) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2530) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2482) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2440) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:845) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:745) ~[mysql-connector-java-5.1.46.jar:5.1.46]
    at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95) ~[HikariCP-2.7.8.jar:na]
    at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-2.7.8.jar:na]
    at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:473) ~[spring-jdbc-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    ... 73 common frames omitted

应用程序属性

## DB confige
....

## Hibernate Properties
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect


# Hibernate ddl auto (create, create-drop, validate, update)
spring.datasource.initialization-mode=always
spring.jpa.hibernate.ddl-auto = create  ###### <---- Problem

数据.sql

insert into course (id, name, created_date, last_updated_date)
values(10001, 'JPA in 50 steps', NOW(), NOW()),
        (10002, 'Spring', NOW(), NOW()),
        (10003, 'Spring Boot', NOW(), NOW());

insert into review(id, description, rating, course_id)
values(50001, 'Okey course', '3', 10001),
        (50002, 'Awesome course', '5', 10001),
        (50003, 'Greate Course', '4', 10003);

insert into passport(id, number)
values(40001, 'ASD2342324'),
        (40002, 'NMWO23423'),
        (40003, 'POOI9098473');


insert into student(id, name, passport_id)
values(20001, 'Ranga', 40001),
        (20002, 'Adam', 40002),
        (20003, 'Jane', 40003);

insert into student_course(student_id, course_id)
values(20001,10001),
(20002,10001),
(20003,10001),
(20001,10003);

标签: hibernatespring-boot

解决方案


问题是 spring.jpa.hibernate.ddl-auto = create每次启动应用程序时都会删除数据库并重新创建。

Whilespring.jpa.hibernate.ddl-auto = update将触发查询以根据实体更改更新您的数据库,而不会删除它或其中的任何数据。

因此,随着 update 和 your data.sqlthat 始终运行,它显然会插入已经存在的行。

作为快速修复,您可以设置spring.datasource.continue-on-error属性并忽略data.sql失败。

但是可能值得学习使用FlywayLiquibase按照文档中的建议,因为它们比ddl-auto = update.

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html


推荐阅读