Ik heb vanuit een aantal invalshoeken aan deze vraag gewerkt en hier zijn mijn bevindingen. Waarschuwing:ik heb al deze onderzoeken gedaan met MyBatis-3.1.1, dus het kan zijn dat de dingen zich in eerdere versies anders hebben gedragen.
Ten eerste heeft MyBatis een ingebouwde EnumTypeHandler
. Elke keer dat u een Java-enum opgeeft als resultType of parameterType, is dit standaard wat dat type zal verwerken. Voor query's, bij het converteren van een databaserecord naar een Java-enum, neemt de EnumTypeHandler slechts één argument en probeert de Java-enumeratiewaarde op te zoeken die overeenkomt met die waarde.
Een voorbeeld zal het beter illustreren. Stel dat uw zoekopdracht hierboven 2
retourneert en "Ready"
wanneer ik "Ready" als argument doorgeef. In dat geval krijg ik de foutmelding No enum constant com.foo.Status.2
. Als ik de volgorde van je SELECT-instructie omdraai om
SELECT ls.name, ls.id
dan is de foutmelding No enum constant com.foo.Status.Ready
. Ik neem aan dat je kunt afleiden wat MyBatis aan het doen is. Merk op dat de EnumTypeHandler de tweede waarde negeert die door de query wordt geretourneerd.
Uw zoekopdracht wijzigen in
SELECT UPPER(ls.name)
zorgt ervoor dat het werkt:de Status.READY-enum wordt geretourneerd.
Dus vervolgens probeerde ik mijn eigen TypeHandler te definiëren voor de Status-enum. Helaas, net als bij de standaard EnumTypeHandler
, Ik kon maar een van de waarden (id of naam) krijgen om naar de juiste Enum te verwijzen, niet naar beide. Dus als de database-ID niet overeenkomt met de waarde die u hierboven hardcoded hebt gegeven, heeft u een mismatch. Als u ervoor zorgt dat het database-ID altijd overeenkomt met het ID dat u opgeeft in de opsomming, dan heeft u alleen de naam van de database nodig (omgezet naar hoofdletters).
Toen dacht ik dat ik slim zou worden en een MyBatis ObjectFactory zou implementeren, zowel de int id als de String-naam zou pakken en ervoor zou zorgen dat deze overeenkomen in de Java-enum die ik teruggeef, maar dat werkte niet omdat MyBatis de ObjectFactory niet aanroept voor een Java-enum-type (ik kreeg het tenminste niet werkend).
Dus mijn conclusie is dat Java-enums in MyBatis eenvoudig zijn, zolang je alleen de naam uit de database hoeft te matchen met de naam van de enum-constante - gebruik ofwel de ingebouwde EnumTypeHandler of definieer je eigen als je UPPER(name) doet in de SQL is niet voldoende om overeen te komen met de Java-opsommingsnamen. In veel gevallen is dit voldoende, omdat de opgesomde waarde slechts een controlebeperking voor een kolom kan zijn en alleen de enkele waarde heeft, niet ook een id. Als u zowel een int-id als een naam moet matchen, zorg er dan voor dat de ID's handmatig overeenkomen bij het instellen van de Java-enum en/of database-items.
Tot slot, als je hier een werkend voorbeeld van wilt zien, zie koan 23 van mijn MyBatis-koans hier:https://github.com/midpeter444/mybatis-koans . Als je alleen mijn oplossing wilt zien, kijk dan in de directory Completed-koans/koan23. Ik heb daar ook een voorbeeld van het invoegen van een record in de database via een Java-enum.