Jag har arbetat med den här frågan från ett par vinklar och här är mina resultat. Varning:Jag gjorde alla dessa undersökningar med MyBatis-3.1.1, så saker och ting kan ha betett sig annorlunda i tidigare versioner.
För det första har MyBatis en inbyggd EnumTypeHandler
. Som standard, varje gång du anger en Java-enum som en resultType eller parameterType, är det detta som kommer att hantera den typen. För frågor, när man försöker konvertera en databaspost till en Java-enum, tar EnumTypeHandler bara ett argument och försöker slå upp Java-enum-värdet som motsvarar det värdet.
Ett exempel kommer att illustrera bättre. Anta att din fråga ovan returnerar 2
och "Ready"
när jag lägger in "Redo" som argument. I så fall får jag felmeddelandet No enum constant com.foo.Status.2
. Om jag ändrar ordningen på din SELECT-sats så att den blir
SELECT ls.name, ls.id
då är felmeddelandet No enum constant com.foo.Status.Ready
. Jag antar att du kan sluta dig till vad MyBatis gör. Observera att EnumTypeHandler ignorerar det andra värdet som returneras från frågan.
Ändra din fråga till
SELECT UPPER(ls.name)
får det att fungera:Status.READY enum returneras.
Så härnäst försökte jag definiera min egen TypeHandler för Status enum. Tyvärr, som med standard EnumTypeHandler
, Jag kunde bara få ett av värdena (id eller namn) för att referera till rätt Enum, inte båda. Så om databas-id:t inte matchar värdet du hårdkodade ovan, kommer du att ha en oöverensstämmelse. Om du säkerställer att databas-id:t alltid matchar det ID du anger i enumet, behöver du bara namnet från databasen (konverterat till versaler).
Sedan tänkte jag att jag skulle bli smart och implementera en MyBatis ObjectFactory, ta både int id och String-namnet och se till att de matchas i Java-enumet som jag skickar tillbaka, men det fungerade inte eftersom MyBatis inte kallar ObjectFactory för en Java enum typ (åtminstone jag kunde inte få det att fungera).
Så min slutsats är att Java-enums i MyBatis är lätta så länge du bara behöver matcha namnet från databasen till enum-konstanten - använd antingen den inbyggda EnumTypeHandler eller definiera din egen om du gör UPPER(name) i SQL är inte tillräckligt för att matcha Java enum-namnen. I många fall är detta tillräckligt, eftersom det uppräknade värdet bara kan vara en kontrollbegränsning på en kolumn och den har bara det enda värdet, inte ett id också. Om du också behöver matcha ett int-id och ett namn, gör sedan att ID:n matchar manuellt när du ställer in Java-enum och/eller databasposter.
Slutligen, om du vill se ett fungerande exempel på detta, se koan 23 av mina MyBatis koans här:https://github.com/midpeter444/mybatis-koans . Om du bara vill se min lösning, titta i katalogen completed-koans/koan23. Jag har också ett exempel där på att infoga en post i databasen via en Java-enum.