db4o Developer Community

db4o open source object database, native to Java and .NET
Welcome to db4o Developer Community Sign in | Join
in Search
More Search Options

ArrayList oder die einzelnen Elemente davon löschen?

Last post 08-16-2008, 03:33 PM by mjablonski. 3 replies.
Sort Posts: Previous Next
  •  08-15-2008, 09:27 AM 50650

    ArrayList oder die einzelnen Elemente davon löschen?

    Vereinfacht gesagt habe ich eine Klasse „Rezept“ die eine ArrayList mit Zutaten enthält. Diese Zutaten sind wieder Objekte. Bei jedem Speichern eines Rezeptes (nicht bei der Neuerfassung sondern beim Bearbeiten eines vorhandenen Rezepts) müssen erst alle Zuordnungen zu Zutaten gelöscht und aus einer temporären Liste wieder gespeichert werden. Nun habe ich eine Frage zu dem Vorgehen. Reicht es die vorhandene ArrayList zu ersetzen? Oder muss ich jedes Objekt aus der ArryList einzeln löschen?
  •  08-15-2008, 01:17 PM 50652 in reply to 50650

    Re: ArrayList oder die einzelnen Elemente davon löschen?

    Hallo,

    ich würde sagen: weder noch. Das folgende Beispiel zeigt Dir, was passiert, wenn man "naiv" die ArrayList einfach durch eine neue ersetzt... plötzlich hat man lauter ArrayList-Objekte in der Datenbank, die man aber gar nicht haben will.

    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;

    import com.db4o.Db4o;
    import com.db4o.ObjectContainer;

    class Rezept {

        private List<Zutat> zutaten;

        public void setZutaten(List<Zutat> zutaten) {
            this.zutaten = zutaten;
        }
    }

    class Zutat {

        private String name;

        public Zutat(String name) {
            this.name = name;
        }
    }

    public class RezeptDatenbank {

        public static void main(String[] args) {
            new File("test.yap").delete();

            ObjectContainer db4o = Db4o.openFile("test.yap");

            // Rezept speichern
            Rezept rezept = new Rezept();
            List<Zutat> zutaten = new ArrayList<Zutat>();
            rezept.setZutaten(zutaten);
            db4o.set(rezept);
            db4o.commit();

            // Zutatenliste 100 mal aktualisieren
            Zutat salz = new Zutat("Salz");
            Zutat zucker = new Zutat("Zucker");
            for (int i = 0; i < 100; i++) {
                zutaten = new ArrayList<Zutat>();
                zutaten.add(zucker);
                zutaten.add(salz);
                rezept.setZutaten(zutaten);
                db4o.set(rezept);
                db4o.commit();
            }

            // Jetzt sind 101 ArrayLists in der Datenbank gespeichert...
            System.out.println(db4o.get(List.class).size());

            db4o.close();
        }

    Es gibt jetzt verschiedene Strategien:

    • entweder die vorhandene ArrayList wiederverwenden (also ein list.clear(), dann über list.addAll() wieder Zutaten hinzufügen), dabei aber auf die korrekte UpdateDepth achten, damit auch die Liste wirklich aktualisiert in der Datenbank gespeichert wird.
    • wenn Du die Liste ersetzen willst, dann müsstest Du das "alte" List-Objekt löschen, damit Du Dir damit nicht die Datenbank volldudelst.
    • Eine andere Strategie könnte darin bestehen, statt der ArrayList einfach ein Array zu benutzen (mache ich in der Regel). Das verhält sich so wie man es wohl eher erwartet: wenn das vorhandene Array ersetzt wird, dann verschwindet damit auch das alte Array aus der Datenbank.
    • Sicher gibt's auch noch andere Varianten...;-)
    Grüße, Maik

    http://db4o.blogspot.com/
  •  08-16-2008, 01:18 PM 50659 in reply to 50652

    Re: ArrayList oder die einzelnen Elemente davon löschen?

    mjablonski:
    entweder die vorhandene ArrayList wiederverwenden (also ein list.clear(), dann über list.addAll() wieder Zutaten hinzufügen), dabei aber auf die korrekte UpdateDepth achten, damit auch die Liste wirklich aktualisiert in der Datenbank gespeichert wird.
    • wenn Du die Liste ersetzen willst, dann müsstest Du das "alte" List-Objekt löschen, damit Du Dir damit nicht die Datenbank volldudelst

    Ich würde schon ganz gern bei ArrayList bleiben, denke ich. Ich werde die List weiter verwenden.

    Aber nur aus Interesse:

    1. Kann man list.clear() und list.addAll() in einer Transaktion durchführen, oder muss ich nach list.clear() das Rezept erst speichern und dann die Liste füllen?

    2. Wie kann ich das alte List-Objekt löschen?

  •  08-16-2008, 03:33 PM 50663 in reply to 50659

    Re: ArrayList oder die einzelnen Elemente davon löschen?

    GambaJo:
    1. Kann man list.clear() und list.addAll() in einer Transaktion durchführen, oder muss ich nach list.clear() das Rezept erst speichern und dann die Liste füllen?

    Das hängt etwas von deinem Transaktionsbegriff ab: natürlich ist clear()/addAll() keine atomare Operation, aber das Ersetzen der ArrayList durch eine andere ja auch nicht, von daher sehe ich da erstmal kein "transaktionelles" Problem.

    Hier mal ein Beispiel, wie das Beispiel von oben geändert werden müsste:

    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;

    import com.db4o.Db4o;
    import com.db4o.ObjectContainer;

    class Rezept {

        private List<Zutat> zutaten = new ArrayList<Zutat>();

        public void setZutaten(List<Zutat> zutaten) {
            this.zutaten.clear();
            this.zutaten.addAll(zutaten);
        }
       
        public String toString() {
            return zutaten.toString();
        }
    }

    class Zutat {

        private String name;

        public Zutat(String name) {
            this.name = name;
        }
       
        public String toString() {
            return name;
        }
    }

    public class RezeptDatenbank {

        public static void main(String[] args) {
            new File("test.yap").delete();

            Db4o.configure().objectClass(Rezept.class).objectField("zutaten").cascadeOnUpdate(true);
            // Alternativ, aber etwas "gröber":
            // Db4o.configure().objectClass(Rezept.class).cascadeOnUpdate(true);
            ObjectContainer db4o = Db4o.openFile("test.yap");

            // Rezept speichern
            Rezept rezept = new Rezept();
            List<Zutat> zutaten = new ArrayList<Zutat>();
            rezept.setZutaten(zutaten);
            db4o.set(rezept);
            db4o.commit();

            // Zutatenliste 100 mal aktualisieren
            Zutat salz = new Zutat("Salz");
            Zutat zucker = new Zutat("Zucker");
            for (int i = 0; i < 100; i++) {
                zutaten = new ArrayList<Zutat>();
                zutaten.add(zucker);
                zutaten.add(salz);
                rezept.setZutaten(zutaten);
                db4o.set(rezept);
                db4o.commit();
            }

            // Jetzt ist eine ArrayList in der Datenbank gespeichert...
            System.out.println(db4o.get(List.class).size());

            db4o.close();
           
            // Zur Kontrolle einmal das Rezept ausgeben
            db4o = Db4o.openFile("test.yap");
            System.out.println(db4o.get(Rezept.class));
            db4o.close();
        }
    }
     

    GambaJo:
    2. Wie kann ich das alte List-Objekt löschen?

    db4o.delete(dasAlteListObject);

    Das kann allerdings etwas "tricky" werden, wenn man eine saubere Trennung der Domain-Klassen von der Persistenzschicht anstrebt, weil man ja die ArrayList aus der Rezept-Klasse (die ja eigentlich ein privates Geheimnis der Rezept-Klasse  ist), ja irgendwie an die Datenbank rausreichen muss. In unserem Beispiel wäre das ja sogar halbwegs problemlos möglich, weil man sich ja über die getZutaten() die alte Liste vor dem setZutaten() holen könnte, um so anschließend in der Datenbank zu löschen.

    Grüße, Maik


    http://db4o.blogspot.com/
View as RSS news feed in XML