MyBatis enum type handler only works for either reads or writes, not both

204 views Asked by At

I have a spring boot project using mybatis 3.5.9 and I'm trying to add a custom type handler for an enum that looks like

public enum Foo {
  VALUE_A("A"),
  VALUE_B("B");

  String value;
  //getters and such...
}

I added mybatis.type-handlers-package to application properties

The handler is a pretty standard

@MappedTypes(Foo.class)
public class FooHandler implements TypeHandler<Foo> {
//the usual setParameter and getResult overrides
}

When reading data this works fine, I can put a breakpoint in the handler and I see that it's being used and I get my enum. When writing, however, the type handler isn't being used, mybatis is trying to write the full "VALUE_A" to the DB column.

On the other hand, if I annotate it with the mapped JDBC type like

@MappedTypes(Foo.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class FooHandler implements TypeHandler<Foo> {
//the usual setParameter and getResult overrides
}

Then writing works fine but reading doesn't. I can solve the problem by getting rid of the jdbc type annotation and sticking an explicit typeHandler=com.example.FooHandler} into every SQL statement, but I have a lot of mappers and really this should just work globally, shouldn't it?

1

There are 1 answers

0
Egor On

It looks like I ran into a MyBatis bug, where enums don't play nice if they override some method, like so

public enum Foo {
  VALUE_A("A"),
  VALUE_B("B") {
    public String bar() {
      return "I am NOT a teapot";
    }
  };

  String value;

  public String bar() {
    return "I am a teapot";
  }

}

After much experimenting, I realized that VALUE_A works without issues, both reading from and writing to the database. I don't need the @MappedJdbcTypes annotation at all. VALUE_B on the other hand breaks everything. I refactored the enum and moved the method out to a utility class and life is good now.