Eu trabalhei nesta questão de alguns ângulos e aqui estão minhas descobertas. Advertência:Eu fiz todas essas investigações usando o MyBatis-3.1.1, então as coisas podem ter se comportado de forma diferente nas versões anteriores.
Primeiro, MyBatis tem um
EnumTypeHandler
embutido . Por padrão, sempre que você especificar uma enumeração Java como resultType ou parameterType, é isso que tratará esse tipo. Para consultas, ao tentar converter um registro de banco de dados em uma enumeração Java, o EnumTypeHandler recebe apenas um argumento e tenta pesquisar o valor da enumeração Java que corresponde a esse valor. Um exemplo ilustrará melhor. Suponha que sua consulta acima retorne
2
e "Ready"
quando passo "Ready" como argumento. Nesse caso, recebo a mensagem de erro No enum constant com.foo.Status.2
. Se eu inverter a ordem da sua instrução SELECT para ser SELECT ls.name, ls.id
então a mensagem de erro é
No enum constant com.foo.Status.Ready
. Suponho que você possa inferir o que MyBatis está fazendo. Observe que o EnumTypeHandler está ignorando o segundo valor retornado da consulta. Alterando sua consulta para
SELECT UPPER(ls.name)
faz com que funcione:a enumeração Status.READY é retornada.
Então, em seguida, tentei definir meu próprio TypeHandler para o Status enum. Infelizmente, assim como o padrão
EnumTypeHandler
, eu só poderia obter um dos valores (id ou name) para referenciar o Enum correto, não ambos. Portanto, se o ID do banco de dados não corresponder ao valor que você codificou acima, você terá uma incompatibilidade. Se você garantir que o id do banco de dados sempre corresponda ao id especificado na enumeração, tudo o que você precisa do banco de dados é o nome (convertido para maiúsculas). Então eu pensei em ficar esperto e implementar um MyBatis ObjectFactory, pegar o int id e o nome da String e garantir que eles correspondam no Java enum que eu passo de volta, mas isso não funcionou, pois MyBatis não chama o ObjectFactory para um Java enum type (pelo menos não consegui fazê-lo funcionar).
Portanto, minha conclusão é que enums Java no MyBatis são fáceis, desde que você só precise corresponder o nome do banco de dados ao nome da constante enum - use o EnumTypeHandler integrado ou defina o seu próprio se estiver fazendo UPPER (name) no SQL não é suficiente para corresponder aos nomes de enumeração Java. Em muitos casos, isso é suficiente, pois o valor enumerado pode ser apenas uma restrição de verificação em uma coluna e possui apenas o valor único, não um id também. Se você também precisar corresponder um id int, bem como um nome, faça com que os IDs correspondam manualmente ao configurar a enumeração Java e/ou as entradas do banco de dados.
Finalmente, se você quiser ver um exemplo funcional disso, veja o koan 23 dos meus koans do MyBatis aqui:https://github.com/midpeter444/mybatis-koans . Se você quiser apenas ver minha solução, procure no diretório completed-koans/koan23. Eu também tenho um exemplo de inserção de um registro no banco de dados por meio de uma enumeração Java.