Domanda

In JPA le Entità sono semplici oggetti Java semplici annotati. Ma non ho trovato un buon modo per interagire con loro e il database.

Nella mia app attuale, il mio progetto di base è sempre avere un ID basato sulla sequenza come chiave primaria, quindi di solito devo cercare entità con proprietà diverse da PK.

E per ogni Entità ho un bean stateless di

@Stateless
public class MyEntApiBean implements MyEntApi {


@PersistenceContext(unitName = "xxx") @Inject EntityManager entityManager;

con metodi di query che sono tutte alcune varianti

/**
 * @return A List of all MyEnts that have some property
 * @param someProp some property
 */
public List<MyEnt> getAllMyEntsFromProp(final String someProp) {

    try {
        final Query query = entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp");
        query.setParameter("someProp", someProp);
        return query.getResultList();
    } catch(final NoResultException nre) {
        log.warn("No MyEnts found");
    }
    return new ArrayList<MyEnt>();
}

  1. Odio davvero avere questi metodi in un bean perché sembrano appartenere alle entità stesse e le interfacce locali del bean mi infastidiscono.

  2. Odio la duplicazione che ho in ogni metodo con " try, createQuery, getResultList, catch, log, return " (principalmente una conseguenza di nessuna chiusura o "con dichiarazione" o somesuch in Java).

Qualcuno ha un suggerimento per un modo migliore di interagire con le Entità e il Database che affronti uno o entrambi i miei problemi?

Attualmente sto pensando di fare alcuni metodi di base con generici e riflessioni per ottenere alcuni metodi di query generici per ridurre la duplicazione (problema 2) (metterò un prototipo per la revisione in seguito).

Grazie, Anders

È stato utile?

Soluzione

Prova Seam. Gli Query Objects fanno la maggior parte del lavoro per te e sono facilmente estensibili. Oppure, puoi sempre implementare un modello simile.

In generale, Seam fa molte cose utili per colmare il divario tra JPA e i livelli di visualizzazione e business. Non è necessario utilizzare JSF per Seam per essere utile.

Altri suggerimenti

Stai diventando inutilmente prolisso. Per prima cosa, getResultList () non genera un'eccezione quando non vengono restituite righe (almeno non in Eclipse o Toplink - non riesco a immaginare che un altro provider sia diverso). getSingleResult () lo fa, getResultList () no. Inoltre, puoi utilizzare il modello del generatore in questo modo:

@SuppressWarnings("unchecked")
public List<MyEnt> getAllMyEntsFromProp(final String someProp) {
  return entityManager.createQuery("select me from MyEnt me where me.someProp = :someProp")
    .setParameter("someProp", someProp);
    .getResultList();
}

dovrebbe essere sufficiente per restituire un Elenco di risultati se ce ne sono o uno vuoto se non ce ne sono. Due cose da notare:

  1. @SuppressWarnings (" deselezionato ") non è necessario ma si elimina un avviso altrimenti inevitabile quando si trasmette il risultato non generico dell'elenco da getResultList () a un elenco generico; e

  2. Probabilmente vale la pena sostituire la chiamata createQuery () con una @NamedQuery su MyEnt (in genere). Per prima cosa, ciò consentirà la convalida del tempo di distribuzione e altre cose utili.

È ragionevolmente conciso e completo.

Se fai molte ricerche testuali, forse dovresti anche prendere in considerazione qualche framework di indicizzazione come Bussola .
Non so se si adatta alla tua applicazione, ma in tal caso può migliorare sia la progettazione che le prestazioni del codice.

Attualmente sto usando Seam. E il suggerimento sull'oggetto Query mi porta a trovare Hibernates Domande sui criteri (query per esempio) funzionalità . Sembra molto vicino a quello che stavo cercando.

Forse in una classe base e con un trattino di farmaci generici ....?

Moin!

Ecco la mia versione per singoli risultati (la uso nelle mie applicazioni JPA desktop con elementi essenziali di TopLink):

public class JPA {
  @SuppressWarnings ("unchecked")
  public static <T> T querySingle(
      EntityManager em, 
      Class<T> clazz, 
      String namedQuery, 
      Pair... params) 
  {
    Query q = em.createNamedQuery(namedQuery);
    for (Pair pair : params) {
      q.setParameter(pair.key, pair.value);      
    }
    List<T> result = q.getResultList();
    if ( result.size() == 0 ) {
      return null;
    }
    if ( result.size() == 1 ) {
      return result.get(0);
    }
    throw new 
      IllegalStateException(
        "To many result rows for query: " 
         + namedQuery 
         + " where " 
         + Arrays.toString(params));
  }

  public static class Pair {
    String key;
    Object value;

    public static Pair param (String key, Object value) {
      return new Pair (key, value);
    }

    public Pair (String key, Object value) {
      this.key = key;
      this.value = value;
    }

    @Override
    public String toString() {
      return key + "=" + value;
    }
  }
}

E l'uso:

import static org.sepix.JPA.*;
...

String id = ...
Customer customer = querySingle (em, Customer.class, 
                      "Customer.findByID", Pair.param ("id", id));

o

String inquiryID = ...
Boolean current = Boolean.TRUE;
Inquiry inq = querySingle (em, Inquiry.class, 
                      "Inquiry.findCurrent", 
                      Pair.param ("inquiry", inquiryID),
                      Pair.param ("current", current));

cordiali saluti,   josh.

Preferisco usare Spring's JpaDaoSupport, che aiuta a gestire l'APP. Un buon esempio è qui http: // github .com / rafalrusin / jpaqb / blob / master / src / test / java / jpaqb / CarDao.java .

Una buona separazione della logica è avere una classe DAO (Data Access Object) e DTO (Data Transfer Object). DAO in genere contiene tutte le query richieste e i DTO sono entità con campi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top