2011-03-07 1 views
0

J'utilise Android avec ORMLite dans une petite application que j'écris actuellement. L'application vise à avoir une fonction d'importation/exportation, pour laquelle j'utilise un framework XML simple. Et tout fonctionne bien, jusqu'à un certain point.Puis-je suspendre temporairement l'ID généré automatiquement dans ORMLite?

La situation est la suivante: L'objet A contient une clé étrangère référençant l'objet B, qui référence l'objet C via une clé étrangère elle-même. L'exportation d'une base de données est géniale. L'importation fonctionne, avec un petit avertissement, à savoir que cela fonctionne tant que les ID de tous les objets sont séquentiels et commencent à partir de 1. Mais si la base de données est fragmentée, je supprime un enregistrement ici et là, après avoir exporté la base de données, J'ai des "trous" dans la structure XML générée. Les exemples d'objets peuvent être:

@DatabaseTable("orders") 
public class Order { 
    @DatabaseField(generatedId = true) 
    private int _id; 
    @DatabaseField(columnName="date") 
    private Date _date; 
    @DatabaseField(columnName="cost") 
    private double _cost; 
    @DatabaseField(foreign = true, columnName="customer_id") 
    private Customer _customer; 
    // ... more fields, getters and setters 
} 

@DatabaseTable("customers") 
public class Customer { 
    @DatabaseField(generatedId = true); 
    private int _id; 
    @DatabaseField 
    private String _name; 
    // ... more fields, getters and setters 
} 

Disons que j'ai une base de données avec 2 clients (id 1 et 2), qui détiennent respectivement des ordres de 1 à 5 et 6 à 8. L'exportation de ces puis réimporter dans un base de données propre fonctionne très bien. Si toutefois supprimer le client 1 et leurs commandes et l'exporter, l'exportateur écrire leur carte d'identité qu'ils sont, à savoir

<customer id="2">...</customer> 

et

<order id="6">...</order> 
<order id="7">...</order> 
<order id="8">...</order> 
<order id="9">...</order> 

etc. Quand j'importer les données dans une nouvelle base de données , je voudrais tout d'abord enregistrer l'objet client via

custDao.create((Customer)x); 

et chacun de leurs commandes via

orderDao.create((Order)o); 

Le problème est que la fonction de création ne tient pas compte de l'ID fourni (qui n'est pas 0) et l'ID nouvellement généré pour le client est 1 (dans une nouvelle base de données vide). Pareil pour les commandes. Mais comme ils font référence au client avec id = 2, le lien entre eux est rompu. Donc, après cette explication un peu longue, voici ma question: Y a-t-il un moyen de dire à ORMLite de prendre la valeur fournie pour un champ generatedId et de l'exécuter, au lieu de l'écraser? Je serais OK, si une exception est générée dans le cas où la fonction create trouve une ligne déjà dans la table avec le même ID, mais continuerait à enregistrer l'enregistrement sinon ... J'ai pensé à une solution de contournement pour cela: tous les objets devraient être triables par ID en utilisant l'interface Comparator; trier ArrayList avec les objets à importer; pour chaque objet - lire l'id supposé dans un int, - sauvegarder dans la base de données en utilisant dao.create, - si le nouvel id de l'objet est différent de l'id supposé, le changer via dao.updateId, - passer à l'objet suivant dans la liste Mais cela semble trop lourd et sujet aux erreurs: que se passe-t-il si la méthode create tente de générer un identifiant, que vous venez de réattribuer à un objet précédent avec updateId?

Je ne crois pas que ma situation soit si rare, que personne ne l'ait déjà rencontré auparavant. J'apprécierais une solution!

meilleures salutations,

+0

Je voulais juste vous assurer que vous avez vu la mise à jour de ma réponse @todor. – Gray

Répondre

2
Todor

ORMLite supporte une option allowGeneratedIdInsert=true-@DatabaseField annotation qui permet l'insertion d'un objet avec l'ID déjà défini dans une table-id généré. Si la valeur du champ ID est nulle ou la valeur par défaut (0, ...), la base de données génère l'ID. Ceci n'est pas supporté par tous les types de bases de données (Derby par exemple). Voici another discussion sur ce sujet spécifique.


Je ne pense la bonne chose à faire ici est de construire votre graphique d'objets en mémoire, associant la appropriéeCustomer sur leurs Order objets avant l'enregistrement d'un d'entre eux sur le disque. Si vous lisez vos clients en mémoire, lisez les objets Order et définissez l'objet réel Customer sur chacun d'entre eux. Lorsque vous créez ensuite chaque objet Customer dans la base de données, ORMLite remplacera le champ id par le champ généré, ce qui le modifiera également dans le champ customer_id enregistré dans chaque champ Order.

Si vous avez une tonne de données et que vous ne pouvez pas tout lire en mémoire (ou pour toute autre raison), vous pouvez toujours créer un Map<Integer,Integer> et enregistrer l'ID Customer du mappage XML vers l'ID que vous obtenez après l'avoir créé dans la base de données. Ensuite, lorsque vous chargez dans les objets Order, vous pouvez définir le nouvel ID corrigé sur l'objet étranger.

Espérons que cela aide. Laissez-moi savoir quelques détails sur la façon dont vous lisez dans les objets et je peux donner un meilleur exemple de la façon de construire le graphique de l'objet.

+0

Eh bien, oui, je suis d'accord que créer tout en mémoire et définir toutes les relations d'objet avant de sauvegarder quoi que ce soit fonctionnera, mais c'est une solution pour les ensembles de données les plus simples ou les plus simples. Et il ouvre une toute nouvelle boîte de Pandore: que se passe-t-il si l'ensemble de données fait partie d'une autre base de données de bureau ou de serveur? Les ID de réécriture vont certainement casser des choses. Ou que se passe-t-il si les ID sont utilisés pour autre chose, comme la création de factures ou de notifications de livraison et que quelqu'un doit restaurer à partir d'une sauvegarde? Changer les ID sur la restauration de la base de données est un gros no-no de tous les administrateurs de base de données qui se respectent ... –

+0

Si vous parlez d'une restauration de base de données, je suis d'accord que changer les identifiants est baaad. Je pensais que vous parliez d'une «petite» application Android qui importe des enregistrements supplémentaires à partir de XML, où il pourrait y avoir chevauchement des identifiants. S'il y a chevauchement des identifiants qui sont référencés dans une autre base de données, vous avez d'autres problèmes. Est-ce que la 2ème partie de ma réponse n'aide pas? Il vous montre comment utiliser un deuxième objet pour insérer des identifiants non générés dans la même table. – Gray

+0

En outre, je souligne très précisément dans ma réponse que l'assemblage des objets en mémoire ne concerne qu'une petite quantité de données. Avez-vous réellement lu toute la réponse? – Gray

Questions connexes