Cloud with rain
.:G
G:.
0 and 1 serie, black on white
pulled card
myjsp.feelinglinux.com
ver. 1.1.9-4
Hallo, welcome to my world.
Here you can find some stuff about computer science.
<<< Enjoy your visit! >>>
0 and 1 serie, white on black

MyBatis: resultType e resultMap, association e collection

          Scritto: Maryna Pylnyk, 06/02/2017     

Nelle nostre applicazioni che usano MyBatis, le query SQL possono restituire diversi tipi di dati. In questo articolo parlero' di due importanti attributi delle query select: resultType e resultMap. Questi attributi indicano con quale tipo di dato rappresentare il risultato della query.
Notate che non è possibile usare entrambi nella stessa query.
Come ho scritto negli articoli precedenti su MyBatis, resultType puo' essere un qualsiasi oggetto, dai tipi primitivi (String) a POJO e JavaBean.
L'altro attributo e' resultMap e si usa sia quando abbiamo come risultato un oggetto semplice, sia quando ne abbiamo uno con una struttura piu' complessa.

Vediamo degli esempi. Iniziero' con uno semplice, aumentandone progressivamente la complessita'. Come motore del database uso il server MySql.
La nostra tabella del database di esempio, table1, ha la seguente struttura:

mysql> desc table1;
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| id          | int(11)      | NO   | PRI | NULL    |       |
| name        | varchar(25)  | NO   |     | NULL    |       |
| description | varchar(100) | YES  |     | NULL    |       |
+-------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

La classe JаvaBean dal nome GenericBean, che di seguito rappresentera' il risultato (attraverso l'attributo resultType), ha questa struttura:

public class GenericBean{
    private String           idField          = "";
    private String           fieldValue       = "";
    private String           description      = "";

    con i relativi metodi set() e get() per ogni proprieta'.
  
} 

La nostra query nel mapper sara':

   <select id="getList" resultType="somePackage.GenericBean">
       SELECT
           id as idField,
           name as fieldValue,
           description as description
       FROM
           table1             
    </select>
    

Pubblicita'
Possiamo notare che ogni campo della tabella e' mappato nella query con un alias corrispondente ad una proprieta' della classe GenericBean.
Se invece il vostro GenericBean dovesse avere le proprieta' con i nomi che corrispondono ai campi della tabella, potreste semplicemente usare "*" (SELECT * FROM table.....). E' bene pero' considerare il fatto che, durante la fase di programmazione oppure nelle future release, potreste avere l'esigenza di effettuare variazioni nella struttura del vostro database come, per esempio, cambiare il nome di una colonna.

Esiste anche un altro metodo per mappare la classe GenericBean come risultato della query SQL, ovvero usando resultMap

   <select id="getList" resultMap="nameResultMap">
       SELECT
           *
       FROM
           table1             
    </select>


L'attributo resultMap ha come valore il nome di una mappa ("nameResultMap"), la cui struttura mettera' in corrispondenza i campi della tabella con le proprieta' del tipo di dato. Eccone la definizione:

   <resultMap id="nameResultMap" type="somePackage.GenericBean">
        <id column="id" property="idField"  />
        <result column="name" property="fieldValue" />
        <result column="description" property="description" />
   </resultMap>

Ad ogni campo "column" della tabella del database, corrisponde una proprieta' "property" del nostro GenericBean. Questo tipo di risultato e' semplice.
L'elemento "id" ha un ruolo importante. Tutte le tabelle del mio database hanno le chiavi primarie, come penso che sia anche per le tabelle vostre. Allora l'elemento "id" contiene la chiave primaria. Non sarebbe considerato come un errore, se per column="id" usaste il tag "result" (come per gli altri campi).

Supponiamo di dover estrarre, per ogni "id" della nostra tabella table1, l'insieme dei dati di un'altra tabella table2 associati a tale id. Ecco la nostra nuova tabella:
mysql>  desc table2;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| id        | int(11)     | NO   | PRI | NULL    |       |
| table1_id | int(11)     | NO   |     | NULL    |       |
| value     | varchar(15) | NO   |     | NULL    |       |
| field     | varchar(25) | NO   |     | NULL    |       |
| name      | varchar(25) | NO   |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

A questo punto il nostro GenericBean deve avere un'altra proprieta', la chiamiamo valueList. Questa proprita' conterra' la collezione di oggetti OtherBean contenenti i dati della tabella "table2". Aggiungiamo la nuova proprieta' con i relativi metodi get() e set() al nostro GenericBean. Cliccando qui si puo' vedere il nuovo oggetto OtherBean
Proviamo a definire il nuovo tipo di risultato:

      <resultMap id="nameResultMap" type="somePackage.GenericBean" >
            <id column="id" property="idField"  />
            <result column="name" property="fieldValue" />
            <result column="description" property="description" />
		
         <!-- collections of values from table2 -->
            <collection property="valueList" ofType="package.OtherBean"
                       column="id" select="selectValuesList" />
      </resultMap>
      

