Estoy creando un trabajo por lotes utilizando Spring Primavera de arranque y Hiberna pero estoy experimentando un problema durante la inserción. Esta es la parte relevante del código:
@Bean
public JdbcBatchItemWriter<OphthalmicLens> writer(DataSource dataSource) throws SQLException {
return new JdbcBatchItemWriterBuilder<OphthalmicLens>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO OphthalmicLens (`createdBy`,`createdDate`,`lastModifiedBy`,`lastModifiedDate`,`sid`,`version`,`manufacturer`,`manufacturerCode`,`name`,`sku`,`upc`,`cylinder`,`design`,`diameter`,`index`,`material`,`source`,`sphere`,`type`) VALUES (:createdBy,NOW(),:lastModifiedBy,NOW(),UUID(),:version,:manufacturer,:manufacturerCode,:name,:sku,:upc,:cylinder,:design,:diameter,:index,:material,:source,:sphere,:type)")
.dataSource(dataSource).build();
}
El diseño de la propiedad es una enumeración:
public enum OphthalmicDesign {
SPHERIC, ASPHERIC, ATORIC, BIASPHERIC
}
que se utiliza en mis OphthalmicLens
granos como esto:
@NotNull
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private OphthalmicDesign design = OphthalmicDesign.SPHERIC;
Estoy utilizando MySQL 5.7 y que la columna en la base de datos es Mappes como un VARCHAR (255) como se esperaba.
Cuando ejecuto el trabajo que sale este error:
Caused by: java.sql.BatchUpdateException: Incorrect string value: '\xAC\xED\x00\x05~r...' for column 'design' at row 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_172]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0_172]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_172]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_172]
at com.mysql.cj.util.Util.handleNewInstance(Util.java:210) ~[mysql-connector-java-8.0.11.jar:8.0.11]
at com.mysql.cj.util.Util.getInstance(Util.java:185) ~[mysql-connector-java-8.0.11.jar:8.0.11]
at com.mysql.cj.util.Util.getInstance(Util.java:192) ~[mysql-connector-java-8.0.11.jar:8.0.11]
at com.mysql.cj.jdbc.exceptions.SQLError.createBatchUpdateException(SQLError.java:218) ~[mysql-connector-java-8.0.11.jar:8.0.11]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeBatchedInserts(ClientPreparedStatement.java:768) ~[mysql-connector-java-8.0.11.jar:8.0.11]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeBatchInternal(ClientPreparedStatement.java:444) ~[mysql-connector-java-8.0.11.jar:8.0.11]
at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:839) ~[mysql-connector-java-8.0.11.jar:8.0.11]
at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:128) ~[HikariCP-2.7.9.jar:?]
Entiendo el problema es la enumeración no se convierte en una cadena. Podría resolver el problema con una diferente BeanPropertyItemSqlParameterSourceProvider
, pero creo que sería overkilled y yo perdería ventaja de las instalaciones de la primavera.
¿Tiene una sugerencia para contar Primavera / Hibernate para convertir automáticamente que la enumeración de una cadena, incluso cuando se utiliza Spring Batch?
Se puede indicar al BeanPropertyItemSqlParameterSourceProvider
devolver el VARCHAR
tipo para el campo design
de la siguiente manera:
@Bean
public JdbcBatchItemWriter<OphthalmicLens> writer(DataSource dataSource) throws SQLException {
return new JdbcBatchItemWriterBuilder<OphthalmicLens>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<OphthalmicLens>() {
@Override
public SqlParameterSource createSqlParameterSource(OphthalmicLens item) {
return new BeanPropertySqlParameterSource(item) {
@Override
public int getSqlType(String paramName) {
if (paramName.equalsIgnoreCase("desing")) {
return Types.VARCHAR;
}
return super.getSqlType(paramName);
}
};
}
})
.sql("INSERT INTO OphthalmicLens (`createdBy`,`createdDate`,`lastModifiedBy`,`lastModifiedDate`,`sid`,`version`,`manufacturer`,`manufacturerCode`,`name`,`sku`,`upc`,`cylinder`,`design`,`diameter`,`index`,`material`,`source`,`sphere`,`type`) VALUES (:createdBy,NOW(),:lastModifiedBy,NOW(),UUID(),:version,:manufacturer,:manufacturerCode,:name,:sku,:upc,:cylinder,:design,:diameter,:index,:material,:source,:sphere,:type)")
.dataSource(dataSource)
.build();
}