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 nelle applicazioni java, configurazione e implementazione

          Scritto: Maryna Pylnyk, 17/01/2017     

Per tanti anni ho scritto query SQL direttamente nel codice, ciò risultava poco efficiente e, per come la penso ora, poco professionale.
Il contenuto di questo articolo è il frutto dell'esperienza personale avuta col framework MyBatis.
Lo scopo non è descrivere la teoria, che potete comunque trovare su internet, ma mostrare un uso pratico di questo strumento.
Inizialmente usavo Ibatis-mapping, sostituito dopo un paio di anni con il suo "fork" MyBatis. MyBatis effettua il mapping (ovvero definisce la corrispondenza) tra i metodi java (o anche di altre piattaforme, per esempio DotNet) e le query SQL. E' bene ricordare che l'efficacia delle query SQL rimane sempre a carico del programmatore.
Negli ultimi anni uso Mysql come database, perciò illustrerò la procedura facendo riferimento a questo RDBMS.
Dunque, vediamo come si configura nel nostro progetto MyBatis+Mysql.

Come primo passo dobbiamo includere nella nostra applicazione (progetto) le seguenti librerie:
  • mysql-connector-java-x.x.x-bin.jar
    (5.1.40 al momento della scrittura dell'articolo). Se usate un altro fork del MySql classico come MariaDb, la libreria da includere sarà
    mariadb-java-client-x.x.x.jar
    (1.5.6 al momento della scrittura dell'articolo)
  • mybatis-x.x.x.jar
    (3.2.8 al momento della scrittura dell'articolo)


File di configurazione MyBatis+Mysql

E' chiaro che deve esserci un file dove si trova la configurazione necessaria per accedere al database e connettersi al framework MyBatis. Questo file è un file xml con una specifica struttura, nel mio progetto è SqlMapConfig.xml (il nome del file può essere diverso).
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- Non dimenticare di includere l'informazione qui sopra per un corretto funzionamento! -->
<configuration>
   <!-- Il file dove si trovano i parametri per la configurazione del database -->
    <properties resource="SqlMapConfig.properties"/> 
<environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> <!-- di seguito ci sono i parametri che uso di solito quando accedo al database attraverso il pool --> <property name="poolMaximumActiveConnections" value="10" /> <property name="poolMaximumIdleConnections" value="2" /> <property name="poolMaximumCheckoutTime" value="120000" /> <property name="poolTimeToWait" value="10000" /> <property name="poolPingQuery" value="select 1" /> <property name="poolPingEnabled" value="true" /> <property name="poolPingConnectionsNotUsedFor" value="900000" /> </dataSource> </environment> </environments> <mappers> <mapper resource="<package>/<Name File with SQL queries>.xml" /> </mappers> </configuration>

Come abbiamo visto, i parametri per l'accesso al database si trovano nel file <SqlMapConfig.properties>.
Questo è il suo contenuto:
# Database access parameters
# Mysql access parameters
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://<host alias>:3306/<Name of Database>?zeroDateTimeBehavior=round&
useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
# MariaDb access parameters
#driver = org.mariadb.jdbc.Driver
#url = jdbc:mariadb://<host alias>:3306/<Name of Database>?zeroDateTimeBehavior=round&
useUnicode=true&characterEncoding=UTF-8&autoReconnect=true

username = <username>
password = <password>

Pubblicita'
Potete notare come i parametri driver, url, username, password nel file SqlMapConfig.xml siano specificati da chiavi nel file SqlMapConfig.properties
Vi potreste domandare il perchè non utilizzare tutti questi parametri direttamente nel file principale. Certo che si possono indicare sia il driver, sia l'url, sia altri parametri nel file SqlMapConfig.xml. Qui descrivo il modo che uso io di solito, che mi permette di configurare anche altre informazioni o addirittura di cifrarle.
Nella stringa "url" indico di solito l'alias del server database che poi specifico nel file hosts ("/etc/hosts" in Linux, e "C:\Windows\System32\Drivers\etc\hosts" in Windows).
Il file SqlMapConfig.properties lo metto sotto "src/", come anche il file SqlMapConfig.xml.
Un altro importante dettaglio riguarda il tag <mappers>. Esattamente qui, dentro questo tag, si trovano tutti i mappers. E' importante indicare il loro corretto posizionamento all'interno del file system del vostro progetto. Personalmente preferisco posizionare tutti i mappers in una directory sotto src/.
Il file di configurazione ha anche altri tag che possono essere utili, come, ad esempio, <typeAliases>. Approfondirò più avanti l'uso di questo tag. Comunque, per una configurazione di base, quanto visto qui sopra è sufficiente.

Adesso vediamo la parte di implementazione in java.

Implementazione java

Il seguente è un esempio di classe di connessione al database.
    // Classe - singleton DatabaseInstance.java
    private static DatabaseInstance instance = null;

    Nel costruttore aggiungiamo:

    try (Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml")) {
        setFactory(new SqlSessionFactoryBuilder().build(reader));
    } catch (Exception e) {}

    e il metodo:

    /**
     * Method used to create the singleton of the class.
     */
    private static DatabaseInstance getInstance() {
        if (instance == null)
        instance = new DatabaseInstance();
        return instance;
    }

    Adesso siamo pronti ad usare la nostra classe nell'applicazione
    quando dobbiamo accedere al database e eseguire le query SQL.
    Il metodo che possiamo invocare da qualsiasi punto del nostro progetto, può essere
    realizzato con questo codice:

    SqlSession session = null;
    try {
        session = DatabaseInstance.getInstance().getFactory().openSession();
        /* chiamando openSession() senza parametro, apriamo la connessione
        SqlSession сon valore di default NON-AUTOCOMMIT, che va benissimo
        per le query di ricerca, ma se volete effettuare le query
        che modificano i dati del database, dovreste correttamente indicare
        il parametro openSession(true)*/

        List<Object> = session.selectList("selectObjects");
        /* selectObjects, questo è il nome della nostra query, proprio 
        quella che noi dobbiamo indicare nel nostro mapper */

    } catch (Exception e) {
        // si consiglia sempre stampare l'eccezione
    } finally {
        if (session != null)
            session.close();
    }

Pubblicita'
Questi metodi possono contenere tutta la logica di cui avete bisogno, usando le transazioni con il rollback. Tutto dipende dal vostro progetto. E' ovvio che qui possiamo fare non solo query SQL di tipo "select", ma anche "insert", "delete" and "update".
Siamo arrivati al momento di vedere l'implementazione del mapper.

I metodi di implementazione dei mapper

Nel file SqlMapConfig.xml tutti i mapper si trovano sotto il tag <mappers>. Ricordate la nostra stringa?
     <mapper resource="<package>/<Name File with SQL queries>.xml" />
Come possiamo notare, anche il file con le query SQL ha lo stesso formato: xml. Creiamo il file xml e mettiamo le query SQL in questo file. Nell'esempio la nostra query è selectObjects
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="package.Example">
    <select id="selectObjects" resultType="<some Object>">
        select
            <field1>,
            <field2> 
        from <table>
    </select>
</mapper>

L'attributo "id" indica il nome della query e bisogna ricordare che il nome della query SQL deve essere univoco all'interno di un namespace (di cui scriverò più tardi). L'attributo "resultType" contiene l'indicazione di che tipo sarà il nostro risultato. <some Object> può essere qualsiasi oggetto, dai tipi primitivi (come String), al POJO oppure anche JavaBean, e deve corrispondere a quello indicato nel metodo. Questo è uno dei modi di descrivere il legame tra mapper e codice java.
Esiste anche un altro modo per connettersi al mapper da codice java, usando le interfacce, specificate nell'attributo "namespace" (nel modo precedente tale valore non ha importanza). In questo caso, il nostro codice sarà leggermente diverso. Nel namespace dobbiamo indicare il percorso completo del package + il nome della interfaccia. L'interfaccia, a sua volta, deve contenere i metodi che corrispondono a quelli contenuti nel mapper. Ovviamente <resultType> deve corrispondere a quello citato nel metodo dell'interfaccia.
    package <package>

    public interface Example {
        List<Object> selectObjects();
    }

    E' nel nostro metodo che noi chiameremo il mapper in questo modo:

    SqlSession session = null;
    try {
        session = DatabaseInstance.getInstance().getFactory().openSession();
        Example exampleMapper = session.getMapper(Example.class);
	List<Object> listObjects = exampleMapper.selectObjects();
    } catch (Exception e) {
        // si consiglia sempre stampare l'eccezione
    } finally {
        if (session != null)
            session.close();
    }

In alcuni progetti potrei avere la neccessità di connettermi con più di un database (qualche volta sullo stesso server oppure su server differenti). Vorrei descrivere questa configurazione e il suo uso pratico: se vi interessa, leggete qui:
Configurazione di più di un database

Infine, qualche parola sul tag che ho promesso, l'utilissimo tag <typeAliases>. Nella fase di creazione del mapper, dicevamo che il risultato può essere un oggetto di qualsiasi tipo (resultType="<some Object>"). Allora, se l'oggetto, per esempio, è JavaBean, vuol dire che esiste nella vostra struttura del progetto il package contenente la classe JavaBean. Questo significa che ogni volta che le vostre molteplici query avranno come il risultato questo tipo di oggetto, in tutti i mappers dovreste indicare il corretto posizionamento della classe. Cosa succederebbe se un giorno, per qualche motivo (e vi assicuro che può accadere), voleste cambiare il package oppure il nome della classe? Beh, sicuramente sarebbe a vostro carico la modifica del percorso (o il nome della classe) in tutti i mapper (va bene se solo in uno, tutto dipende dalla complessità del vostro progetto). Per semplificare la vita in questo caso si può usare il tag <typeAliases>. Nel file di configurazione indicate l'alias per ogni classe del resultType, poi usate tale alias nel mapper.
File di configurazione SqlMapConfig.xml:

<typeAliases>
  <typeAlias alias="ObjectTest1" type="<package>.Object1"/>
  <typeAlias alias="ObjectTest2" type="<package>.Object2"/>
  <typeAlias alias="ObjectTest3" type="<package>.Object3"/>
</typeAliases>

e il mapper:

<mapper namespace="package.Example">
    <select id="selectObjects" resultType="ObjectTest3">
        select
            <field1>,
            <field2>
            from <table>
    </select>
</mapper>

In conclusione, vorrei sottolineare che l'articolo contiene la struttura di base del mapper. La creazione di uno o più mapper nel vostro progetto (tutto dipende dalla sua complessità) può semplificare sia la manutenzione che la leggibilità.
Per la creazione di query SQL parametrizzate potete leggere 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'