Newsgroup: it.comp.java
Titolo: JPA lento con query su database remoti

Ciao a tutti,
ho sviluppato un'applicazione desktop che accede ai dati di un
database remoto mediante JPA, utilizzando Toplink Essentials come
provider. Sto riscontrando una estrema lentezza nel caricamento dei
dati quando il database è remoto, cosa che non succede in locale.
Sapreste consigliarmi come fare per risolvere il problema? Non vorrei
dover riconvertire tutta l'applicazione all'utilizzo di JDBC...
Grazie mille in anticipo per il vostro aiuto!

Forse potrei risolvere il problema con il paging...
Che ne pensate? Come potrei implementarlo? L'applicazione è stata
sviluppata con Netbeans, sapete se offre qualcosa in merito al paging?

 Forse potrei risolvere il problema con il paging...
in Query ci sono 2 metodi per fare il paging:
setMaxResults
setFirstResult

Ho implementato un sistema di paging in JPA seguendo questo utile
tutorial
http://www.google.com/url?sa=D&q=http://rubenlaguna.com/wp/2009/08/18/jtable-beans-binding-and-jpa-pagination&usg=AFQjCNGmUb9nmbBWcN4q8ITyZI2r8ye2Ig
.
Ma non sono soddisfatto dalle sue performance, infatti lo scroll
verticale non è immediato, bisogna attendere finchè non carica il
subset di righe rimanenti.
Pensate che in JDBC puro avrei performance migliori?
Avreste qualche idea su come migliorare la performance delle query in
JPA su db remoti?
Per essere più chiaro, ecco la mia query JPA ed il codice della
Entity:
//query
String query = "SELECT a FROM Articoli a";
Query q = entityManager.createQuery(query);
java.util.Collection data = q.getResultList();
for (Object entity : data) {
   entityManager.refresh(entity);
}
list.clear();
list.addAll(data);
//entity, Articoli.java
@Entity
@Table(name = "articoli")
@NamedQueries({
        ..qui sono le NamedQueries per chiascun campo..
})
public class Articoli implements Serializable {
    @Transient
    private PropertyChangeSupport changeSupport = new
PropertyChangeSupport(this);
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "CodiceArticolo")
    private Integer codiceArticolo;
    @Basic(optional = false)
    @Column(name = "Descrizione")
    private String descrizione;
    @Column(name = "H")
    private BigDecimal h;
    @Column(name = "L")
    private BigDecimal l;
    @Column(name = "Diametro")
    private BigDecimal diametro;
    @Column(name = "Spessore")
    private BigDecimal spessore;
    @Basic(optional = false)
    @Column(name = "prezzo")
    private BigDecimal prezzo;
    @Column(name = "Lungh")
    private BigDecimal lungh;
    @Column(name = "Peso")
    private BigDecimal peso;
    @Column(name = "Lung_scatola")
    private BigDecimal lungscatola;
    @Column(name = "Larg_scatola")
    private BigDecimal largscatola;
    @Column(name = "H_scatola")
    private BigDecimal hscatola;
    @Column(name = "Peso_scatola")
    private BigDecimal pesoscatola;
    @Column(name = "Spessore_max")
    private BigDecimal spessoremax;
    @Column(name = "Lampada")
    private String lampada;
    @Column(name = "Watt")
    private BigDecimal watt;
    @Column(name = "Lumen")
    private BigDecimal lumen;
    @Column(name = "Temp_colore")
    private BigDecimal tempcolore;
    @Column(name = "Trattamento")
    private String trattamento;
    @Column(name = "T_50_min")
    private BigDecimal t50min;
    @Column(name = "T_50_max")
    private BigDecimal t50max;
    @Column(name = "Id")
    private BigDecimal id;
    @Column(name = "Od")
    private BigDecimal od;
    @Version
    protected int version;
    @JoinColumn(name = "CodiceSezione", referencedColumnName =
"codice")
    @ManyToOne
    private Sezione codiceSezione;
    @JoinColumn(name = "CodiceCategoria1", referencedColumnName =
"codice")
    @ManyToOne
    private Categoria codiceCategoria1;
    @JoinColumn(name = "CodiceCategoria2", referencedColumnName =
"codice")
    @ManyToOne
    private Categoria codiceCategoria2;
    @JoinColumn(name = "CodiceCategoria3", referencedColumnName =
"codice")
    @ManyToOne
    private Categoria codiceCategoria3;
    @JoinColumn(name = "CodiceCategoria4", referencedColumnName =
"codice")
    @ManyToOne
    private Categoria codiceCategoria4;
    @OneToMany(cascade = CascadeType.ALL, mappedBy =
"codicearticolomagaz")
    private Collection<Magazzinodettaglio>
