15-OSFrameworks -45p [Compatibility Mode]
Transcript
15-OSFrameworks -45p [Compatibility Mode]
Open Source Frameworks Ingegneria del Software Andrea Bei 1 Framework Un framework è un insieme di classi e interfacce che cooperano e generalizzano task e workflow comuni di uno specifico dominio applicativo (funzionale o tecnologico) Un framework ha le seguenti caratteristiche Accelera la costruzione di applicazioni del dominio a cui si rivolge grazie al riuso della soluzione architetturale che ne costituisce la struttura I componenti del framework sono riusabili Utilizzo diffuso di classi astratte e interfacce Considerate come "template" per le sottoclassi o classi delle specifiche applicazioni. Adozione di un modello collaborativo Inversione del flusso di controllo (IOC) Lo sviluppatore non scrive codice per coordinare le componenti. Lo sviluppatore implementa le componenti che aderendo alla logica collaborativa del framework verranno coordinate da quest'ultimo. I framework assumono il controllo della applicazione e non il contrario! cfr ad esempio: pattern template method) 2 Framework Open Source Sono stati tra i principali elementi di innovazione nelle architetture web negli ultimi anni Hanno rappresentato il principale veicolo dell’esperienza “collettiva” degli sviluppatori in termini di design & architectural pattern, idioms, best practices Rispetto ai framework in-house (realizzati ad hoc) hanno una contribuzione di sviluppo più ampia e quindi una maggiore velocità di convergenza alla soluzione “migliore” per il dominio specifico Aumentano la produttività nello sviluppo Supportano la standardizzazione delle soluzioni Supportano un approccio allo sviluppo architettura-centrico Per uno sviluppatore/architetto Java EE la competenza su framework e librerie Open Source è fondamentale 3 Web Application Framework Un Web Application Framework è: un sistema software che fornisce struttura e comportamento generalizzati di task e workflow tipici delle applicazioni web. Es: gestione della navigazione (MVC), gestione dell’accesso ai dati (DAO), … Il framework di riferimento di LIS è un Web Application Framework didattico completo (nel senso che include tutti i task tipici di una applicazione web dalla presentazione all’accesso ai dati basandosi sui design pattern fondamentali) Nella “vita reale” per la realizzazione di web application è tipico l’utilizzo congiunto di diversi framework open source specializzati in aspetti specifici Ci concentreremo su alcuni di quelli più diffusi Struts / Struts 2 Spring Hibernate 4 Struts Struts E’ un insieme di classi ed interfacce che costituiscono l'infrastruttura per costruire web application Java EE conformi al design pattern Model 2 (MVC) Il suo ideatore è Craig McClanahan ed è stato donato alla Apache Software Foundation nel maggio del 2000 da parte di IBM. E’ uno dei web application framework più diffusi al mondo Struts 2 Nonostante il nome, Struts 2 non è una nuova release di Struts ma un framework completamente nuovo basato su WebWork Sono state introdotte caratteristiche non presenti in Struts grazie ai feedback di migliaia di sviluppatori 5 Spring Spring è un “lightweight” container che fornisce una soluzione per sviluppare applicazioni costruite su POJO. Si basa su: Inversion of Control/Dependency Injection (configurazione data-driven di POJO) AOP (Aspect Oriented Programming) Diverse componenti di utilità (tra cui una propria implementazione di MVC) La prima versione venne scritta da Rod Johnson e rilasciata con la pubblicazione del proprio libro "Expert One-on-One Java EE Design and Development" (Wrox Press, Ottobre 2002). Spring è stato largamente riconosciuto all'interno della comunità Java quale valida alternativa al modello basato su Enterprise JavaBeans (EJB). Rispetto a quest'ultimo, il framework Spring lascia una maggiore libertà al programmatore fornendo allo stesso tempo un'ampia e ben documentata gamma di soluzioni 6 semplici adatte alle problematiche più comuni. Hibernate Hibernate (H8) è un middleware ORM (Object-relational mapping) open source. Consente la rappresentazione e la gestione su database relazionale di un sistema di oggetti Java. E’ stato originariamente sviluppato da un team internazionale di programmatori volontari coordinati da Gavin King; in seguito il progetto è stato proseguito sotto l'egida di JBoss, che ne ha curato la standardizzazione rispetto alle specifiche Java EE. 7 Mapping dei FW OS con eUniversity Struts Hibernate Spring 8 Struts – class diagram 9 Struts – componenti principali Struts-config.xml fornisce alla ActionServlet, in base ai parametri della URL La Action da invocare La pagina JSP a cui inoltrare la richiesta ActionServlet: il controller di Model 2 Action: il Model di Model 2 (Classe base per le classi “action” ) Le classi action sono responsabili di Interfacciarsi con il layer sottostante (es: EJB, DAO, …) Recuperare i dati da presentare alla View e inserirli in sessione JSP: la View di Model 2 Le pagine JSP sono responsabili di Recuperare i dati da visualizzare dalla sessione Visualizzare i dati 10 StrutsStruts- esempio di strutsstruts-config <struts-config> <form-beans> <form-bean name=”projectForm” type=”it.uniroma2.app.form.ProjectListForm”/> </form-beans> <action-mappings> <action path=”/tasklist” type=” it.uniroma2.app.action.ProduceTaskListAction” name=”projectForm” scope=”request” validate=”true” input=”/jsp/Project.jsp”> <forward name=”success” path=”/jsp/TaskList.jsp”/> <forward name=”failure” path=”/jsp/ServerErrors.jsp”/> </action> </action-mappings> </struts-config> 11 Bibliografia Programming Jakarta Struts - Chuck Cavaness 12 Spring - Caratteristiche Spring è un lightweight container framework che supporta tecniche di IoC (inversion of control) e AoP (aspect-oriented programming) Lightweight (“leggero”) “leggero” per dimensione e overhead di elaborazione. (file JAR circa 1MB) Inversion of control Permette di sostenere “low coupling” (basso accoppiamento). Gli oggetti ricevono passivamente dall’esterno le loro dipendenze (es: il riferimento ad altri oggetti) , invece di crearle (new di oggetti) o cercarle in file esterni (es: classloading dinamico). Approccio “push” invece di “pull”. E’ il container che fornisce le dipendenze all’oggetto all’atto della istanziazione di quest’ultimo (Dependency Iniection) Aspect-oriented programming Permetta la SoC (separation of concern). Ovvero la separazione di responsabilità tra business logic e system services (come logging, autenticazione, gestione delle transazioni) 13 Spring - Caratteristiche Container Contiene e gestisce il ciclo di vita e la configurazione delle dipendenze degli oggetti. E’ possibile configurare come ogni singolo bean (POJO) deve essere creato (ad esempio in modalità “singleton”, pool, classica) e quali sono le sue dipendenze con gli altri bean. Framework Permette di configurare e comporre applicazioni complesse a partire da componenti più semplici in maniera dichiarativa (XML) Fornisce funzionalità infrastrutturali riusabili (transaction management, persistence framework integration, etc.), lasciando al developer solo lo sviluppo della logica di business 14 Spring Architettura 15 Spring Architettura Core container Contiene le funzionalità di base del framework. Contiene il BeanFactory, il “cuore” di ogni applicazione Spring-based, che che consiste in una implementazione del pattern factory che utilizza la tecnica IoC Modulo Application Context Contiene il supporto per l’internazionalizzazione (I18N messages), gestione degli eventi del ciclo di vita della applicazione, meccanismi di validazione, servizi come e-mail, JNDI access, EJB integration, scheduling, integrazione con “templating framework” come Velocity e FreeMarker Modulo AOP E’ il componente base per lo sviluppo di aspects (le API sono conformi a quelle definite in AOP Alliance . Permette la meta-programmazione. (è possibile aggiungere annotations per istruire Spring su dove e quando aggiungere aspetti) 16 Spring Architettura Modulo JDBC e DAO Aiuta a evitare il codice “boilerplate” proprio di JDBC (connessioni, resultset, …). Fornisce una astrazione del codice boilerplate e permette di semplificare il codice di accesso a db. Fornisce un layer di exception relative all’accesso al db “on top” rispetto a quelle native dei db. Modulo Web Context and Utility Si basa sul modulo Application Context e lo specializza per applicazioni. Fornisce il supporto a task web-oriented (es: file upload) e all’integrazione con Jakarta Struts . MVC framework Fornisce un framework Model/View/Controller (MVC) per la costruzione di web application. Spring’s MVC framework usa IoC per separare la logica di business e la logica di controllo e collegare in modo dichiarativo i parametri della request ai relativi oggetti di business (i.e. actions) Modulo O/R Mapping Punto di integrazione per Hibernate, JDO, OJB, iBATIS 17 Spring “hello world” public interface GreetingService { public void sayGreeting(); } public class GreetingServiceImpl implements GreetingService { private String greeting; public GreetingServiceImpl() {} public GreetingServiceImpl(String greeting) { this.greeting = greeting; } public void sayGreeting() { System.out.println(greeting); } public void setGreeting(String greeting) { this.greeting = greeting; } } GreetingServiceImpl ha un solo attributo (o property): greeting. La property è l’unica dipendenza della classe può essere impostata tramite il costruttore o tramite il metodo setter SPRING IMPOSTA IL VALORE DELLA PROPERTY 18 Spring “hello world” <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id=“greetingService” class="com.springinaction.chapter01.hello.GreetingServiceImpl"> <property name="greeting"> <value>Buenos Dias!</value> </property> </bean> </beans> TRAMITE SETTER - EQUIVALE A GreetingServiceImpl greetingService = new GreetingServiceImpl(); greetingService.setGreeting("Buenos Dias!"); 19 Spring “hello world” <bean id="greetingService" class="com.springinaction.chapter01.hello.GreetingServiceImpl"> <constructor-arg> <value>Buenos Dias!</value> </constructor-arg> </bean> TRAMITE COSTRUTTORE - EQUIVALE A GreetingServiceImpl greetingService = new GreetingServiceImpl(“Buenos Dias”); 20 Spring “hello world” package com.springinaction.chapter01.hello; import java.io.FileInputStream; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; public class HelloApp { public static void main(String[] args) throws Exception { BeanFactory factory = new XmlBeanFactory(new FileInputStream("hello.xml")); GreetingService greetingService = (GreetingService) factory.getBean("greetingService"); greetingService.sayGreeting(); } } Risultato “Hello World”: Come configurare un bean mediante l’injection di una specifica stringa in una property. La reale potenzialià di Spring consiste nel poter fare l’injection di un bean in un altro bean usando IoC 21 IoC (Inversion of control) Hollywood Principle “Don’t call me, I’ll call you”. Lo sviluppatore implementa dei metodi che verranno chiamati dal framework E’ una tecnica usata nella progettazione dei framework Uno dei pattern per realizzarla è il Template Method (fig. a destra) Esempio: Servlet container Gestisce il ciclo di vita le request delle Servlet Invocando i metodi callback “Init”, “Destroy”, “doGet”, “doPost” abstract class AbstractClass { public void templateMethod() { // qui c’è l’algoritmo ... framework method1(); while (...) method2(); ... method3(); } abstract void method1(); abstract void method2(); abstract void method3(); } class ConcreteClass extends AbstractClass { void method1() {...} applicazione void method2() {...} void method3() {...} } 22 Dependency Iniection E’ un tipo particolare di inversione del controllo Tradizionalmente nell’ OOP ogni oggetto è responsabile di ottenere i riferimenti agli oggetti con cui collabora (le sue dipendenze) Applicando IoC, agli oggetti le dipendenze vengono fornite all’atto della creazione da un entità esterna che coordina ogni oggetto nel sistema. In altre parole le dipendenze vengono “iniettate” nell’oggetto In pratica in Spring il container inietta le dipendenze nell’oggetto tramite i suoi metodi Java usati come metodi callback (setter o costruttori). Le dipendenze possono essere oggetti (es: String) o tipi semplici (es: int, float) . DI è anche conosciuta come “push configuration”. Le dipendenze sono “spinte dentro” (push) l’oggetto dal container piuttosto che “prelevate” (pull) dall’oggetto stesso PULL PUSH 23 Dependency Injection Pattern DI Esempio public class KnightOfTheRoundTable { private String name; private HolyGrailQuest quest; public KnightOfTheRoundTable(String name) { this.name = name; quest = new HolyGrailQuest(); -> L’oggetto recupera la propria dipendenza } public HolyGrail embarkOnQuest() throws GrailNotFoundException { return quest.embark(); }} public class HolyGrailQuest { public HolyGrailQuest() {} public HolyGrail embark() throws GrailNotFoundException { HolyGrail grail = null; // Look for grail … return grail; }} 24 DI Esempio import junit.framework.TestCase; public class KnightOfTheRoundTableTest extends TestCase { public void testEmbarkOnQuest() { KnightOfTheRoundTable knight = new KnightOfTheRoundTable("Bedivere"); try { HolyGrail grail = knight.embarkOnQuest(); assertNotNull(grail); assertTrue(grail.isHoly()); } catch (GrailNotFoundException e) { fail(); }}} Se si esegue il test su KnightOfTheRoundTable, indirettamente si effettua il test anche su HolyGrailQuest Inoltre è impossibile avere un comportamento diverso HolyGrailQuest (e.g., return null o throw GrailNotFoundException) per diversi test Se si sta utilizzando per HolyGrailQuest un mock object per simulare un oggetto reale in ambiente di test si deve modificare il codice per farlo funzionare in ambiente di produzione 25 DI Esempio Il problema è l’accoppiamento. KnightOfTheRoundTable è staticamente accoppiato con HolyGrailQuest (non si può avere un KnightOfTheRoundTable senza avere anche un HolyGrailQuest) L’accoppiamento è necessario ma va minimizzato Necessario: Due oggetti sono accoppiati quando uno dipende dall’altro, ma un programma OO in esecuzione è proprio un insieme di oggetti che dipendono l’uno dall’altro (eseguono dei compiti o delegano l’esecuzione ad altri oggetti dipendenti) Minimizzato: Va reso più basso possibile perchè riduce la leggibilità, manutenibilità, testabilità (pattern GRASP “low coupling”). Un modo per ridurre l’accoppiamento diretto è introdurre un livello di indirezione mediante interfacce public interface Quest { public abstract Object embark() throws QuestException; } public class HolyGrailQuest implements Quest { public HolyGrailQuest() {} public Object embark() throws QuestException { // Do whatever it means to embark on a quest return new HolyGrail(); }} private Quest quest; … public Object embarkOnQuest() throws QuestException { return quest.embark(); } Nella classe KnightOfTheRoundTable uso il tipo interfaccia 26 DI Esempio public interface Knight { public Object embarkOnQuest() throws QuestException; } public class KnightOfTheRoundTable implements Knight { private Quest quest; … public KnightOfTheRoundTable(String name) { quest = new HolyGrailQuest(); … } public Object embarkOnQuest() throws QuestException { return quest.embark(); }} Anche con le interfacce non risolvo il problema perchè un KnightOfTheRoundTable è vincolato solo ad un tipo di ricerca per “Holy Grail” e nessun altro tipo di ricerca 27 DI Esempio E’ giusto che il cavaliere scelga da solo la propria ricerca (missione) o è più conveniente/utile che gli venga assegnata ? public class KnightOfTheRoundTable implements Knight { private Quest quest; … public KnightOfTheRoundTable(String name) { … } public HolyGrail embarkOnQuest() throws QuestException { … return quest.embark(); } public void setQuest(Quest quest) { this.quest = quest; }} Ora KnightOfTheRoundTable non è più responsabile di recuperare le proprie missioni. Inoltre poiché KnightOfTheRoundTable è dipendente solo dall’interfaccia Quest è possibile passargli qualsiasi implementazione di tale interfaccia. La responsabilità di coordinare la collaborazione tra oggetti dipendenti è scorporata dagli oggetti stessi. es: In ambiente di produzione potremmo aver bisogno di un tipo di HolyGrailQuest,28ma in ambiente di test potremmo avere una implementazione mock (mock object) DI Esempio Ora che l’oggetto è pronto a ricevere dall’”esterno” una dipendenza chi la passa ? QUI ENTRA IN GIOCO SPRING L’azione di creare associazioni tra componenti applicativi è detta wiring (cablare/collegare fili elettrici). In Spring, ci sono molti modi di collegare tra loro componenti ma il più comune è tramite XML (“knight.xml”) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="quest“ class="com.springinaction.chapter01.knight.HolyGrailQuest"/> <bean id="knight“ class="com.springinaction.chapter01.knight.KnightOfTheRoundTable"> <constructor-arg> <value>Bedivere</value> </constructor-arg> <property name="quest"> <ref bean="quest"/> </property> </bean> </beans> 29 DI Esempio import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; public class KnightApp { public static void main(String[] args) throws Exception { BeanFactory factory = new XmlBeanFactory(new FileInputStream("knight.xml")); KnightOfTheRoundTable knight = (KnightOfTheRoundTable)factory.getBean("knight"); knight.embarkOnQuest(); } } 30 Hibernate - Caratteristiche Hibernate è un middleware ORM (Object Relational Mapping). La funzione principale di un ORM è l’automatica e trasparente persistenza di oggetti nelle tabelle di un DB relazionale tramite metadata che descrivono il mapping tra oggetti e entità del DB. Lo strato ORM trasforma dati da una rappresentazione e l’altra in entrambi i versi Ogni middleware ORM comprende i seguenti elementi: API per eseguire operazioni CRUD (Create Read Update Delete) su oggetti di classi persistenti Un linguaggio o API per specificare delle Query su classi e proprietà di classi Una “facility” per specificare i mapping metadata Una tecnica per gestire oggetti transazionali per eseguire dirty checking, lazy association fetching, ed altre funzioni di ottimizzazione 31 Hibernate “Hello World” package hello; public class Message { private Long id; private String text; private Message nextMessage; private Message() {} public Message(String text) { this.text = text; } public Long getId() { return id; } private void setId(Long id) { this.id = id; } public String getText() { return text; } Applying advice to an object is known as weaving public void setText(String text) { this.text = text; } public Message getNextMessage() { return nextMessage; } public void setNextMessage(Message nextMessage) { this.nextMessage = nextMessage; }} 32 Hibernate “Hello World” Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); Message message = new Message("Hello World"); session.save(message); tx.commit(); session.close(); equivale a insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) values (1, 'Hello World', null) 33 Hibernate “Hello World” Session newSession = getSessionFactory().openSession(); Transaction newTransaction = newSession.beginTransaction(); List messages = newSession.find("from Message as m order by m.text asc"); System.out.println( messages.size() + " message(s) found:" ); for ( Iterator iter = messages.iterator(); iter.hasNext(); ) { Message message = (Message) iter.next(); System.out.println( message.getText() ); } newTransaction.commit(); newSession.close(); Hibernate Query Language (HQL) equivale a select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID from MESSAGES m order by m.MESSAGE_TEXT asc 34 Hibernate “Hello World” XML Mapping <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="hello.Message“ table="MESSAGES"> <id name="id“ column="MESSAGE_ID"> <generator class="increment"/> </id> <property name="text“ column="MESSAGE_TEXT"/> <many-to-one name="nextMessage“ cascade="all“ column="NEXT_MESSAGE_ID"/> </class> </hibernate-mapping> 35 Hibernate “Hello World” Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); // 1 is the generated id of the first message Message message = (Message) session.load( Message.class, new Long(1) ); message.setText("Greetings Earthling"); Message nextMessage = new Message("Take me to your leader (please)"); message.setNextMessage( nextMessage ); tx.commit(); session.close(); equivale a select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID from MESSAGES m where m.MESSAGE_ID = 1 insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) values (2, 'Take me to your leader (please)', null) update MESSAGES set MESSAGE_TEXT = 'Greetings Earthling', NEXT_MESSAGE_ID = 2 where MESSAGE_ID = 1 36 Hibernate Startup Startup di Hibernate Localizzare il file di mapping tramite l’oggetto Configuration Creare un SessionFactory Regole 1. Il file di mapping (Message.hbm.xml) deve essere visibile nel CLASSPATH 2. Per convenzione 1 map file per classe (è possibile invocare più volte il metodo addResource per caricarli tutti) 3. Per impostare le configurazioni 3 alternativa java -Dproperty=value. file hibernate.properties nel classpath. Tag <property> in hibernate.cfg.xml nel classpath. Equivalente con il method chaining Configuration cfg = new Configuration(); cfg.addResource("hello/Message.hbm.xml"); cfg.setProperties( System.getProperties() ); SessionFactory sessions = cfg.buildSessionFactory(); Configuration cfg = new Configuration() .addResource("hello/Message.hbm.xml") .setProperties(System.getProperties()) .buildSessionFactory(); 37 Connection Pool Supporto al connection pool open source C3P0 (altri supportati sono Apache DBCP e Proxool) Senza Hibernate Con Hibernate File hibernate.properties hibernate.connection.driver_class = org.postgresql.Driver hibernate.connection.url = jdbc:postgresql://localhost/auctiondb hibernate.connection.username = auctionuser hibernate.connection.password = secret hibernate.dialect = net.sf.hibernate.dialect.PostgreSQLDialect hibernate.c3p0.min_size=5 hibernate.c3p0.max_size=20 hibernate.c3p0.timeout=300 hibernate.c3p0.max_statements=50 hibernate.c3p0.idle_test_period=3000 38 Caso di Studio: Modello di DominioDominio-Aste Online 1°Passo: Disegnare il Modello di Dominio 39 Caso di Studio: Modello di DominioDominio-Aste Online 2°Passo: Progettare i POJO (o JavaBean) public class User implements Serializable { private String username; private Address address; public User() {} public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public MonetaryAmount calcShippingCosts(Address fromLocation) { ... } } Impl. Serializable Setter/Getter Business Method 40 Caso di Studio: Modello di DominioDominio-Aste Online 3°Passo: Progettare le associazioni public class Category implements Serializable { private String name; private Category parentCategory; private Set childCategories = new HashSet(); public Category() { } ... public void setName(String name) { this.name = name; } public Set getChildCategories() { Codice “Scaffolding” return childCategories; } public void setChildCategories(Set childCategories) { this.childCategories = childCategories; } public Category getParentCategory() { return parentCategory; } public void setParentCategory(Category parentCategory) { this.parentCategory = parentCategory; } } 41 Caso di Studio: Modello di DominioDominio-Aste Online 3°Passo: Progettare le associazioni (…aggiungere el ementi) Category aParent = new Category(); Category aChild = new Category(); aChild.setParentCategory(aParent); aParent.getChildCategories().add(aChild); Codice “Scaffolding” 3°Passo: Progettare associazioni public class Category { ... private Set items = new HashSet(); ... public Set getItems() { return items; } public void setItems(Set items) { this.items = items; } } Codice “Scaffolding” Categoria > Item 42 Caso di Studio: Modello di DominioDominio-Aste Online 3°Passo: Progettare le associazioni public class Item { private String name; private String description; ... private Set categories = new HashSet(); ... public Set getCategories() { Codice “Scaffolding” return categories; Item > Categoria } private void setCategories(Set categories) { this.categories = categories; } public void addCategory(Category category) { if (category == null) throw new IllegalArgumentException("Null category"); category.getItems().add(this); categories.add(category);}} 43 Caso di Studio: Modello di DominioDominio-Aste Online 4°Passo: Definire i metadata <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="org.hibernate.auction.model.Category“ table="CATEGORY"> <id name="id“ column="CATEGORY_ID“ type="long"> <generator class="native"/> </id> <property name="name“ column="NAME“ type="string"/> </class> </hibernate-mapping> 44 Bibliografia Hibernate in Action - CHRISTIAN BAUER-GAVIN KING Manning 45