2011-01-05 1 views
3

Existe-t-il un moyen généralement accepté de renvoyer une grande liste d'objets à l'aide de Java EE? Par exemple, si vous aviez une base de données ResultSet contenant des millions d'objets, comment les renvoyer à une application cliente (distante)? Un autre exemple - plus proche de ce que je fais actuellement - consisterait à agréger des données de centaines de sources, à les normaliser et à les transférer de façon incrémentielle vers un système client sous la forme d'une seule «liste».Récupération de grandes listes d'objets à l'aide de Java EE

Étant donné que toutes les données ne peuvent pas tenir dans la mémoire, je pensais qu'une combinaison d'un SessionBean avec état et d'un type d'Iterator personnalisé rappelant le serveur ferait l'affaire. En d'autres termes, si j'ai une API comme Iterator<Data> getData(), alors quelle est une bonne façon de mettre en œuvre getData() et Iterator<Data>?

Comment avez-vous résolu ce problème par le passé?

Répondre

2

Ne dupliquez définitivement pas la totalité du DB dans la mémoire de Java. Cela n'a aucun sens et ne fait que rendre les choses inutilement lentes et accrocheuses. Plutôt introduire la pagination au niveau de la base de données. Vous devriez interroger seulement les données que vous avez besoin d'afficher sur la page actuelle, comme le fait Google.

Si vous avez du mal à l'implémenter correctement et/ou à représenter la requête SQL pour la base de données spécifique, jetez un coup d'œil à this answer. Pour l'équivalent JPA/Hibernate, jetez un oeil à this answer.


Mise à jour selon les commentaires (qui change en fait l'objet toute question ...), voici une base (pseudo) coup d'envoi exemple:

List<Source> inputSources = createItSomehow(); 
Source outputSource = createItSomehow(); 

for (Source inputSource : inputSources) { 
    while (inputSource.next()) { 
     outputSource.write(inputSource.read()); 
    } 
} 

De cette façon, vous finissez efficacement avec une seule entrée dans la mémoire de Java au lieu de la collection comme dans ce qui suit (inefficace) par exemple:

List<Source> inputSources = createItSomehow(); 
List<Entry> entries = new ArrayList<Entry>(); 

for (Source inputSource : inputSources) { 
    while (inputSource.next()) { 
     entries.add(inputSource.read()); 
    } 
} 

Source outputSource = createItSomehow(); 

for (Entry entry : entries) { 
    outputSource.write(entry); 
} 
+0

Merci pour la réponse. La base de données était juste un exemple. Je n'utilise pas de base de données et les informations ne sont pas affichées pour un utilisateur. J'agrège des données provenant d'un grand nombre de sources et je les transfère à une autre application. – hallidave

+0

Ensuite, je le ferais par entrée. Traiter/envoyer immédiatement la seule entrée de l'entrée à la sortie sans tenir l'entrée complète dans la mémoire de Java. – BalusC

+0

Alors à quoi ressemblerait la mise en œuvre? Je pensais que l'API serait "Iterator getData()", mais n'était pas sûr de la meilleure façon d'implémenter l'Iterator. Il semble que vous parlez d'une solution basée sur un message? – hallidave

0

Si votre liste est énorme, vous devez un Supposons qu'il ne peut pas tenir dans la mémoire. Ou au moins, si votre serveur doit gérer cela sur de nombreux accès simultanés, vous avez un risque élevé de OutOfMemoryException.

Donc, fondamentalement, ce que vous faites est la pagination et l'utilisation de la lecture par lots. Supposons que vous chargez 1 000 objets de votre base de données, vous les envoyez à la réponse à la demande du client. Et vous bouclez jusqu'à ce que vous ayez traité tous les objets. (Voir la réponse de BalusC)

Le problème est le même côté client, et vous aurez probablement besoin de diffuser les données dans le système de fichiers pour éviter les erreurs OutOfMemory.

Veuillez également noter: Il est possible de charger des millions d'objets à partir d'une base de données en tant que tâche administrative: comme pour effectuer une sauvegarde et exporter un cas «exceptionnel». Mais vous ne devriez pas l'utiliser comme une requête qu'un utilisateur pourrait faire. Il sera lent et drainera les ressources du serveur.

1

La pagination est une bonne solution lorsque vous travaillez avec une interface Web. Cependant, il est parfois beaucoup plus efficace de tout diffuser en un seul appel. la bibliothèque rmiio a été écrite explicitement à cet effet, et est déjà connue pour fonctionner dans une variété de serveurs d'applications.

+0

Cela semble prometteur. Je vais regarder de plus près. Merci. – hallidave