Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable converting enums to integer (built-in or custom converter) [DATAJDBC-408] #629

Closed
spring-projects-issues opened this issue Aug 26, 2019 · 12 comments
Assignees
Labels
status: invalid An issue that we don't feel is valid

Comments

@spring-projects-issues
Copy link

Fábio Coutinho Valente opened DATAJDBC-408 and commented

I'm changing my application from Spring Data JPA to Spring Data JDBC, and I have one column on my table that saves an integer of the ordinal.
According to documentation Spring Data JDBC only allows converting enums to string out of the box. So I tried a workaround with custom converters.

I created a custom converter with @ReadingConverter and could read/convert properly to my enum value according to the integer on my table.
I tried creating a custom converter with @WritingConverter annotation, but its not being executed instead the converter org.springframework.core.convert.support.EnumToStringConverter is being called.
After some debugging I found the map javaToDbType in class BasicRelationalPersistentProperty to be the resposible for that due to this static line

javaToDbType.put(Enum.class, String.class)

If there is no built-in convertion enum to integer, could you allow custom converter to be used instead?
Is there any other way to convert enum values into integer (ordinal number)?


2 votes, 3 watchers

@spring-projects-issues
Copy link
Author

Jens Schauder commented

Thanks for raising this.

If we would handle Enum values with a CustomConversion by default which could be replaced at configuration time this should be possible and not too difficult to do

@lpgph
Copy link

lpgph commented Jan 9, 2021

I also had this problem. I'm Custom enumeration value ,eg:

public enum StateEnum{
  ACTIVATED(1),
  DEACTIVATED(2);

  StateEnum(Integer value) {
    this.value = value;
  }

  private final Integer value;

  public int getValue() {
    return value;
  }
}

register converter to JdbcCustomConversions

@Slf4j
@WritingConverter
public class StateToIntegerConverter implements Converter<StateEnum,Integer> {
  @Override
  public Integer convert(StateEnum source) {
    return source.getValue();
  }
}

but always use org.springframework.core.convert.support.EnumToStringConverter

Temporary plan

@Slf4j
@WritingConverter
public class StateToIntegerConverter implements Converter<StateEnum,String> {
  @Override
  public String convert(StateEnum source) {
    return String.valueOf(source.getValue());
  }
}

@ahmet-voys
Copy link

ahmet-voys commented Sep 28, 2021

We also hit this issue. We have custom integer values associated with enums. We have custom WriteConverter classes.
But during write, it tries to write the String value instead. Is there any workaround you can suggest?

 @WritingConverter
    static class MyEnumWritingConverter implements Converter<MyEnum, Integer> {

        @Override
        public Integer convert(@NonNull MyEnum e) {
            return e.getDbIndex();
        }
    }

@lesiak
Copy link

lesiak commented Jan 21, 2022

Proposed workaround in Spring-Boot 2.6.2:
https://stackoverflow.com/a/70792020/1570854

mp911de added a commit that referenced this issue Feb 21, 2022
Outline that the usage of this annotation leads to calling Results.getRowsUpdated() to obtain the query method result value.

Closes #629
@schauder
Copy link
Contributor

schauder commented Nov 7, 2022

Thanks for finding this. Yes I think this should be considered resolved.

Leaving it open for a bit for the OP to veto a close.

@schauder
Copy link
Contributor

Closing this as solved as indicated by the comment above.

@peteraramaldes
Copy link

@schauder
Same problem here with spring-data-jdbc:2.4.2
Do we have any updates on this?

@schauder
Copy link
Contributor

We might have closed that prematurely.
@peteraramaldes Can you verify that this issue still exists in Spring Data JDBC 3.x?

@jtkb
Copy link

jtkb commented Nov 5, 2023

This problem exists in Spring Data JDBC and plain Spring JDBC 3.1.5.
Whether using Data-JDBC or plain JDBC ultimately update calls are routed through StatementCreatorUtils.setValue(PreparedStatement ps, int paramIndex, int sqlType, @Nullable String typeName, @Nullable Integer scale, Object inValue)
Dependent upon the type which an particular enum is meant to be mapped (this would need to be explicitly passed through in the parameter map by the client code) this method will generally fail if the object type is of type Enum.

Workaround for Spring JDBC i.e. NOT using CrudRepository<T, ID>

In the above mentioned method inValue is first checked to be of type org.springframework.jdbc.core.SqlTypeValue. This is an interface which can be implemented by any enum. The implementation could therefore set the desired type in the PreparedStatement.

Unfortunately this does not work for Spring Data JDBC because by the time the above method is called Enum types have been cast to type String due to the proxy objects created by Spring Data for each CrudRepository<T, ID>. This casting is done in StringBasedJdbcQuery.convertAndAddParameter. Ultimately it is this call JdbcValue elementJdbcValue = converter.writeJdbcValue(o, actualType.getType(), JdbcUtil.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(actualType.getType())));

Following the code through is can be seen that Enum.class is always mapped to String.class.

Currently I don't know a work around for Spring Data JDBC.

@streZet
Copy link

streZet commented May 15, 2024

Another solution is to use JdbcValue as the target type. Then the writer will look something like this:

@Slf4j
@WritingConverter
public class StateToIntegerConverter implements Converter<StateEnum,JdbcValue> {
  @Override
  public JdbcValue convert(StateEnum source) {
    return JdbcValue.of(source.getValue(), JDBCType.INTEGER);
  }
}

@schauder
Copy link
Contributor

I tried to write a test verifying this problem, but found that there is already a set of test that tests reading, writing and querying enums with custom converters:


So the issue does seem to be resolved as far as I can tell.

If anyone still has an issue with this please create a new issue and provide a reproducer.

@schauder schauder closed this as not planned Won't fix, can't repro, duplicate, stale Jul 11, 2024
@schauder schauder added status: invalid An issue that we don't feel is valid and removed type: bug A general bug labels Jul 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

9 participants