Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    [Hibernate] Simulare una "view" usano il Loader

    Salve a tutti,
    seguendo questo articolo (Use Hibernate’s Custom Loaders to fake an aggregation view) sto tentando di simulare una vista (non vorrei doverla creare fisicamente sul database) usando una query.

    ecco il mio codice:
    codice:
    @javax.persistence.Entity
    @Entity(dynamicInsert=false, dynamicUpdate=false, mutable=false)
    @Loader(namedQuery="loadArticoloView")
    @SqlResultSetMapping(name="loadArticoloView",
                         entities=@EntityResult(entityClass=ArticoloView.class))
    @NamedNativeQuery(name="loadArticoloView", 
                      query="select " +
                      		"a.id as id, nome, descrizione, posizione, prezzo, coefficientePrezzo, prezzoFinito, " +
                      		"c.testo as categoria, " +
                      		"m.quantita as quantita, " +
                      		"(select nome" +
                      		"from " +
                      		"articolo_fattura " +
                      		"left join fornitore on articolo_fattura.id_fornitore = fornitore.id " +
                      		"where id_articolo = a.id " +
                      		"order by data_fattura DESC " +
                      		"limit 0,1) as fornitore " +
                      		"from " +
                      		"articolo a " +
                      		"left join codcategoria c on c.id = a.id_categoria " +
                      		"left join magazzino m on m.id_articolo = a.id " +
                      		"where a.id = ?", 
                      		resultSetMapping="loadArticoloView")
    public class ArticoloView {
    	String id;
    	String nome;
    	String descrizione;
    	String posizione;
    	Float prezzo;
    	Float coefficientePrezzo;
    	Float prezzoFinito;
    	String categoria;
    	Integer quantita;
    	String fornitore;
    	
    	
    	@Id
    	public String getId() {
    		return id;
    	}
    	public void setId(String id) {
    		this.id = id;
    	}	
    	
            // altri getter e setter...
    	
    }
    ed ecco come tento di recuperare l'entità:
    codice:
            Query q = em.createQuery("Select count(*) from ArticoloView", Long.class);
    	System.out.println(q.getResultList().get(0).toString());
    ma hibernate continua a eseguire la seguente query: "select count(*) as col_0_0_ from ArticoloView articolovi0_"
    con il conseguente errore Table 'articoloview' doesn't exist

    (in teoria hibernate non dovrebbe generare la quary ma dovrebbe usare quella scritta da me, ca sembra che la ignori completamente, senza dare nessun messaggio di errore)
    Tra i messaggi di inizializzazione ho trovato questi :
    codice:
    1621 [http-8080-2] INFO org.hibernate.cfg.AnnotationBinder - Binding entity from annotated class: com.example.testhibernate3.hibernate.view.ArticoloView
    1624 [http-8080-2] INFO org.hibernate.cfg.annotations.QueryBinder - Binding named native query: loadArticoloView => select a.id as id, nome, descrizione, posizione, prezzo, coefficientePrezzo, prezzoFinito, c.testo as categoria, m.quantita as quantita, (select nomefrom articolo_fattura left join fornitore on articolo_fattura.id_fornitore = fornitore.id where id_articolo = a.id order by data_fattura DESC limit 0,1) as fornitore from articolo a left join codcategoria c on c.id = a.id_categoria left join magazzino m on m.id_articolo = a.id where a.id = ?
    1625 [http-8080-2] INFO org.hibernate.cfg.annotations.EntityBinder - Bind entity com.example.testhibernate3.hibernate.view.ArticoloView on table ArticoloView
    La prima riga tutto normale, ha mappato la mia classe.La seconda...sembra che abbia capito che deve usare la query (ma non conosco bene hibernate e non so esattamente come l'abbia intesa...). La terza riga...la tabella non esiste e questa entità non deve essere mappata su una tabella.

    Qualcuno ha idea di cosa stia sbagliando ?

  2. #2
    Prova con il costrutto sql:

    codice:
    create view <nome_tua_vista> as <tua_query>
    forse è lì il problema.

  3. #3
    (non vorrei doverla creare fisicamente sul database)
    come dicevo, non vorrei essere costretto a creare una vista, vorrei simularla in modo da non dover modificare il database e restarne indipendente.
    Non posso credere che hibernate non disponga di un modo per farlo.

  4. #4
    Forse non la crea perchè la query non produce tuple come risultato.

  5. #5
    Originariamente inviato da VincenzoTheBest
    Forse non la crea perchè la query non produce tuple come risultato.
    Come riporta la documentazione (http://www.w3schools.com/sql/sql_view.asp)
    il codice da te proposto crea un vista all'interno del database.

    Non ha nulla a che fare con hibernate, e l'istruzione stessa dovrebbe essere eseguita da console sql (o un client qualunque) e come risultato creerebbe una vista stabile salvata all'interno del db a cui potrei certamente collegare l'entità di hibernate, ma in questo modo ho modificato il database (cosa che voglio evitare).

  6. #6

    [Solved][Hibernate] Simulare una "view" usano il Loader

    Finalmente ho trovato la soluzione, hibernate e' davvero documentato male, in giro per la rete si trovano centinaia di documenti diversi, che si riferiscono alle piu disparate versioni e ognuno spiega qualcosa di diverso dall'altro o che negli altri non c'e'.
    Grazie a uno di questi documenti ho risolto il mio problema, il documento dice:

    codice:
    Sometimes you want to use a view, but you cannot create one in the database (i.e. with a legacy schema). In this case, you can map an immutable and read-only entity to a given SQL subselect expression:
    
    <class name="Summary">
        <subselect>
            select item.name, max(bid.amount), count(*)
            from item
            join bid on bid.item_id = item.id
            group by item.name
        </subselect>
        <synchronize table="item"/>
        <synchronize table="bid"/>
        <id name="name"/>
        ...
    </class>
    Declare the tables to synchronize this entity with, ensuring that auto-flush happens correctly and that queries against the derived entity do not return stale data. The <subselect> is available both as an attribute and a nested mapping element.
    Come potete vedere si riferisce a hibernate usando i file xml, e io odio i file xml.
    Fortunatamente esiste l'annotazione corrispondente:
    codice:
     
    @Entity
    @Subselect(value="select item.name, max(bid.amount) as m, count(*) as c "+
            "from item "+
            "join bid on bid.item_id = item.id "+
            "group by item.name"
    		)
    @Synchronize(value={"item ", "bid "})
    public class Summary implements Serializable {
    //...
    }
    dovete utilizzare gli alias come se fossero dei nomi di colonna e il gioco e' fatto.
    Spero che la cosa possa essere di aiuto a qualcuno.

    ps. chiederei a un moderatore di modificare il titolo

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.