He trabajado en esta cuestión desde un par de ángulos y aquí están mis conclusiones. Advertencia: Hice todas estas investigaciones utilizando MyBatis-3.1.1, por lo que las cosas podrían haberse comportado de manera diferente en versiones anteriores.
Primero, MyBatis tiene incorporado EnumTypeHandler
. De forma predeterminada, cada vez que especifique una enumeración Java como resultType o parameterType, esto es lo que manejará ese tipo. Para las consultas, al tratar de convertir un registro de la base de datos en una enumeración Java, EnumTypeHandler solo toma un argumento e intenta buscar el valor enum de Java que corresponde a ese valor.
Un ejemplo lo ilustrará mejor. Supongamos que su consulta anterior devuelve 2
y "Ready"
cuando paso "Listo" como argumento. En ese caso, recibo el mensaje de error No enum constant com.foo.Status.2
. Si invierto el orden de la instrucción SELECT para ser
SELECT ls.name, ls.id
continuación, el mensaje de error es No enum constant com.foo.Status.Ready
. Supongo que puedes deducir lo que está haciendo MyBatis. Tenga en cuenta que EnumTypeHandler está ignorando el segundo valor devuelto por la consulta.
Cambiar su consulta a
SELECT UPPER(ls.name)
provoca que funcione: se devuelve la enumeración Status.READY.
A continuación, traté de definir mi propio TypeHandler para Status enum. Desafortunadamente, como con el valor predeterminado EnumTypeHandler
, solo pude obtener uno de los valores (id o name) para hacer referencia al Enum correcto, no a ambos. Entonces, si la identificación de la base de datos no coincide con el valor que codificó anteriormente, entonces tendrá una discrepancia. Si se asegura de que el ID de la base de datos siempre coincide con el ID que especifica en la enumeración, todo lo que necesita de la base de datos es el nombre (convertido a mayúsculas).
Luego pensé que sería inteligente e implementaría MyBatis ObjectFactory, tomaría el ID int y el nombre de la cadena y me aseguraría de que coincidan en la enumeración Java que devuelvo, pero eso no funcionó ya que MyBatis no llama ObjectFactory para un tipo de enumeración Java (al menos no pude hacer que funcione).
Así que mi conclusión es que las enumeraciones de Java en MyBatis son sencillas siempre que solo tenga que hacer coincidir el nombre de la base de datos con el nombre de la constante enum; utilice el EnumTypeHandler integrado o defina el suyo propio haciendo UPPER (nombre) en el SQL no es suficiente para que coincida con los nombres enum de Java. En muchos casos, esto es suficiente, ya que el valor enumerado puede ser simplemente una restricción de verificación en una columna y solo tiene el valor único, no una identificación también.Si también necesita hacer coincidir un ID int y un nombre, haga que los ID coincidan de forma manual al configurar el enum de Java y/o las entradas de la base de datos.
Finalmente, si desea ver un ejemplo de esto, vea koan 23 de mis koans MyBatis aquí: https://github.com/midpeter444/mybatis-koans. Si solo quiere ver mi solución, busque en el directorio completado-koans/koan23. También tengo un ejemplo de insertar un registro en la base de datos a través de una enumeración de Java.
ISTM que setId() en una enumeración es una idea terrible ... :) –