Jeg har arbejdet med dette spørgsmål fra et par vinkler, og her er mine resultater. Advarsel:Jeg lavede alle disse undersøgelser ved hjælp af MyBatis-3.1.1, så tingene kunne have opført sig anderledes i tidligere versioner.
For det første har MyBatis en indbygget EnumTypeHandler
. Som standard, hver gang du angiver en Java-enum som en resultType eller parameterType, er det dette, der håndterer den type. For forespørgsler, når du prøver at konvertere en databasepost til en Java-enum, tager EnumTypeHandler kun ét argument og forsøger at slå Java-enum-værdien op, der svarer til denne værdi.
Et eksempel vil bedre illustrere. Antag, at din forespørgsel ovenfor returnerer 2
og "Ready"
når jeg indsætter "Klar" som argument. I så fald får jeg fejlmeddelelsen No enum constant com.foo.Status.2
. Hvis jeg vender om rækkefølgen af din SELECT-sætning til at være
SELECT ls.name, ls.id
så er fejlmeddelelsen No enum constant com.foo.Status.Ready
. Jeg går ud fra, at du kan udlede, hvad MyBatis laver. Bemærk, at EnumTypeHandler ignorerer den anden værdi, der returneres fra forespørgslen.
Ændring af din forespørgsel til
SELECT UPPER(ls.name)
får det til at virke:Status.READY enum returneres.
Så dernæst prøvede jeg at definere min egen TypeHandler for Status enum. Desværre, som med standard EnumTypeHandler
, Jeg kunne kun få en af værdierne (id eller navn) for at referere til den rigtige Enum, ikke begge. Så hvis database-id'et ikke matcher den værdi, du har kodet ovenfor, vil du have en uoverensstemmelse. Hvis du sikrer, at database-id'et altid matcher det id, du angiver i enum, så er alt hvad du behøver fra databasen navnet (konverteret til store bogstaver).
Så tænkte jeg, at jeg ville blive klog og implementere en MyBatis ObjectFactory, få fat i både int-id'et og String-navnet og sikre, at de matches i Java-oversigten, jeg sender tilbage, men det virkede ikke, da MyBatis ikke kalder ObjectFactory for en Java enum type (jeg kunne i hvert fald ikke få det til at virke).
Så min konklusion er, at Java-enums i MyBatis er nemme, så længe du blot skal matche navnet fra databasen til enum-konstanten-navnet - enten brug den indbyggede EnumTypeHandler eller definer din egen, hvis du laver UPPER(name) i SQL er ikke nok til at matche Java-enum-navnene. I mange tilfælde er dette tilstrækkeligt, da den opregnede værdi måske blot er en kontrolbegrænsning på en kolonne, og den har kun den enkelte værdi, ikke også et id. Hvis du også skal matche et int-id såvel som et navn, så få ID'erne til at matche manuelt, når du opsætter Java-enum og/eller databaseposter.
Til sidst, hvis du gerne vil se et fungerende eksempel på dette, kan du se koan 23 af mine MyBatis koans her:https://github.com/midpeter444/mybatis-koans . Hvis du bare vil se min løsning, så kig i mappen completed-koans/koan23. Jeg har også et eksempel der på at indsætte en post i databasen via en Java-enum.