{"id":12262,"date":"2017-02-10T10:24:29","date_gmt":"2017-02-10T09:24:29","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=12262"},"modified":"2017-02-10T10:36:00","modified_gmt":"2017-02-10T09:36:00","slug":"mongodb-e-java-facciamoli-interagire","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/mongodb-e-java-facciamoli-interagire\/","title":{"rendered":"MongoDB e Java: facciamoli interagire"},"content":{"rendered":"<p>In articoli precedenti apparsi su questo sito abbiamo gi\u00e0 fatto la conoscenza di MongoDB e l&#8217;abbiamo visto in azione congiunta con Node.js. Parliamo di uno dei DBMS pi\u00f9 utilizzati al mondo ed il pi\u00f9 diffuso\u00a0dell&#8217;emisfero NoSQL. Orientato ai documenti, offre la possibilit\u00e0 di immagazzinare i dati in formato JSON, pensandoli gi\u00e0 come oggetti: ci\u00f2 lo rende rapidamente integrabile nelle nostre applicazioni ed il driver Java che mostriamo oggi offre interessanti possibilit\u00e0 di impiego.<\/p>\n<h2>Iniziare il progetto: integrare il driver per MongoDB<\/h2>\n<p>Supponiamo di avere a disposizione un&#8217;installazione funzionante di MongoDB come abbiamo spiegato negli articoli precedenti. Il nostro progetto Java dovr\u00e0 interagirvi e, per questo, sar\u00e0 necessario integrare il driver. Potremo partire\u00a0dalla pagina dei <a href=\"http:\/\/mongodb.github.io\/mongo-java-driver\/?_ga=1.198351663.1495278578.1468790851\" target=\"_blank\">download\u00a0<\/a>dove troveremo le opportune informazioni sia per farlo tramite\u00a0un tool di <em>build automation<\/em> come Maven (solitamente integrato nei pi\u00f9 comuni IDE) sia, in maniera pi\u00f9 tradizionale, procedendo\u00a0allo scaricamento della libreria in formato jar.<\/p>\n<h2>L&#8217;esempio<\/h2>\n<p>Il nostro esempio mostrer\u00e0 l&#8217;invio di comandi al database\u00a0per\u00a0popolarlo ed interrogarlo direttamente senza tediosi preamboli come la progettazione della struttura interna.<\/p>\n<p>Supponiamo di dover gestire un sistema remoto che funga da banca dati centralizzata per le casse di\u00a0pagamento collocate in\u00a0attivit\u00e0\u00a0commerciali. Ciascuna\u00a0cassa invier\u00e0 al database ogni nuovo\u00a0importo accompagnato da un\u00a0numero identificativo: consideriamo, per semplicit\u00e0, di avere dieci casse numerate in modo progressivo a partire dalla numero 1. L&#8217;accoppiata di questi due valori sar\u00e0 salvata in un documento, concetto che in MongoDB equivale al\u00a0record di\u00a0un database relazionale.<\/p>\n<p>Il codice che presentiamo dovr\u00e0 creare dei dati di test che potranno essere poi visualizzati sempre nell&#8217;ambito del programma o grazie ad uno strumento di gestione del database come RoboMongo, di cui abbiamo parlato sempre su queste pagine. Il programmino che vedremo qui \u00e8 di puro carattere sperimentale quindi accumuleremo tutte le funzionalit\u00e0 all&#8217;interno di una sola classe, che chiameremo DbManager, e ne useremo un&#8217;altra, contenente solo un <em>main<\/em> per metterne alla prova\u00a0i metodi.<\/p>\n<p>Nella nostra classe DbManager, definiremo alcune costanti ed un paio di membri:<\/p>\n<pre class=\"lang:java decode:true\">class DbManager\r\n{\r\n  private static final String SERVER_IP=\"192.168.100.25\";\r\n  private static final int TCP_PORT=27017;\r\n  private static final int NUM_CASSE=10;\r\n \t\r\n  private MongoClient mongoClient; \r\n  private DB db;\r\n\r\n  ...\r\n}<\/pre>\n<p>Con le costanti forniremo innanzitutto le coordinate di rete ove sar\u00e0 reperibile il nostro server MongoDB in esecuzione mentre NUM_CASSE indicher\u00e0 il numero di casse che il nostro sistema avr\u00e0 a disposizione.<\/p>\n<p>I due membri sono oggetti messi a disposizione direttamente dal driver MongoDB\/Java. <strong>MongoClient<\/strong> \u00e8 l&#8217;oggetto tramite il quale gestiremo tutto il dialogo con il database e avremo a disposizione una connessione. DB \u00e8 la classe che rappresenta il database MongoDB con cui siamo connessi.\u00a0All&#8217;interno del costruttore verranno opportunamente inizializzati:<\/p>\n<pre class=\"lang:java decode:true \">public DbManager(String dbName)\r\n\t{\r\n\t\ttry {\r\n\t\t\tmongoClient = new MongoClient( SERVER_IP, TCP_PORT );\r\n\t\t\tdb = mongoClient.getDB( dbName );\r\n\t\t\tinizializza();\r\n\t\t} catch (UnknownHostException ex) {\r\n\t\t\tSystem.out.println(\"Errore\");\r\n\t\t}\r\n\t}<\/pre>\n<p>Come vediamo, MongoClient stabilisce una connessione e subito viene impiegato per ottenere un riferimento al database il cui nome ci \u00e8 stato passato come parametro formale.<\/p>\n<p>Il metodo <em>inizializza()<\/em>, invocato nel costruttore, crea una serie di dati fittizi ma, al contempo, ci offre la possibilit\u00e0 di vedere al lavoro diversi oggetti del driver MongoDB:<\/p>\n<pre class=\"lang:java decode:true\">private void inizializza()\r\n{\r\n   DBCollection coll = db.getCollection(\"introiti\");\r\n\t\t\r\n   for(int i=1; i&lt;1+NUM_CASSE; i++)\r\n   {\r\n\tint numeroImporti=(int) Math.round((Math.random()*10000)%200);\r\n\tfor(int k=0;k&lt;numeroImporti;k++)\r\n\t{\r\n\t   BasicDBObject voce = new BasicDBObject()\r\n\t\t.append(\"idCassa\", i)\r\n\t\t.append(\"importo\", Math.round((Math.random()*7000)%350));\r\n\t   coll.insert(voce);\r\n        }\r\n\t\t\t\r\n    }\r\n\t\t\r\n}<\/pre>\n<p>Questo codice, bench\u00e8 finalizzato ad un puro esempio, \u00e8 piuttosto esemplificativo. Mostra per prima cosa il concetto di <strong>Collection<\/strong>. Si tratta di un insieme di documenti &#8211; un p\u00f2 la tabella del mondo relazionale &#8211; che viene ottenuta fornendone il nome che in questo caso \u00e8 &#8220;introiti&#8221;. Subito dopo un ciclo <em>for<\/em> attiva il meccanismo per generare dati fittizi ed avremo una iterazione per ogni cassa che dovr\u00e0 essere presente nel database. Per ogni cassa si svolger\u00e0 un altro ciclo\u00a0la cui durata dipender\u00e0 dal numero &#8211; generato casualmente &#8211; di introiti di test che si vogliono inserire. Finalmente, arriviamo all&#8217;oggetto <strong>BasicDBObject<\/strong> che costituisce il documento da salvare. Come si vede l&#8217;approccio ai dati di MongoDB si offre facilmente all&#8217;interazione ad oggetti. Con il metodo <em>append<\/em>, in pratica, inseriamo\u00a0un campo alla volta corrispondente ad una propriet\u00e0 dell&#8217;oggetto JSON con cui viene salvato il documento. Una volta, pronto il nuovo oggetto sar\u00e0 inserito\u00a0nella collection tramite il metodo <em>insert<\/em>.<\/p>\n<h2>Le interrogazioni<\/h2>\n<p>Gli altri metodi che inseriremo nella classe DbManager ci permetteranno di svolgere delle interrogazioni in base ai nostri scopi. Per lo pi\u00f9 dovremo attivare una query su una Collection tramite il metodo <em>find<\/em> e poi fruire dei dati con un <strong>Cursor<\/strong>, un puntatore al set di risultati.\u00a0A <em>find<\/em> potremo passare un oggetto BasicDBObject, che conterr\u00e0 le condizioni per il filtro.<\/p>\n<p>Questo primo metodo eseguir\u00e0 la lettura di tutti i dati relativi ad una cassa:<\/p>\n<pre class=\"lang:java decode:true \">public void trovaPerCassa(int numero)\r\n\t{\r\n\t\tDBCursor cursor=db.getCollection(\"introiti\").find(new BasicDBObject().append(\"idCassa\", numero));\r\n\t\ttry\r\n\t\t{\r\n\t\t\twhile(cursor.hasNext())\r\n\t\t\t{\r\n\t\t\t\tDBObject ob=cursor.next();\r\n\t\t\t\tSystem.out.println((ob.get(\"idCassa\")+\" - \"+ob.get(\"importo\")));\r\n\t\t\t}\r\n\t\t}\r\n\t\tfinally\r\n\t\t{\r\n\t\t\tcursor.close();\r\n\t\t}\r\n\t}<\/pre>\n<p>Come si vede alla prima riga otteniamo un cursore che punta alla collection &#8220;introiti&#8221; \u00a0chiedendo a <em>find<\/em> di cercare tutti gli oggetti che nella propriet\u00e0 <em>idCassa<\/em> abbiano il numero che abbiamo passato in input. Il cursore generato potr\u00e0 essere iterato con i metodi <em>hasNext<\/em> che controlla la presenza di ulteriori documenti da leggere e <em>next<\/em> che legge\u00a0il successivo.<\/p>\n<p>Una volta ottenuto un documento con il metodo <em>next(),<\/em> potremo interrogarne le propriet\u00e0 come una normale mappa. Il tutto verr\u00e0 incluso\u00a0in un costrutto<em> try&#8230;finally<\/em> in modo da ottenere la chiusura del cursore anche in caso di errore.<\/p>\n<p>Abbiamo utilizzato in pratica un oggetto BasicDBObject come una sorta di query in grado di raggruppare le condizioni cui devono rispondere i documenti per poter essere selezionati nel set finale di risultati. La condizione di ricerca che abbiamo utilizzato \u00e8 di uguaglianza: abbiamo infatti richiesto che il numero identificativo della cassa, salvato nel documento, fosse uguale a quello passato al metodo.<\/p>\n<p>Se volessimo cercare tutti gli importi salvati relativi ad una medesima cassa ma di controvalore non inferiore ad un determinato livello dovremmo passare alla nostra query un ulteriore parametro da confrontare con l&#8217;operatore &#8220;maggiore o uguale&#8221;: vediamolo nel prossimo metodo:<\/p>\n<pre class=\"lang:java decode:true\">public void trovaImportiPerCassaConValoreMinimo(int numero, int minimo)\r\n{\r\n   DBObject query=new BasicDBObject()\r\n\t.append(\"idCassa\", numero)\r\n\t.append(\"importo\", new BasicDBObject().append(\"$gte\", minimo));\r\n\t\t\r\n\tDBCursor cursor=db.getCollection(\"introiti\").find(query);\r\n\t\t\r\n\ttry\r\n\t{\r\n\t\twhile(cursor.hasNext())\r\n\t\t{\r\n\t\t   DBObject ob=cursor.next();\r\n\t\t   System.out.println((ob.get(\"idCassa\")+\" - \"+ob.get(\"importo\")));\r\n\t\t}\r\n\t}\r\n\tfinally\r\n\t{\r\n\t\tcursor.close();\r\n\t}\r\n}<\/pre>\n<p>La struttura del metodo \u00e8 analoga a quella del precedente, ci\u00f2 che cambia \u00e8 l&#8217;oggetto BasicDBObject che svolge, ancora una volta, il ruolo di query. La seconda\u00a0invocazione di <em>append<\/em>\u00a0 esegue un controllo sull&#8217;importo verificando che superi il livello riportato dalla variabile di nome <em>minimo<\/em>. La costante &#8220;$gte&#8221; \u00e8\u00a0uno degli <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/operator\/aggregation-comparison\/\" target=\"_blank\">operatori di confronto <\/a>messi a disposizione da MongoDB e\u00a0rappresenta proprio quel concetto di &#8220;maggiore o uguale&#8221; di cui abbiamo bisogno<\/p>\n<h2>Conclusioni<\/h2>\n<p>Per sperimentare questi metodi, possiamo creare un semplicissimo metodo <em>main<\/em> di questo tipo:<\/p>\n<pre class=\"lang:java decode:true\">public class App \r\n{\r\n\t\r\n\t\r\n    public static void main( String[] args )\r\n    {\r\n    \t\r\n    \t\/\/ inizializzazione del sistema con la creazione di dati di prova\r\n    \tDbManager manager=new DbManager(\"importi\");\r\n    \t\r\n    \t\/\/ stampa degli introiti relativi alla cassa n. 2\r\n    \tmanager.trovaPerCassa(2);\r\n    \t\r\n    \t\/* ricerca degli introiti registrati dalla cassa n. 2 \r\n         * di controvalore non inferiore a 123,00 euro\r\n         *\/\r\n    \tmanager.trovaImportiPerCassaConValoreMinimo(2,123);\r\n    }\r\n}<\/pre>\n<p>Il driver che abbiamo iniziato a vedere in questo tutorial permette di integrare velocemente MongoDB nei nostri programmi Java trasformando in persistenti gli oggetti che creiamo nelle nostre strutture dati. Continueremo a sperimentarlo nei prossimi metodi creandogli attorno contesti pi\u00f9 concreti e vedendone ulteriori funzionalit\u00e0.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In articoli precedenti apparsi su questo sito abbiamo gi\u00e0 fatto la conoscenza di MongoDB e l&#8217;abbiamo visto&#8230;<\/p>\n","protected":false},"author":561,"featured_media":12809,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[1530,1526,1652,1529],"class_list":["post-12262","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorial-pratici","tag-database","tag-java","tag-mongodb","tag-nosql"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12262","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/561"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=12262"}],"version-history":[{"count":6,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12262\/revisions"}],"predecessor-version":[{"id":12268,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12262\/revisions\/12268"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media\/12809"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=12262"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=12262"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=12262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}