Как конвертировать сроку в enum при выполнении скрипта SQL
У меня есть скрипт в папке ресурсы data.sql
insert into Product (id, name, type) values ('1', 'Falcon 9', 'ROCKET');
При запуске программы получаю следующую ошибку:
Exception in thread "task-2" org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/C:/Users/besto/Desktop/spacex/target/classes/data.sql]: insert into Product (id, name, type) values ('1', 'Falcon 9', 'ROCKET'); nested exception is org.h2.jdbc.JdbcSQLDataException: Ошибка преобразования данных при конвертации "'ROCKET' (PRODUCT: ""TYPE"" INTEGER)"
Data conversion error converting "'ROCKET' (PRODUCT: ""TYPE"" INTEGER)"; SQL statement:
insert into Product (id, name, type) values ('1', 'Falcon 9', 'ROCKET') [22018-200]
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:622)
at org.springframework.jdbc.datasource.init.ResourceDatabasePopulator.populate(ResourceDatabasePopulator.java:254)
at org.springframework.jdbc.datasource.init.DatabasePopulatorUtils.execute(DatabasePopulatorUtils.java:49)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.runScripts(DataSourceInitializer.java:202)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.initSchema(DataSourceInitializer.java:119)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker.onApplicationEvent(DataSourceInitializerInvoker.java:91)
at org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker.onApplicationEvent(DataSourceInitializerInvoker.java:38)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:404)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:361)
at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.publishEventIfRequired(DataSourceInitializedPublisher.java:99)
at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.access$100(DataSourceInitializedPublisher.java:50)
at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher$DataSourceSchemaCreatedPublisher.lambda$postProcessEntityManagerFactory$0(DataSourceInitializedPublisher.java:200)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.h2.jdbc.JdbcSQLDataException: Ошибка преобразования данных при конвертации "'ROCKET' (PRODUCT: ""TYPE"" INTEGER)"
Data conversion error converting "'ROCKET' (PRODUCT: ""TYPE"" INTEGER)"; SQL statement:
insert into Product (id, name, type) values ('1', 'Falcon 9', 'ROCKET') [22018-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:457)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)
at org.h2.message.DbException.get(DbException.java:194)
at org.h2.table.Column.getDataConversionError(Column.java:409)
at org.h2.table.Column.validateConvertUpdateSequence(Column.java:381)
at org.h2.table.Table.validateConvertUpdateSequence(Table.java:845)
at org.h2.command.dml.Insert.insertRows(Insert.java:187)
at org.h2.command.dml.Insert.update(Insert.java:151)
at org.h2.command.CommandContainer.update(CommandContainer.java:198)
at org.h2.command.Command.executeUpdate(Command.java:251)
at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:228)
at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:201)
at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95)
at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java)
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:601)
... 17 more
Caused by: org.h2.message.DbException: Ошибка преобразования данных при конвертации "ROCKET"
Data conversion error converting "ROCKET" [22018-200]
at org.h2.message.DbException.get(DbException.java:194)
at org.h2.value.Value.convertTo(Value.java:875)
at org.h2.value.Value.convertTo(Value.java:772)
at org.h2.value.TypeInfo.cast(TypeInfo.java:515)
at org.h2.table.Column.validateConvertUpdateSequence(Column.java:378)
... 27 more
Caused by: org.h2.jdbc.JdbcSQLDataException: Ошибка преобразования данных при конвертации "ROCKET"
Data conversion error converting "ROCKET" [22018-200]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:457)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)
... 32 more
Caused by: java.lang.NumberFormatException: For input string: "ROCKET"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at org.h2.value.Value.convertToInt(Value.java:982)
at org.h2.value.Value.convertTo(Value.java:806)
... 30 more
Вот сам класс продукт:
package com.example.spacex.entity;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.Id;
@Data
@RequiredArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)
@Entity
public class Product {
@Id
private final String id;
private final String name;
private final Type type;
public static enum Type {
ROCKET, STARSHIP, SUIT, ACCESSORIES
}
}
Ответы (2 шт):
При таком подходе элементы enum в базе будут храниться в виде целочисленного типа, и каждое число будет соответствовать порядку в котором декларированы ваши enum типы в public static enum Type.
Таким образом, если вам нужно вставить элемент ROCKET, выполняйте ваш SQL запрос в следующем виде:
insert into Product (id, name, type) values ('1', 'Falcon 9', '0');
Если вы работаете с БД через JDBC, то вам нужно будет и обработать преобразование полученного числа из столбца type в enum тип, когда будете доставать данные из БД.
Если вам нужно хранить строкой, тогда private final Type type объявите строковым типом. Но этот вариант также подразумевает маппинг полученного значения в enum тип своими силами.
Если используете Spring Data, поставьте аннотацию @Enumerated(EnumType.STRING), т.к. по умолчанию будет выбран механизм EnumType.ORDINAL
Для того чтобы Hibernate хранил enum-ы как текст, а не порядковый номер, нужно использовать аннотацию @Enumerated
@Enumerated(EnumType.STRING)
private final Type type;