Login
Cerca all'interno di JavaPortal
Help
Home Page Documentazione Forum Progetti Partner Pubblica!
Documentazione > Tutorial > JAKARTA OJB (ObJectRelationalBridge)
Hide
Best Practices
EJB
Frameworks
Howto
J2EE
J2ME and Wireless
J2SE
JSP e Servlet
Java Application Server
Java IDE/Tools
Java Media
Java Security
Java Sys Admin
Java e XML
Java e SQL
OpenSource Java
Patterns
Repository
Tesi
UML
Web Services
Slide
White Paper di jws.it
project management
Eventi
Groovy

Hai una tesi in Java?
Tesine preparate
per esami?
Pubblica tutto su
JavaPortal!

Scrivi al nostro staff


Javaportal media partner per Devoxx


John Fitzgerald Kennedy
L'uomo è il computer più straordinario di tutti


Il motore CMP su JBoss


Rss Feed
Home Page
Articoli
News
Forum
Classi

  Visualizza Commenti (0) Aggiungi Commento    
Add to Shortcuts
 
Vota l'articolo
JAKARTA OJB (ObJectRelationalBridge)
By Andrea Previati
9 settembre 2005
Valutazione Acquisita: 22

  JAKARTA OJB (ObJectRelationalBridge)
Program Da dove iniziare
Program Come usarlo
Program Perche' usarlo
Program I Test
Program Conclusioni

Jakarta OJB è un framework che permette la persistenza trasparente tra oggetti Java e database relazionali.
Questo articolo non vuole rappresentare un vero e proprio Tutorial o una guida all'utilizzo del framework, ma un semplice help nato da esperienze personali per stabilire se OJB può facilitare l'implementazione dell' Integration layer nella vostra applicazione e, eventualmente, iniziare ad utilizzarlo nel più breve tempo possibile.



Da dove iniziare top
DB è un progetto della Apache Software Foundation, la cui missione è la creazione e mantenimento di soluzioni per database commerciali, open source e di alta qualità basate sulla licenza Apache.

I sottoprogetti di DB sono in questo momento tre:Torque, DB Commons e ObJectRelationalBridge - OJB

http://db.apache.org/ojb/ è il sito che da questo momento sarà la vostra nuova dimora, approfittate quindi degli ottimi tutorial della sezione Documentation.

http://mirror.tomato.it/apache/db/ojb/db-ojb-1.0.1/ è il mirror suggerito da Apache per il download della distribuzione.






Come usarlo top

Superato il tempo di startup necessario alla configurazione del framework, OJB necessita sostanzialmente di due oggetti per ogni entità del database:

- un value object  che verrà utilizzato come container dei dati

- un xml descriptor, necessario al framework per conoscere la struttura della tabella ed eseguire il mapping fisico(database) / logico(bean)

Utilizzando Eclipse come IDE, è possibile utilizzare il plugin di Impart (http://www.impart.ch/eng/download.htm) che permette il browsing della base dati direttamente da una View personalizzata e la generazione di oggetti e descrittori.

Rispetto all'utilizzo di Statement e PreparedStatement, l'implementazione mediante il framework permette la totale trasparenza del codice SQL: utilizzando esclusivamente oggetti e metodi per l'interrogazione e l'aggiornamento della base dati, sarebbe per assurdo possibile interagire con qualsiasi DBMS senza conoscere il significato delle keyword SELECT, INSERT, UPDATE, ecc...

I bean devono necessariamente contenere i field relativi ai campi definiti nei descrittori xml; per mantenere la corretta persistenza dei dati e garantire il corretto funzionamento dell'SQL generator, la tipizzazione degli oggetti deve essere coerente con uno specifico mapping tra JDBC types e Java Types (http://db.apache.org/ojb/docu/guides/jdbc-types.html).

Queste precisazioni servono per evidenziare due importanti vantaggi: impossibile incorrere nel tipico errore di sintassi in fase di scrittura della query string nell'utilizzo di java.sql.Statement (stringhe senza apici, date in formato non corretto, nomi colonne errati, ecc...), niente occhi che si incrociano e dita sullo schermo per costruire il corretto bind utilizzando PreparedStatement (è umano avere qualche difficoltà in tabelle con un consistente numero di colonne nell'identificare il 15esimo setter da associare al 15esimo '?'...)

PREPARED STATEMENT:

         PreparedStatement ins = con.prepareStatement(

"INSERT INTO TAB1 (A,B,C,D,E,F,G,H,I,L) VALUES(?,?,?,?,?,?,?,?,?,?);

ins.setInt(1, 75);

ins.setString(2, "Duke");

...

ins.setString(10,"...")

ins.executeUpdate():

OJB:

Tab1 t = new Tab1();

t.setA(75);

t.setB("Duke");

t.setL("...");

t.store();

Come bene sappiamo, la risposta del database avviene mediante la restituzione di un java.sql.ResultSet da parte del metodo executeQuery(String): scorrendolo opportunamente sarà semplice recuperare i dati ricevuti in risposta alla query, ma non sarebbe più semplice se la risposta fosse un value object contenente tutti i valori del record restituito o, nel caso ci fossero più occorrenze, una Collection (org.apache.ojb.broker.ManageableCollection) di value object?

Questo è solo un piccolo esempio di ciò che può fare questo framework, ma credo siano le features più interessanti per chi si appresta ad un primo approccio al DAO.



Perche' usarlo top

Di seguito una breve descrizione step by step per vedere OJB in funzione, utilizzando come base dati MySQL (4.1.7):

[+] Prepariamo la base dati con una semplice tabella di esempio (in questo caso sullo schema 'test') rappresentate un'anagrafica composta da NOME, COGNOME e un ID utente:

CREATE TABLE test.TB01_ANAG (

         NOME varchar(50) NOT NULL ,

         COGNOME varchar(50),

         ID integer NOT NULL,

         PRIMARY KEY(ID)

);

 [+] Creiamo una delle tabelle necessarie al corretto funzionamento di OJB (vedi repository-internal.xml):

CREATE TABLE test.OJB_HL_SEQ (

         TABLENAME VARCHAR(175) NOT NULL,

         FIELDNAME VARCHAR(70) NOT NULL,

         MAX_KEY BIGINT,

         GRAB_SIZE INTEGER,

         VERSION INTEGER,

         CONSTRAINT SYS_PK_OJB_HL_SEQ

         PRIMARY KEY(TABLENAME,FIELDNAME)

);

[+] Creiamo un nuovo Java Project inseriamo nel classpath tutti i riferimenti alle librerie di terze parti necessarie al funzionamento di OJB e il driver di MySQL.

[+] Inseriamo nella root del project i file di configurazione del framework (eventualmente generati da Impart OJB Generator) e vediamone le possibilità di configurazione:

-OJB.properties

Specifica la configurazione di base del framework, le classi di implementazioni delle interfacce, impostazione del pool di connessioni e dei vari livelli di log.In questa primo approccio non dovrebbero essere necessarie modifiche.


-repository-internal.xml

Descrittore delle tabelle di servizio del framework, il commento parla da solo:
http://db.apache.org/ojb/docu/guides/platforms.html#OJB+internal+tables

- repository_user.xml

Descrive le tabelle fisiche e la associa ad oggetti Java:

         <class-descriptor

                  class="beans.TB01_anag"

                  table="TB01_ANAG"

           >

                  <field-descriptor id="0"

                           name="id"

                           column="ID"

                           jdbc-type="INTEGER"

                           primarykey="true"

                           autoincrement="true"

                  />

                  <field-descriptor id="1"

                           name="nome"

                           column="NOME"

                           jdbc-type="VARCHAR"

                  />

                  <field-descriptor id="2"

                           name="cognome"

                           column="COGNOME"

                           jdbc-type="VARCHAR"

                  />

         </class-descriptor>

in questo caso viene descritto il mapping tra la tabella test.TB01_anag e la classe beans.TB01_anag.java, che trovate di seguito:

/*

* Created on 14-giu-2004

*

* Questo Java Bean mappa la tabella fisica TB01_ANAG, riportandone i nomi delle colonne

* tipizzati secondo il mapping JDBC-Java presente nella documentazione di OJB

*

* I nomi dei fields devono essere riporati nell'xml descriptor della tabella: repository_user.xml

*/

package beans;

/**

* @author Andrea Previati

*/

public class TB01_anag {

         String nome;

         String cognome;

         int id;

         /**

         * @return Returns the cognome.

         */

         public String getCognome() {

         return cognome;

         }

         /**

         * @param cognome The cognome to set.

         */

         public void setCognome(String cognome) {

         this.cognome = cognome;

         }

         /**

         * @return Returns the id.

         */

         public int getId() {

         return id;

         }

         /**

         * @param id The id to set.

         */

         public void setId(int id) {

         this.id = id;

         }

         /**

         * @return Returns the nome.

         */

         public String getNome() {

         return nome;

         }

         /**

         * @param nome The nome to set.

         */

         public void setNome(String nome) {

         this.nome = nome;

         }

}

-repository.xml + repository.dtd

Questo descrittore contiene la configurazione necessaria per la connessione alla base dati e le inclusioni degli altri descrittori come entity:

<?xml version="1.0" encoding="UTF-8"?>

<!-- This repository file is generated by the impart OJB Generator -->

<!--www.impart.ch matthias.roth@impart.ch-->

<!-- defining entities for include-files -->

<!DOCTYPE descriptor-repository SYSTEM "repository.dtd" [

<!ENTITY user SYSTEM "repository_user.xml">

<!ENTITY internal SYSTEM "repository_internal.xml">

]>

<descriptor-repository version="1.0" isolation-level="read-uncommitted">

<jdbc-connection-descriptor

                 jcd-alias="test"

                  default-connection="true"

                  platform="MySQL"

                  jdbc-level="2.0"

                  driver="com.mysql.jdbc.Driver"

                  protocol="jdbc"

                  subprotocol="mysql"

                  dbalias="//localhost:3306/test"

                  username="root"

                  password="password"

                  batch-mode="false"

>

         <connection-pool maxActive="21" validationQuery="" />

         <sequence-manager className="org.apache.ojb.broker.util.sequence.SequenceManagerHighLowImpl">

                  <attribute attribute-name="grabSize" attribute-value="1"/>

         </sequence-manager>

</jdbc-connection-descriptor>

<!-- include user defined mappings here -->

&user;

<!-- include ojb internal mappings here -->

&internal;

</descriptor-repository>



I Test top

Verifichiamo la disponibilità delle risorse necessarie al framework (direttamente dal classpath del mio project):

<classpathentry kind="lib" path="/COMMON_LIB/commons-pool.jar"/>

<classpathentry kind="lib" path="/COMMON_LIB/db-ojb-1.0.1.jar"/>

<classpathentry kind="lib" path="/COMMON_LIB/commons-dbcp-1.0-src.jar"/>

<classpathentry kind="lib" path="/COMMON_LIB/commons-beanutils.jar"/>

<classpathentry kind="lib" path="/COMMON_LIB/commons-collections.jar"/>

<classpathentry kind="lib" path="/COMMON_LIB/commons-digester.jar"/>

<classpathentry kind="lib" path="/COMMON_LIB/commons-lang.jar"/>

<classpathentry kind="lib" path="/COMMON_LIB/commons-logging.jar"/>

<classpathentry kind="lib" path="/COMMON_LIB/mysql-connector-java-3.0.7-stable-bin.jar"/>

Esaminiamo i punti salienti del codice: inseriremo 'n' record ed interrogheremo la base dati con una semplice query.

import java.util.Collection;

import java.util.Iterator;

import org.apache.ojb.broker.PersistenceBrokerFactory;

import org.apache.ojb.broker.query.Criteria;

import org.apache.ojb.broker.query.Query;

import org.apache.ojb.broker.query.QueryByCriteria;

import beans.TB01_anag;

org.apache.ojb.broker.PersistenceBroker broker = null;

try {

//    istanza del broker

      broker = PersistenceBrokerFactory.defaultPersistenceBroker();

//    l'isolation level della transazione è settato nel file repository.xml

      broker.beginTransaction();

//    Inserimento: il bean TB01_anag mappa il record della tabella TB01_ANAG

//    Inseriamo 5 record

      TB01_anag tab = null;

      for(int i=0; i<10; i++) {

//          istanza del bean

            tab = new TB01_anag();

//          Abbiamo creato la tabella per la gestione delle HighLowSequence: usiamola ed
//          omettiamo la valorizzazione della primary key! :-)

              tab.setId(i);

//          Valorizzazione del campo NOME

            tab.setNome("Nome "+i);

//          Valorizzazione del campo COGNOME

            tab.setCognome("Cognome "+i);

//          scrittura del record su db

            broker.store(tab);

//          ...in pratica:

//          insert into TB01_anag (ID, NOME, COMGNOME) values (0, 'Nome 0', 'Cogmone 0')

      }

      broker.commitTransaction();

//    Interrogazione della base dati: estraggo tutti gli utenti con id > 4

//    Istanzio un Criteria

      Criteria crit = new Criteria();

//    setto una clausola equivalente alla where dell'SQL standard, dove specifico che

//    la colonna ID deve avere un valore maggiore di 4

       crit.addGreaterThan("ID", new Integer(4));

//    istanzio l'oggetto Query di OJB, passando al costruttore il criteria appena creato

      Query query = new QueryByCriteria(TB01_anag.class, crit);

//    il broker si occupa di eseguire la query, recuperare il ResultSet e

//    "impacchettare" il risultato in una collection di oggetti.

//    ************

//    *ATTENZIONE*

//    ************

//    La collection restituita contiene OGGETTI java.lang.Object, pertanto è importante

//    porre attenzione al cast in fase di scorrimento dell'Iterator

//    ...oppure...

//    J2SE 1.5: Collection <TB01_anag> coll = broker.getCollectionByQuery(query);

      Collection coll = broker.getCollectionByQuery(query);

      Iterator iterator = coll.iterator();

      TB01_anag tab2 = null;

      while(iterator.hasNext()) {

//          cast Object -> TB01_anag

            tab2 =(TB01_anag)iterator.next();

//          mediante i getter del bean, estraggo i valori del "record"

            System.out.println(tab2.getId()+" - "+tab2.getNome()+" - "+tab2.getCognome());

      }

}catch (Throwable t){

       t.printStackTrace();

       System.out.println("Rollback transaction");

       broker.abortTransaction();

}

finally{

//           chiusura del borker

              if(broker!=null)broker.close();

}

Complilate, avviate, buona fortuna.



Conclusioni top

Queste prime righe di codice risultano utili esclusivamente a scopo dimostrativo, una web application o un progetto più complesso meritano sicuramente maggiore attenzione nella gestione delle risorse e delle prestazioni, ma spero possano essere utili a chi, come me, non ha mai trovato un esempio concreto e funzionante per configurare OJB.

Nelle "puntate successive" tratterò più approfonditamente l'interrogazione della base dati, la gestione delle foreign key e l'esecuzione di statement in transazione.



Username:
Password:
To sign up for an account, click register... Register
Hide





Powered By



Campagna Anti-IF


Skin


PARTNER
Zio Budda
HostingJava


LICENZA



Eccetto dove diversamente specificato, i contenuti di questo sito sono rilasciati sotto licenza Creative Commons

Sitemap  © 2002-2004 Copyright Information. Privacy . Today is domenica 1 agosto 2010