magazzinodettaglioCollection;
    @OneToMany(cascade = CascadeType.ALL, mappedBy =
"codicearticolofornitore")
    private Collection<Articolifornitori>
articolifornitoriCollection;
    public Articoli() {
    }
    public Articoli(Integer codiceArticolo) {
        this.codiceArticolo = codiceArticolo;
    }
    public Articoli(Integer codiceArticolo, String descrizione,
BigDecimal prezzo) {
        this.codiceArticolo = codiceArticolo;
        this.descrizione = descrizione;
        this.prezzo = prezzo;
    }
    ..qui sono i metodi getter/setter per ciascun campo..
    public Collection<Magazzinodettaglio>
getMagazzinodettaglioCollection() {
        return magazzinodettaglioCollection;
    }
    public void
setMagazzinodettaglioCollection(Collection<Magazzinodettaglio>
magazzinodettaglioCollection) {
        this.magazzinodettaglioCollection =
magazzinodettaglioCollection;
    }
    public Collection<Articolifornitori>
getArticolifornitoriCollection() {
        return articolifornitoriCollection;
    }
    public void
setArticolifornitoriCollection(Collection<Articolifornitori>
articolifornitoriCollection) {
        this.articolifornitoriCollection =
articolifornitoriCollection;
    }
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (codiceArticolo != null ? codiceArticolo.hashCode() :
0);
        return hash;
    }
    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Articoli)) {
            return false;
        }
        Articoli other = (Articoli) object;
        if ((this.codiceArticolo == null && other.codiceArticolo !=
null) || (this.codiceArticolo != null && !
this.codiceArticolo.equals(other.codiceArticolo))) {
            return false;
        }
        return true;
    }
    @Override
    public String toString() {
        return "desktopapplication1.Articoli[codiceArticolo=" +
codiceArticolo + "]";
    }
    public void addPropertyChangeListener(PropertyChangeListener
listener) {
        changeSupport.addPropertyChangeListener(listener);
    }
    public void removePropertyChangeListener(PropertyChangeListener
listener) {
        changeSupport.removePropertyChangeListener(listener);
    }
}
Se non è abbastanza, fatemi sapere per favore, e preparerò
un'applicazione di esempio.


Ho risolto il problema!
Era dovuto alla mancanza di una corretta dichiarazione delle relazioni
ManyToOne - OneToMany... :-)
Grazie lo stesso ragazzi!
-
http://carmelosaffioti.blogspot.com
-

 String query = "SELECT a FROM Articoli a";
Vedo a tentoni...forse hai campi particolarmente lunghi o magari 
addirittura dei blob che non ci hai mostrato? In quel caso potresti 
avere differenze tra locale e remoto, per questioni di buffering.
Comunque se "select a from Articoli a" torna quantità enormi di dati, è 
il caso che ridisegni l'interfaccia grafica in modo da obbligare 
l'utente ad una ricerca più mirata.
Dopotutto non ha alcun senso navigare a caso tra migliaia di record.

 ManyToOne - OneToMany... :-)
E il discorso locale / remoto?