Ricapitolando, la nostra collection :
  • contiene gli oggetti OtherBean, l'attributo ofType,
  • punta alla proprieta' valueList dell'oggetto GenericBean, l'attributo property,
  • indica la relazione con il campo id della tabella database, l'attributo column,
  • rappresenta il risultato della query selectValuesList attraverso l'attributo select.
Adesso nel mapper dobbiamo aggiungere questa nuova query selectValuesList.
     <select id="selectValuesList" resultType="package.OtherBean">
         SELECT
             id,
             value,
             field,
             name	
         FROM
             table2 
         WHERE
             table1_id = #{id} 
     </select>

collection rappresenta una relazione "uno-a-molti" (one-to-many).

Il tipo "uno-a-uno" e' un tipo di relazione tra i dati piu' semplice, ora lo vedremo. Per realizzare questo tipo useremo association. Aggiungiamo nella nostra tabella table1 il campo table3_id:
+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| id          | int(11)      | NO   | PRI | NULL    |       |
| name        | varchar(25)  | NO   |     | NULL    |       |
| description | varchar(100) | YES  |     | NULL    |       |
| table3_id   | int(11)      | NO   |     | NULL    |       |
+-------------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

Supponiamo di dover trovare, per ogni riga della tabella table1, un'informazione aggiuntiva contenuta nella tabella table3, e che questa informazione sia rappresentata da una sola riga. Cio' vuol dire che la select avra' un solo risultato. Il nuovo campo "table3_id" sara' il campo-legame con la tabella table3:
mysql< desc table3;
+-----------+-------------+------+-----+---------+-------+
| Field     | Type        | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| id        | int(11)     | NO   | PRI | NULL    |       |
| alias     | varchar(15) | NO   |     | NULL    |       |
| title     | varchar(25) | NO   |     | NULL    |       |
| name      | varchar(25) | NO   |     | NULL    |       |
+-----------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

Pubblicita'


Volevo, infine, spendere due parole per quanto riguarda l'informazione aggiuntiva. Tale informazione puo' essere di diversa natura, per esempio, guardando la tabella "table3", potremmo aver bisogno di selezionare solo l'"alias", oppure un oggetto contenente tutti i dati della riga: id+alias+title+name. Nel primo caso possiamo fare a meno del tag association, ed indicare direttamente nella nostra query select principale la subquery che possiamo vedere cliccando qui

Nel secondo caso, dobbiamo per forza usare il tag association.
E' necessario ricordare che il tag association deve essere inserito prima del tag collection.

Aggiungiamo nel GenericBean un'altra proprieta' con i relativi set() e get(): l'oggetto TableThreeBean (possiamo vederlo cliccando qui)

Adesso aggiungiamo:

nel tag del risultato resultMap id="nameResultMap":

         <association property="type" column="table3_id" select="selectFromTable3"/>

nel mapper la nuova query:
     
         <select id="selectFromTable3" resultType="package.TableThreeBean">
             SELECT
                 id,
                 alias,
                 title,
                 name	
             FROM
                 table3 
             WHERE
                 id = #{table3_id} 
         </select>


Osserviamo, che la nostra association :
  • punta alla proprieta' type dell'oggetto TableThreeBean, l'attributo property,
  • indica la relazione con il campo table3_id della tabella database, l'attributo column,
  • rappresenta il risultato della query selectFromTable3, l'attributo select, dove e' stato indicato il tipo dell'oggetto (TableThreeBean) attraverso l'attributo resultType.

Se i campi nelle tabelle non dovessero corrispondere alle proprieta' del vostro oggetto, potreste sempre usare l'attributo resultMap al posto di resultType="package.TableThreeBean".
Per quanto riguarda il passaggio dei parametri potete leggete l'articolo
" MyBatis e i parametri nelle query SQL "

Hai trovato utile questo articolo?
Aiutami a condividerlo o metti un "mi piace".
Grazie mille!


Gli strumenti di condivisione (Google+, Facebook) sono visibili in alto a destra solo dopo aver accettato la policy di utilizzo dei cookie per questo sito.
FAQ - Come faccio a cambiare la mia scelta?

 

Strumenti (myjsp.feelinglinux.com)
Gioco: allenamento con la tastiera Strumenti di codifica/decodifica URI (%-encoding) e Base64 Strumenti di calcolo online per IP e Reti
QUIZ GAME
Quiz game

Cerca @myjsp.feelinglinux.com

Pubblicita'