Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    442

    Gestione delle chiavi con MapDB

    Sto sperimentando un problema relativamente alla gestione delle chiavi con MapDB.
    Il mio database è di questo tipo:
    ConcurrentNavigableMap<Integer, Offerta> offerte = db.getTreeMap("offerte");

    Integer rappresenta il tipo di chiave, Offerta è il tipo di oggetto che la mappa deve mantenere.
    Ora, io ho diverse mappe i cui dati sono relazionati fra loro. Con MySql potevo tranquillamente lasciare a lui la gestione del discorso chiavi/id, ma con MapDB questo non mi sembra possibile (se qualcuno può smentirmi, ben venga!). Per cui l'unica soluzione che ho trovato è una cosa del genere, che viene fatta ad ogni inserimento di oggetti nella mappa/db:
    codice:
    int ultimoIdOfferte=0; //inizializzo la chiave
    if (offerte.lastEntry() == null) {
                    ultimoIdOfferte = 1;
                }
                // Altrimenti estraggo ID da assegnare
                else {
                    ultimoIdOfferte = offerte.lastKey();
                }
    Tuttavia con questo sistema se quando rimuovo un'offerta dal db se questa è l'ultima inserita il suo id viene riassegnato perché offerte.lastKey(); estrae chiaramente l'ultima chiave disponibile e se quella che prima era l'ultima non c'è più, lo diventa la precedente.
    Ciò può portare a problematiche nella coerenza dei dati nel caso in cui ci sia qualche dato che ha a sua volta memorizzato un riferimento all'id di quell'offerta.
    Come posso risolvere in maniera più efficiente? Fondamentalmente devo fare in modo che un id già utilizzato non venga mai più riassegnato.
    Grazie.

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Jamie04 Visualizza il messaggio
    codice:
    int ultimoIdOfferte=0; //inizializzo la chiave
    if (offerte.lastEntry() == null) {
                    ultimoIdOfferte = 1;
                }
                // Altrimenti estraggo ID da assegnare
                else {
                    ultimoIdOfferte = offerte.lastKey();
                }
    Se ho capito bene (confermami .. magari ho capito male io), il tuo dubbio/problema è come "prendere" in modo corretto il prossimo ID utile da usare per un inserimento nella mappa.

    Premetto che non ho esperienza con MapDB (ma sto guardando giusto ora della documentazione). Da quanto vedo MapDB offre anche la gestione di oggetti "Atomic" Integer/Long/ecc...

    Non so esattamente che versione stai usando (sto vedendo una versione più "vecchia") ma puoi fare qualcosa del tipo:

    codice:
    Atomic.Integer offerteId = db.getAtomicInteger("offerte_id");

    Poi ogni volta che devi inserire una nuova offerta:

    codice:
    offerte.put(offerteId.incrementAndGet(),  .........  );

    Questo modo di usare gli Atomic Integer/Long ecc.. "persistenti" per gli ID è concettualmente l'equivalente (da quanto intuisco) delle "sequence" nei database come PostgreSQL, Oracle DB, ecc...

    E non dovresti avere problemi, l'incremento e il get sono "atomici", quindi NON puoi avere ID duplicati, né riusati (finché ce ne sono a disposizione .. chiaramente).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    442
    Se ho capito bene (confermami .. magari ho capito male io), il tuo dubbio/problema è come "prendere" in modo corretto il prossimo ID utile da usare per un inserimento nella mappa.
    Il mio problema è come prendere in modo corretto il prossimo ID utile nel caso in cui ci sia stata la cancellazione dell'ultima entry disponibile (o la prima, nel caso la mappa fosse stata vuota).
    Esempio banale: l'ultima asta inserita ha id 5 e diverse offerte che si riferiscono a quell'asta. Con il mio sistema se cancello l'asta con id5 e poi ne creo una nuova a quest'ultima viene assegnato l'id 5, di conseguenza tutte le offerte che prima riferivano l'asta con id5 verrebbero associate a questa nuova asta e ciò sarebbe ovviamente sbagliato. Questo problema l'ho aggirato cancellando anche le offerte riferite all'asta che sto cancellando, il che mi va anche bene dato che questa è la cosa più logica da fare visto che non ha senso mantenere offerte nel db che non riferiscono più nessuna asta esistente.
    Ma il problema mi si può ripresentare anche in altre situazioni visto che deve poter essere possibile cancellare qualsiasi tipo di dato che può avere altri dati che lo referenziano, quindi mi chiedevo se c'è un meccanismo in grado di impedire che un id già precedentemente assegnato (ovviamente per un oggetto di quella mappa) venga riassegnato nuovamente. Siccome gli id li passo io a MapDB lui se ne frega e prende quelli che gli passo (ovviamente) perché a lui basta che non vi siano duplicati nella stessa mappa,quindi nella mia mappa ovviamente non avrò mai due aste
    La versione di MapDB che sto usando è piuttosto vecchia, la 0.9.7.

    Cosa fa esattamente questa istruzione?
    Atomic.Integer offerteId = db.getAtomicInteger("offerte_id");
    E dove dovrei metterla?

    offerte_id sarebbe il nome della mia chiave?

    Considera che io creo/accedo il db in ogni metodo in cui ho bisogno di farlo con queste istruzioni:

    codice:
            DB db = DBMaker.newFileDB(new File(FILE_NAME)).closeOnJvmShutdown().make();
            ConcurrentNavigableMap<Integer, Offerta> offerte = db.getTreeMap("offerte");
    ....
            db.commit();
            db.close();
    Peraltro non ho nemmeno capito se il commit() e il close() devono stare solo alla fine del metodo che accede/modifica i dati nel db. Mi è sembrato di capire che il commit è più o meno l'equivalente di una transazione, cioè o fa tutte le modifiche inserite nel metodo o non ne fa nessuna...almeno credo.

    e questa:
    offerte.put(offerteId.incrementAndGet(), ......... );
    immagino serva per l'inserimento e al punto dei puntini ci vada il nome dell'oggetto da inserire...
    Grazie!!

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Jamie04 Visualizza il messaggio
    Il mio problema è come prendere in modo corretto il prossimo ID utile nel caso in cui ci sia stata la cancellazione dell'ultima entry disponibile (o la prima, nel caso la mappa fosse stata vuota).
    Ma come ho detto prima, con gli Atomic Integer/Long di MapDB che sono "persistenti" (insieme al resto dei tuoi dati) non dovresti avere assolutamente questi problemi.

    Nei DB (PostgreSQL e altri) che hanno le "sequence", quando "stacchi" un Id dalla sequence ... quello è staccato, ce l'hai solo tu. Le sequence vanno sempre e solo in avanti.
    E questo è anche sostanzialmente lo stesso concetto dei campi "auto increment" in MySQL.

    Quote Originariamente inviata da Jamie04 Visualizza il messaggio
    Cosa fa esattamente questa istruzione?
    Atomic.Integer offerteId = db.getAtomicInteger("offerte_id");
    E dove dovrei metterla?
    Così come fai "una tantum" all'inizio della applicazione:

    ConcurrentNavigableMap<Integer, Offerta> offerte = db.getTreeMap("offerte");

    per ottenere la mappa, allora farai all'inizio una tantum il:

    Atomic.Integer offerteId = db.getAtomicInteger("offerte_id");

    per ottenere il Atomic.Integer.

    Quote Originariamente inviata da Jamie04 Visualizza il messaggio
    offerte_id sarebbe il nome della mia chiave?
    Così come "offerte" è il nome della tua mappa all'interno del DB di MapDB .... "offerte_id" sarà il nome di quel Integer "atomico".

    Quote Originariamente inviata da Jamie04 Visualizza il messaggio
    e questa:
    offerte.put(offerteId.incrementAndGet(), ......... );
    immagino serva per l'inserimento e al punto dei puntini ci vada il nome dell'oggetto da inserire...
    Si, ovviamente, il value nella mappa che è l'oggetto Offerta.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    442
    E quando invece rimuovo quale istruzione dovrei usare? Mi sembra che quella che usavo prima non vada, ovvero offerte.remove(offerteId, offertaDaRimuovere);
    Ho provato e non rimuove nulla.
    Ancora grazie!

  6. #6
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    442
    No aspetta forse ho fatto una cavolata io...quando creo l'oggetto passo anche l'id al costruttore e siccome non lo ho più come campo ho fatto:
    Asta nuovaAsta = new Asta (idAsta.incrementAndGet(), utente, nomeOggetto, descrizione, categoria, prezzoBase, dataIns, scadenza, statoAsta);
    aste.put(idAsta.incrementAndGet(), nuovaAsta);

    E già mi sono accorta che mi salta un id perché fa un doppio incremento. Devo togliere l'id dal costruttore di Asta mi sa.

  7. #7
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Jamie04 Visualizza il messaggio
    Devo togliere l'id dal costruttore di Asta mi sa.
    Di per sé è corretto e sensato che ciascun oggetto Asta mantenga il suo Id. Semplicemente "stacca" un Id una volta sola.
    La cosa più semplice sarebbe: passi un nuovo Id ad Asta e poi nel put:

    aste.put(nuovaAsta.getId(), nuovaAsta);


    Se avessi (ipoteticamente) "modellato" meglio le cose, potevi fare una classe apposita che "incapsula" la mappa delle aste (idem per le altre mappe), in modo da offrire metodi più di alto livello e più semplici da usare (e meno error-prone).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  8. #8
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    442
    Infatti se tolgo l'id dal costruttore mi succedono cose strane...dovrei rivedermi tutto il codice e non ne ho il tempo... mi sa che lo devo lasciare e faccio come hai detto tu col getId()...
    Sicuramente si poteva fare molto meglio, il problema è il tempo che non ho e che quando ho cominciato ero veramente messa male. Man mano che sto rispolverando sto capendo molte cose e molti errori fatti ma adesso rimetterci le mani è veramente un casino.

  9. #9
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    442
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Se avessi (ipoteticamente) "modellato" meglio le cose, potevi fare una classe apposita che "incapsula" la mappa delle aste (idem per le altre mappe), in modo da offrire metodi più di alto livello e più semplici da usare (e meno error-prone).
    Ti potresti spiegare meglio su questo punto?
    Effettivamente mi ritrovo con dei grossi problemi ora, soprattutto per la gestione della conclusione delle aste
    Quando un'asta è scaduta il suo stato deve diventare appunto scaduta. Io ho inserito un booleano che però non so come manipolare. Come posso gestire un evento in qualche modo "temporizzato"? La scadenza di un'asta si evince ovviamente da un confronto con la data odierna.
    Ultima modifica di Jamie04; 02-02-2018 a 17:19

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.