Come rendere le chiamate di metodo più generiche quando si hanno a che fare con più tipi di classe?

0

Ho una classe del caricatore che esegue le funzioni di caricamento dei dati in fase di avvio affinché la mia applicazione mi dia dati di prova.

L'idea è piuttosto semplice, sto leggendo in dati XML, usando JaxB per trasformarlo in un POJO e poi persistendo il POJO usando il repo JPA.

Ecco il mio codice (piuttosto piccolo):

Osservando il metodo parseFile , creo una nuova istanza JaxB ma richiede la classe UserContainer. Il problema è che voglio riutilizzare questo metodo per potenzialmente infinitamente molti contenitori. Qual è il modo migliore per refactarlo per renderlo più generico?

Speravo di evitare la necessità di passare un riferimento al tipo di classe in ogni metodo successivo.

@Override
  public void onApplicationEvent(ApplicationReadyEvent event) {
    LOGGER.log(Level.INFO, "Preparing to load data into database");

    try {
      loadAndStoreUserData();
    } catch (IOException | JAXBException e) {
      LOGGER.log(Level.INFO, "Unable to store user data");
      e.printStackTrace();
    }
  }

  /**
   * Loads up any test data from resources and stores into embedded DB for test env
   * @throws IOException
   * @throws JAXBException
   */
  private void loadAndStoreUserData() throws IOException, JAXBException {
    LOGGER.log(Level.INFO, "User data table being added to database");
    UserContainer userData = (UserContainer) ingestFromFile("testDatabase/users.xml", UserContainer);
    userData.getUsers().stream().forEach(userRepo::save);
  }

  /**
   * Read in file from static resources dir
   * @param fileName
   * @return
   * @throws IOException
   * @throws JAXBException
   */
  private Object ingestFromFile(String fileName, Object classReference) throws IOException, JAXBException {
   Resource resource =  new ClassPathResource(fileName);
   return parseFile(resource.getFile());
  }

  /**
   * Takes input file from disk and parsed out contents by marshaling XML -> POJO
   * @param inputFile
   * @return
   * @throws JAXBException
   */
  private Object parseFile(File inputFile) throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(UserContainer.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    return jaxbUnmarshaller.unmarshal(inputFile);
  }
}
    
posta John Lippson 20.04.2018 - 04:12
fonte

2 risposte

0

Perché non puoi semplicemente passare un riferimento alla classe del contenitore? Immagina:

private <T> T parseFile(String fileName, Class<T> targetClass) {
    JAXBContext jaxbContext = JAXBContext.newInstance(targetClass);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    // The cast must be prety safe.
    return targetClass.cast(jaxbUnmarshaller.unmarshal(inputFile));
}
    
risposta data 20.04.2018 - 04:32
fonte
0

Quindi tutte le informazioni che devi sapere sui dati persistenti dai file sono scritte nei file tranne la classe pojo che la rappresenta.

Logicamente, tutto ciò che devi fare è aggiungere queste informazioni al file affinché sia completamente automatico. Eviterei di dover passare in classe al metodo a meno che non sia possibile ottenere la classe attraverso altri mezzi. È sempre possibile codificare un mapping tra il nome del file e la sua classe equivalente pojo, e mentre funzionerebbe, sarebbe comunque l'unica cosa che impedisce di automatizzarlo completamente dalle informazioni nel file, e quindi rimane imbarazzante.

Idealmente ogni e tutte le informazioni sarebbero contenute nel tuo xml, ma se non puoi modificare lo stesso xml, potresti avere un file ".properties" con lo stesso nome che fornisce queste informazioni. Quando si carica l'xml, si carica anche il suo file .properties e si determina in questo modo il nome della classe pojo di implementazione.

Se pensi di poter riutilizzare la stessa classe Pojo per molti file, considera un singolo file di configurazione per ospitare una mappatura tra il file e la sua classe pojo. Piuttosto che cercare un file di configurazione con lo stesso nome con estensione ".properties", devi semplicemente caricare il file di mapping per queste informazioni.

In ogni caso, l'obiettivo dovrebbe essere quello di eliminare ogni traccia di hard-coding. Se volessi fare un ulteriore passo avanti, potresti caricare i dati in una Map contenente coppie chiave / valore piuttosto che usare una classe pojo. Questo è il più adattabile, consentendo di salvare qualsiasi dato senza dover prima creare la sua classe pojo.

    
risposta data 20.04.2018 - 08:42
fonte

Leggi altre domande sui tag