2015-04-29 6 views
8

JDBI supporta il binding dei tipi di enumerazione tramite annotazione?È possibile utilizzare @Bind con enumerazione e altri tipi arbitrari utilizzando JDBI?

Ad esempio, ipotizzando un DAO che ha incluso un metodo:

@SqlQuery("select count(*) from answer a where a.foo = :foo") 
Long someSqlQuery(@Bind("foo") Foo foo); 

E, foo pari a Foo.BAR, potrebbe mi aspetto una query:

select count(*) from answer a where a.foo = 'BAR' 

Se è così, è toString() utilizzata per determinare cosa è sostituito?

Inoltre, JDBI consente di utilizzare @Bind con qualsiasi tipo che si estende Object? E ancora, se è così, è toString() usato?

+0

Come commento successivo, la mia esperienza con 2.5.1 è che "Enum" si comporta nel modo in cui descrivo sopra. Detto questo, ho visto anche qualche strano comportamento, attorno a questo, probabilmente a causa di versioni JDBI in conflitto localmente. Speravo che qualcuno potesse indicarmi la documentazione relativa a questa funzione (vedo solo la documentazione che mostra 'Stringhe', tipi primitivi e 'Date') e un'indicazione di quale versione è consentita per usare' @ Bind' con 'enum'. – vpiTriumph

risposta

9

Secondo il source codeEnum.name() viene utilizzato, non toString()

Se un oggetto è legato, jdbi utilizza setObject(Object object) del driver JDBC che si sta utilizzando. Nella mia esperienza con PostgreSQL, ad esempio, associa con successo Map a hstore e array a postgreSQL array s perché questo è ciò che fa il driver jdbc di PostgreSQL.

Se si desidera gestire un particolare tipo di oggetti in un modo specifico, è possibile implementare ArgumentFactory s (per il quale non sembra esserci alcuna documentazione, ma un esempio qui in Stack Overflow) o BinderFactory s (che ho appena scoperto ora.)

+0

Nota rapida: è necessario JDBI 2.56 o successivo per eseguire il binding di Enums. Non è stato fino a questo punto che "EnumArgument" è stato aggiunto come uno dei tipi di "Argomento" di default. Quindi, prima di ciò, dovrai creare tu stesso le funzionalità creando un 'EnumArgument' e un' EnumArgumentFactory'. – vpiTriumph

+0

Ah si. In realtà, prima ho avuto un sacco di 'getEnumName()' hack per aggirarlo che ho rimosso in seguito. – Natan

0

Per rispondere alla domanda "Tipi arbitrari", è possibile implementare un BinderFactory da associare a tutto ciò che si desidera.

@BindingAnnotation(UserBinder.UserBinderFactory.class) 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.PARAMETER}) 
public @interface UserBinder { 
    public static class UserBinderFactory implements BinderFactory { 

     @Override 
     public Binder build(Annotation annotation) { 
      return new Binder<UserBinder, User>() { 
       @Override 
       public void bind(SQLStatement<?> q, UserBinder bind, User arg) { 
        q.bind("userId", arg.getUserId()); 
        q.bind("uuid", arg.getUuid()); 
        q.bind("openId", arg.getOpenId()); 
        q.bind("givenName", arg.getGivenName()); 
        // etc. 
       } 
      }; 
     } 
    } 
} 

Questo è molto utile se si dispone di tipi complessi che si desidera memorizzare in un modo particolare, ad es. dati binari o raccolte che si desidera convertire in CSV o memorizzate solo in tabelle di mapping separate. Quindi si utilizza il nuovo legante fantasia in questo modo:

@SqlUpdate(
     "INSERT INTO user (openId,givenName,uuid," + 
     // etc. 
     ") VALUES (:openId,:givenName,:uuid" + 
     // etc. 
     ")" 
) 
public abstract int createUser(
     @UserBinder User user 
); 

È inoltre possibile utilizzare un @BindBean annotazione, che sarà automaticamente cercare campi su un oggetto dal nome del parametro bind (ad esempio, si può mappare un segnaposto interrogazione ":userId" al Metodo getUserId()).

+1

Risposta piacevole, ma fornire un esempio che in realtà non va oltre quello che l'implementazione predefinita 'BindBean' fa è un po 'confuso. – Madbreaks

Problemi correlati