简体   繁体   English

spring 数据 jdbc。 无法为枚举添加自定义转换器

[英]spring data jdbc. Can't add custom converter for enum

I want to have enum as a field for my entity.我想将枚举作为我的实体的字段。

My application is look like:我的应用程序看起来像:

Spring boot version Spring开机版

plugins {
        id 'org.springframework.boot' version '2.3.4.RELEASE' apply false

repository:存储库:

@Repository
public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, UUID> {
 ...

entity:实体:

@Table("my_entity")
public class MyEntity{
   ...
   private FileType fileType;
  // get + set
}

enum declaration:枚举声明:

public enum FileType {
    TYPE_1(1),
    TYPE_2(2);

    int databaseId;

    public static FileType byDatabaseId(Integer databaseId){
        return Arrays.stream(values()).findFirst().orElse(null);
    }
    FileType(int databaseId) {
        this.databaseId = databaseId;
    }

    public int getDatabaseId() {
        return databaseId;
    }
}

My attempt:我的尝试:

I've found following answer and try to follow it: https://stackoverflow.com/a/53296199/2674303我找到了以下答案并尝试关注它: https://stackoverflow.com/a/53296199/2674303

So I've added bean所以我加了豆

@Bean
public JdbcCustomConversions jdbcCustomConversions() {
    return new JdbcCustomConversions(asList(new DatabaseIdToFileTypeConverter(), new FileTypeToDatabaseIdConverter()));
}

converters:转换器:

@WritingConverter
public class FileTypeToDatabaseIdConverter implements Converter<FileType, Integer> {
    @Override
    public Integer convert(FileType source) {
        return source.getDatabaseId();
    }
}

@ReadingConverter
public class DatabaseIdToFileTypeConverter implements Converter<Integer, FileType> {
    @Override
    public FileType convert(Integer databaseId) {
        return FileType.byDatabaseId(databaseId);
    }
}

But I see error:但我看到错误:

The bean 'jdbcCustomConversions', defined in class path resource [org/springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class], could not be registered.无法注册在 class 路径资源 [org/springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class] 中定义的 bean 'jdbcCustomConversions'。 A bean with that name has already been defined in my.pack.Main and overriding is disabled.已在 my.pack.Main 中定义了具有该名称的 bean,并且禁用了覆盖。

I've tried to rename method jdbcCustomConversions() to myJdbcCustomConversions() .我试图将方法jdbcCustomConversions()重命名为myJdbcCustomConversions() It helped to avoid error above but converter is not invoked during entity persistence and I see another error that application tries to save String but database type is bigint.它有助于避免上述错误,但在实体持久性期间未调用转换器,我看到另一个错误,即应用程序尝试保存 String 但数据库类型为 bigint。

20:39:10.689  DEBUG  [main] o.s.jdbc.core.StatementCreatorUtils: JDBC getParameterType call failed - using fallback method instead: org.postgresql.util.PSQLException: ERROR: column "file_type" is of type bigint but expression is of type character varying
  Hint: You will need to rewrite or cast the expression.
  Position: 174 

I also tried to use the latest(currently) version of spring boot:我还尝试使用 spring 引导的最新(当前)版本:

id 'org.springframework.boot' version '2.6.2' apply false

But it didn't help.但这没有帮助。

What have I missed?我错过了什么? How can I map enum to integer column properly?如何正确地将 map 枚举到 integer 列?

Try the following instead:请尝试以下操作:

@Bean
public AbstractJdbcConfiguration jdbcConfiguration() {
    return new MySpringBootJdbcConfiguration();
}

static class MySpringBootJdbcConfiguration extends AbstractJdbcConfiguration {
    @Override
    protected List<?> userConverters() {
        return List.of(new DatabaseIdToFileTypeConverter(), new FileTypeToDatabaseIdConverter());
    }
}

Explanation:解释:

Spring complains that JdbcCustomConversions in auto-configuration class is already defined (by your bean) and you don't have bean overriding enabled. Spring 抱怨自动配置JdbcCustomConversions中的 JdbcCustomConversions 已经定义(由您的 bean)并且您没有启用 bean 覆盖。

JdbcRepositoriesAutoConfiguration has changed a few times, in Spring 2.6.2 it has: JdbcRepositoriesAutoConfiguration已经改变了几次,在 Spring 2.6.2 它有:

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(AbstractJdbcConfiguration.class)
static class SpringBootJdbcConfiguration extends AbstractJdbcConfiguration {

}

In turn, AbstractJdbcConfiguration has:反过来, AbstractJdbcConfiguration具有:

@Bean
public JdbcCustomConversions jdbcCustomConversions() {

    try {

        Dialect dialect = applicationContext.getBean(Dialect.class);
        SimpleTypeHolder simpleTypeHolder = dialect.simpleTypes().isEmpty() ? JdbcSimpleTypes.HOLDER
                : new SimpleTypeHolder(dialect.simpleTypes(), JdbcSimpleTypes.HOLDER);

        return new JdbcCustomConversions(
                CustomConversions.StoreConversions.of(simpleTypeHolder, storeConverters(dialect)), userConverters());

    } catch (NoSuchBeanDefinitionException exception) {

        LOG.warn("No dialect found. CustomConversions will be configured without dialect specific conversions.");

        return new JdbcCustomConversions();
    }
}

As you can see, JdbcCustomConversions is not conditional in any way, so defining your own caused a conflict.如您所见, JdbcCustomConversions是有条件的,因此定义自己的会导致冲突。 Fortunately, it provides an extension point userConverters() which can be overriden to provide your own converters.幸运的是,它提供了一个扩展点userConverters()可以覆盖它以提供您自己的转换器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM