sabato 3 settembre 2011

Spring 3.0 ed Hibernate 3.2 su un progetto Java Standard

Oggi volevo provare ad utilizzare assieme Spring 3.0 e Hibernate 3.2 per sviluppare un progetto Java ed operare delle CRUD su una semplice tabella di Db.
Devo dire che ho trovato molte difficoltà soprattutto per quanto riguarda la configurazione dell’ambiente e dei jar necessari;  e cercando su internet ho notato che molta gente in rete lamentava i miei stessi problemi.
Trovo quantomeno singolare che nei siti specifici dei progetti non ci sia una paginetta che elenchi tutti i jar necessari per far funzionare Spring, forse sarà perché spesso Spring si utilizza all’interno di container web che al loro interno hanno già le librerie necessarie.
Alla fine dopo diverse “googlate” sono riuscito a configurare il tutto e a farlo funzionare.
Caso d’uso
Il db server utilizzato è MySql 5.5.15.
La tabella creata (Persona) ha la seguente ddl



CREATE TABLE `persona` (
  `idpersona` int(11) NOT NULL AUTO_INCREMENT,
  `nome` varchar(45) DEFAULT NULL,
  `cognome` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`idpersona`)
)
 














Configurazione librerie di progetto
Di seguito riporto un elenco di tutti i jar necessari al progetto , ben 34 di cui 20 sono quelli presenti nella directory dist della distribuzione di Spring 3.0.6, 1 di hibernate 3.2, 1 è il connector J utilizzato per andare su Mysql e i restanti 12 jar servono invece a Spring per vari motivi (logging, transazionalità ecc. ecc.).
Come ide di sviluppo ho utilizzato Eclipse Indigo ed ho messo tutti i jar in una directory lib del progetto che ho quindi aggiunto nel classpath (tasto destro sul progetto,Properties/ java/build path /Libraries/Add Library)

antlr-2.7.5H3.jar
cglib-nodep-2.2.jar
commons-collections-3.1.jar
commons-logging-1.1.1-javadoc.jar
commons-logging-1.1.1-sources.jar
commons-logging-1.1.1.jar
commons-logging-adapters-1.1.1.jar
commons-logging-api-1.1.1.jar
commons-logging-tests.jar
dom4j-1.6.1.jar
ehcache-1.2.3.jar
hibernate-3.2.0.cr2.jar
jta.jar
mysql-connector-java-3.1.14-bin.jar
org.springframework.aop-3.0.6.RELEASE.jar
org.springframework.asm-3.0.6.RELEASE.jar
org.springframework.aspects-3.0.6.RELEASE.jar
org.springframework.beans-3.0.6.RELEASE.jar
org.springframework.context-3.0.6.RELEASE.jar
org.springframework.context.support-3.0.6.RELEASE.jar
org.springframework.core-3.0.6.RELEASE.jar
org.springframework.expression-3.0.6.RELEASE.jar
org.springframework.instrument-3.0.6.RELEASE.jar
org.springframework.instrument.tomcat-3.0.6.RELEASE.jar
org.springframework.jdbc-3.0.6.RELEASE.jar
org.springframework.jms-3.0.6.RELEASE.jar
org.springframework.orm-3.0.6.RELEASE.jar
org.springframework.oxm-3.0.6.RELEASE.jar
org.springframework.test-3.0.6.RELEASE.jar
org.springframework.transaction-3.0.6.RELEASE.jar
org.springframework.web-3.0.6.RELEASE.jar
org.springframework.web.portlet-3.0.6.RELEASE.jar
org.springframework.web.servlet-3.0.6.RELEASE.jar
org.springframework.web.struts-3.0.6.RELEASE.jar

Configurazione xml di Spring e Hibernate
Ho quindi aggiunto una directory xml all’interno del progetto dove sono presenti i seguenti 3 file xml:
·         spring.xml, per definire i bean utilizzati da Spring;
·         hibernate.cfg.xml, per definire la session factory di hibernate e per mappare le risorse;
·         persona.hbm.xml l’hbm che definisce le mappature tra oggetto e tabella.

Spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

       <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
       <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
       </bean>
       <bean id="personaDao" class="it.test.daoImpl.SpringHibernatePersonaDaoImpl">
       <property name="sessionFactory" ref="sessionFactory"></property>
       </bean>
</beans>
 


Qui ho  definito la sessionFactory di Hibernate, specificando che i valori di configurazione devono essere presi dal file hibernate.cfg.xml che si trova sul classpath, e quindi il bean utilizzato per le operazioni di CRUD sulla tabella,  a cui ho iniettato la sessionFactory (come si vedrà dopo è una DI via set della proprietà e non via costruttore).

Hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
 <!-- Database connection settings -->       
 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>       
 <property name="connection.url">jdbc:mysql://localhost:3306/test</property>      
 <property name="connection.username">root</property>       
 <property name="connection.password">root</property>       
 <!-- JDBC connection pool (use the built-in) -->      
 <property name="connection.pool_size">1</property>      
 <!-- SQL dialect -->       
 <property name="dialect">org.hibernate.dialect.MySQLDialect</property>      
 <!-- Echo all executed SQL to stdout -->      
 <property name="show_sql">true</property>
 <!-- Mapping files -->
<mapping resource="persona.hbm.xml"/>
</session-factory>
</hibernate-configuration>
 




Persona.hbm.xml
Di seguito l’hbm che mappa la tabella

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="it.test.oggetti">
<class name="Persona" table="persona">
<id name="id" type="long" unsaved-value="null" >    
<column name="idpersona" not-null="true"/>    
<generator class="identity"/> 
</id>
<property name="nome" type="string">
<column name="nome" length="45"></column>
</property>
<property name="cognome" type="string">
<column name="cognome" length="100"></column>
</property>
</class>
</hibernate-mapping>
 



NB: si noti la mappatura della Primary Key della tabella con generator class IDENTITY,  significa che il valore della chiave può non essere disponibile al momento dell’inserimento, in quanto generato nel commit dello statement SQL.  Questa caratteristica accomuna molti database, tra cui appunto MySql e Microsoft SQL Server, per Oracle si sarebbe dovuto usare SEQUENCE.

La classe Persona è un semplice POJO con le 3 proprietà id di tipo Long e nome e cognome di tipo Stringa.
L’ interfaccia di Business  per realizzare la CRUD sulla tabella è :


public interface PersonaDao {
      
       public void store(Persona p);
       public void delete(Long id);
       public Persona findById(Long id);
       public List<Persona> findAll();

}
 




Di seguito l’implementazione dell’interfaccia

public class SpringHibernatePersonaDaoImpl implements PersonaDao {
       private SessionFactory sessionFactory;
       public SpringHibernatePersonaDaoImpl(){
             Configuration conf=new Configuration().configure();
             sessionFactory=conf.buildSessionFactory();
       }
    public void setSessionFactory(SessionFactory sessionFactory){
       this.sessionFactory=sessionFactory;
    }
       @Override
       public void store(Persona p) {
             Session session=sessionFactory.openSession();
             Transaction tx=session.getTransaction();
             try
             {
                    tx.begin();
                    session.saveOrUpdate(p);
                    tx.commit();
             }
             catch(RuntimeException ex){
                    tx.rollback();
                    throw ex;
             }
             finally{
                    session.close();
             }

       }

       @Override
       public void delete(Long id) {
             Session session=sessionFactory.openSession();
             Transaction tx=session.getTransaction();
             try
             {
                    tx.begin();
                    Persona p=(Persona)session.get(Persona.class, id);
                    session.delete(p);
                    tx.commit();
             }
             catch(RuntimeException ex){
                    tx.rollback();
                    throw ex;
             }
             finally{
                    session.close();
             }
            

       }

       @Override
       public Persona findById(Long id) {
             Session session=sessionFactory.openSession();
             try
             {
                    Persona p=(Persona)session.get(Persona.class, id);
                    return p;
             }
             finally{
                    session.close();
             }
            
       }

       @Override
       public List<Persona> findAll() {
             Session session=sessionFactory.openSession();
             try
             {
                    Query q=session.createQuery("from Persona");
                    return q.list();
             }
             finally{
                    session.close();
             }
       }


}


A questo punto non resta che richiamare da un main il bean di Spring , in questo modo


ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
PersonaDao p=(PersonaDao)context.getBean("personaDao");
Persona p1=new Persona();
p1.setCognome("Bianchi");
p1.setNome("Mario");
p.store(p1);
Persona p2=new Persona();
p2.setCognome("Rossi");
p2.setNome("Mario");
p.store(p2);
Persona p3=new Persona();
p3.setCognome("Rossi");
p3.setNome("Mario");
p.store(p3);
System.out.println(p.findAll());
 



Nessun commento:

Posta un commento