# Wie kopieren ich eine Spalte von einer Tabelle in eine andere Tabelle SQLite durch java code?



## Bajra (7. Feb 2021)

Hallo zusammen, ich bin relative neue in Java und ich brauche eure Hilfe. wie könne ich eine Methode davon machen, den den SQLite Anfrage entspricht.

ich will von der Tabelle groupsAddPeptides die pepID  in der peptides  Tabelle einfügen. Beide egsitieren schon.


```
UPDATE peptides SET pGroup = (SELECT pepID FROM groupsAddPeptides Where id = peptides.id)
```

Auf eine Antwort oder Erklärung würde ich mich sehr freuen.


----------



## mihe7 (7. Feb 2021)

Du baust eine JDBC-Verbindung zur Datenbank auf und hast dann ein Connection-Objekt. Mit dem kannst Du dann etwas wie

```
String sql = "UPDATE peptides SET pGroup = (SELECT pepID FROM groupsAddPeptides Where id = peptides.id)";
try(Statement stmt = conn.createStatement()) {
    stmt.executeUpdate(sql);
}
```
machen.


----------



## Bajra (7. Feb 2021)

mihe7 hat gesagt.:


> Du baust eine JDBC-Verbindung zur Datenbank auf und hast dann ein Connection-Objekt. Mit dem kannst Du dann etwas wie
> 
> ```
> String sql = "UPDATE peptides SET pGroup = (SELECT pepID FROM groupsAddPeptides Where id = peptides.id)";
> ...


Danke dir.


----------



## mihe7 (7. Feb 2021)

Noch ein Hinweis: solltest Du in die Verlegenheit kommen, eine parametrisierte Query ausführen zu müssen, bau das SQL nicht selbst zusammen. Hierfür gibt es PreparedStatement, so dass Du in den Query-String Parameter einbauen und deren Werte im Nachhinein bestimmen kannst. Alles andere ist 99,9 % der Fälle Murks.


----------



## Bajra (10. Feb 2021)

mihe7 hat gesagt.:


> Noch ein Hinweis: solltest Du in die Verlegenheit kommen, eine parametrisierte Query ausführen zu müssen, bau das SQL nicht selbst zusammen. Hierfür gibt es PreparedStatement, so dass Du in den Query-String Parameter einbauen und deren Werte im Nachhinein bestimmen kannst. Alles andere ist 99,9 % der Fälle Murks.


Ich hätte noch eine Frage. Ich habe nicht eine Idee, wie ich das  TreeMap<Long, Group> child in der Datenbank speicher kann. 
Ich bin da durcheinander und ich wies nicht wie ich das anders geht.  Das ist die einzige Methode, wo ich eine Map habe. Ich bin seit zwei Tagen dran. 

Auf eine Antwort würde ich mich sehr freuen. 
Danke!




```
public void updateChildIdsSqliteDB(Group groupID, TreeMap<Long, Group> child ) {

        ResultSet rs = null;
        String sql = "INSERT INTO groupsAddChild(groupID, childID) VALUES (?,?)";

        try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
                    
            pstmt.setString(1, groupID.getGroupsID());

           [B] pstmt.setNString(2, child); // Das geht nicht!!![/B]

            pstmt.executeUpdate();
            connection.commit();

        } catch (Exception e) {
            e.getMessage();
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                LOGGER.error(e);
            }
        }
    }
```


----------



## mihe7 (10. Feb 2021)

Dazu müsste ich wissen, was die TreeMap eigentlich abbildet und wie die groupID im Verhältnis zu child steht.


----------



## Bajra (10. Feb 2021)

Das ist die XML-Ausgabe und die ist richtig Aber mir fehlt die Idee die gleiche im SQLite zu abbilden. Ich hoffe, dass es das Bild dir hilft zu verstehen.

Diese 140 wird in den Map gespeichert und Übergabe die groupID mit


----------



## mihe7 (10. Feb 2021)

So blick ich da nicht durch, daher einfach mal ins Blaue hinein:


```
private static final String INSERT_GROUP_CHILD =
           "INSERT INTO groupsAddChild(groupID, childID) VALUES (?,?)";

   public void updateChildIdsSqliteDB(Group groupID, Map<Long, Group> children ) {
        try (PreparedStatement pstmt = connection.prepareStatement(INSERT_GROUP_CHILD)) {
            for (Long childId : children.keySet()) {
                pstmt.setString(1, groupID.getGroupsID());
                pstmt.setLong(2, childId);
                pstmt.addBatch(); // Satz von Parametern hinzufuegen
            }
            pstmt.executeBatch(); // alles auf einmal ausfuehren -> schnell
            connection.commit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
```
Den finally-Block brauchst Du nicht. Da wir hier try-with-resources verwenden, wird das Statement automatisch geschlossen.


----------



## mrBrown (10. Feb 2021)

mihe7 hat gesagt.:


> ```
> catch (Exception e) {
> e.getMessage();
> }
> ```



Da hast du dich vertippt


----------



## mihe7 (10. Feb 2021)

mrBrown hat gesagt.:


> Da hast du dich vertippt


Scheiß Copy and Paste.

EDIT: angepasst, danke.


----------



## Bajra (11. Feb 2021)

mihe7 hat gesagt.:


> So blick ich da nicht durch, daher einfach mal ins Blaue hinein:
> 
> 
> ```
> ...


Moin und noch mal  viele lieben danke dafür. Es hat mir super geholfen und danke für den Tipp. Es ist auch schneller beim Schrieben jetzt. Was könnte man machen, dass es beim Lesen schneller wird? Ich schick dir meine Implementierung was ich für die gleiche Funktion gemacht habe.

```
@Override
    public Map<Long, Group> getChildren(Group groupID) {
        String sqlGetChildrensID = "SELECT childID FROM groupsAddChild WHERE groupID = ?";

        Map<Long, Group> children = new TreeMap<>();
        try (PreparedStatement pstmt = connection.prepareStatement(sqlGetChildrensID)) {
            pstmt.setString(1, groupID.getGroupsUniqueID());
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    long childID = rs.getLong("childID");

                    children.put(childID, groupID);
                }

            }

        } catch (SQLException e) {
            e.printStackTrace();
            LOGGER.error(e);
            
        }
        return children;
    }
```


----------



## mihe7 (11. Feb 2021)

Beni hat gesagt.:


> Was könnte man machen, dass es beim Lesen schneller wird?


Wichtig ist, dass die betreffenden Sätze von der DB schnell gefunden werden, was man durch Primärschlüssel bzw. Indizes erreicht. Ich gehe mal davon aus, dass (groupId, childId) einen Primärschlüssel bildet, insofern sollte die Suche kein Problem darstellen.


----------



## Bajra (14. Feb 2021)

So ist das bei der Maps implementiert worden. Ich will die gleiche beim SQLite Implementierung haben. Versucht habe ich auch, aber ich kriege NullPointerException. Unten ist die Implementierung was ich versucht habe 



```
private Map<String, Map<String, Accession>> accessions;

    this.accessions = new HashMap<>();


    // mit der Methode wird in der Datenbanke eingefügt 
    @Override
    public void groupsAddAccession(Group group, Accession accession) {

        Map<String, Accession> acc = accessions.get(group.getGroupsUniqueID());

        if (acc == null) {
            acc = new HashMap<String, Accession>();
        }

        acc.put(accession.getAccession(), accession);
        accessions.put(group.getGroupsUniqueID(), acc);
    }


    // hier wird es gelesen
@Override
    public Map<String, Accession> getAccessions(Group group) {
        
        Map<String, Accession> acc = accessions.get(group.getGroupsUniqueID());
        if(acc ==  null) {
            acc = new HashMap<>();
        }
        
        accessions.put(group.getGroupsUniqueID(), acc);
        return acc;
    }
```


```
private Map<String, Map<String, Accession>> accessions;

//Im Konstruktor
this.accessions = new HashMap<>();

@Override
    public void groupsAddParent(Group currenGroup, Group parent) {
        TreeMap<Long, Group> parentsMap = parents.get(currenGroup.getGroupsUniqueID());
        if(parentsMap == null) {
            parentsMap = new TreeMap<>();
        }
        parentsMap.put(parent.getID(), parent);
        parents.put(currenGroup.getGroupsUniqueID(), parentsMap);

    }
    
  private Map<String, Map<String, Accession>> accessions;
    @Override
    public Map<String, Accession> getAccessions(Group group) {
        
        Map<String, Accession> acc = accessions.get(group.getGroupsUniqueID());
        if(acc ==  null) {
            acc = new HashMap<>();
        }
        
        accessions.put(group.getGroupsUniqueID(), acc);
        return acc;
    }



// Für die SQLite
@Override
    public void groupsAddAccession(Group group, Accession acc) {
         /** SQL for inserting new addPeptides in the groups */
         String sqlNewGroupsAddAccession = "INSERT INTO groupsAddAccessions(groupID, accId, accessions) VALUES (?,?,?)";
        try (PreparedStatement pstmt = connection.prepareStatement(sqlNewGroupsAddAccession)) {
            pstmt.setString(1, group.getGroupsUniqueID());
            pstmt.setLong(2, acc.getID());
            pstmt.setString(3, acc.getAccession());

            pstmt.addBatch();
            pstmt.executeBatch();
            connection.commit();
        
                        
        } catch (Exception e) {
            e.getMessage();
        
        }
        
    }
    //TODO


    @Override
    public Map<String, Accession> getAccessions(Group groupID) {
        String sqlGetAccessionsID = "SELECT accId, accessions FROM groupsAddAccessions WHERE groupID = ?";
        Map<String, Map<String, Accession>> a = new ConcurrentHashMap<String, Map<String,Accession>>();
        
        Map<String, Accession> acc = a.get(groupID.getGroupsUniqueID());
    
        try (PreparedStatement pstmt = connection.prepareStatement(sqlGetAccessionsID)) {
            pstmt.setString(1, groupID.getGroupsUniqueID());
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    long accId = rs.getLong("accId");
                    String accession = rs.getString("accessions");
                    
                    acc.put(accession, new Accession(accId, this));
                    a.put(groupID.getGroupsUniqueID(), acc);
                }
            }
        } catch (SQLException e) {
            LOGGER.error(e);
        }
        return acc;
    }
```


----------



## mihe7 (14. Feb 2021)

Vergiss mal Deinen Code und versuche zu erklären, was Du eigentlich machen willst (nicht die Lösung oder Teile davon, sondern das Problem beschreiben). Das scheint ja irgendwas mit Zugriffs(rechten) und Gruppen zu tun zu haben, die irgendwie miteinander zusammenhängen.


----------



## Bajra (14. Feb 2021)

mihe7 hat gesagt.:


> Vergiss mal Deinen Code und versuche zu erklären, was Du eigentlich machen willst (nicht die Lösung oder Teile davon, sondern das Problem beschreiben). Das scheint ja irgendwas mit Zugriffs(rechten) und Gruppen zu tun zu haben, die irgendwie miteinander zusammenhängen.


Ja. In dem ersten Teil wird ja bei der groupsAddAccession Methode eine ID (Das ist UUID von der Java Klasse als String) und das Accession Objekt übergeben. Dort wird das Id zum referenzieren in der Map mit übergeben. Dann wird das durch diese ID geholt und zurück in der Group klasse. Der Teil läuft richtig. Der untere Teil ist aber falsch, der soll das Gleiche tun, was das oberen tut. Außer hier soll von der Datenbank geschrieben und zurückgeliefert.  Ich will halt von Maps loswerden, deswegen speicher ich in der Datenbank.


----------



## Bajra (14. Feb 2021)

Das Problem bei der Gruppe klasse ist, dass die Gruppe durch Threads erstellt werden. Die bekommen Accession(Protein) und Peptide (genau gleiche wie die Obere Methoden) und die zusammen erstellen eine Gruppe. Es ist halt schwierig bei der Klasse, weil es keine Feste Id gibt und deswegen habe ich das UUID benutzt. Habe es mit zähler probieret, wieder kommische Zahelen in der Datenbank bekommen. Mit der UUID klappt es bessere aber es fällt mir jetzt schwirig diese Implementierung von Mpas gleiche auch bei der SQLite Klasse zu haben.


----------



## mihe7 (14. Feb 2021)

Das einzige, was ich jetzt problembezogenes gelesen habe, ist, dass eine Gruppe aus Accession und Peptide besteht. Das wäre eine simple 1:n-Beziehung zwischen Gruppe und Accession bzw. Peptide.


----------



## Bajra (14. Feb 2021)

mihe7 hat gesagt.:


> Das einzige, was ich jetzt problembezogenes gelesen habe, ist, dass eine Gruppe aus Accession und Peptide besteht. Das wäre eine simple 1:n-Beziehung zwischen Gruppe und Accession bzw. Peptide.


Ja genau, mindesten 1 Peptide und 1 Accession muss eine Gruppe haben. Es gibt fälle wo es mehr peptide oder Accession in einer Grupper vorkommen.


----------



## mihe7 (14. Feb 2021)

Kann ein und dasselbe Peptide/Acccession in mehreren Gruppen auftauchen?


----------



## mihe7 (14. Feb 2021)

OK, wenn ich es richtig verstehe, dann hätte ich mal drei Tabellen für Grupe, Peptide und Accession:

Gruppe: ID, Name
Peptide: ID, Name
Accession: ID, Name

und zwei Tabellen, mit denen die Beziehungen dargestellt werden:

Gruppe_Peptide: Gruppe_ID, Peptide_ID
Gruppe_Accession: Gruppe_ID, Accession_ID

Mir ist nur nicht klar, was Du mit den Maps willst.


----------



## Bajra (14. Feb 2021)

mihe7 hat gesagt.:


> Kann ein und dasselbe Peptide/Acccession in mehreren Gruppen auftauchen?


Nein, keine von beiden kann es doppelt vorkommen in einer Grouppe!


----------



## mihe7 (14. Feb 2021)

Ich meinte nicht in einer Gruppe, sondern über mehrere Gruppen hinweg. 

Beispiel: eine Rechnungsposition gehört zu einer Rechnung und kann nur in dieser einen Rechnung auftauchen.
Tabellen: Rechnung (ID, ...) und Rechnungsposition (Rechnung_ID, Positionsnr, ...) - typische 1:n-Beziehung

Gegenbeispiel: es gibt Kochrezepte mit der Zutat "Sahne". Die Sahne kann aber in mehreren Kochrezepten auftauchen. 
Tabellen: Rezept (ID, ...), Zutat (ID, Name) und Rezept_Zutat (Rezept_ID, Zutat_ID, Menge, ...)


----------



## Bajra (14. Feb 2021)

mihe7 hat gesagt.:


> OK, wenn ich es richtig verstehe, dann hätte ich mal drei Tabellen für Grupe, Peptide und Accession:
> 
> Gruppe: ID, Name
> Peptide: ID, Name
> ...


Maps  waren in der Gruppe Klasse deklariert. Dafür sind dort Funktionen geschrieben. Idee dahinter war die Maps in eine andere Klasse zu schieben und in der Gruppe klasse durch eine Variable ersetzen. Diese Maps sollen jetzt in der Datenbank gespeichert. die return Methode soll gleich aussehen wir in der Gruppe klasse. Aber die Daten sollen von der Datenbanke aufgerufen. Die wollte ich in den Map einfügen und zurückgeben in der Gruppe Klasse.


----------



## mihe7 (14. Feb 2021)

Aus Sicht der Gruppe sind das doch aber nur Listen von Peptide/Accession-Objekten.


----------



## Bajra (14. Feb 2021)

mihe7 hat gesagt.:


> Aus Sicht der Gruppe sind das doch aber nur Listen von Peptide/Accession-Objekten.


Ja genau, die werde dann nur nach der ID referenziert. Das XML-Ausgabe oben kann dir helfen. Da sind nur die ids von Peptide und accession aufgelistet.


----------



## mihe7 (14. Feb 2021)

Gut, wenn ich nach den Daten des XML gehe, dann brauchst Du ja nur:

Gruppe: ID, Name
Peptide: ID, Gruppe_ID, Name
Accession: ID, Gruppe_ID, Name

Gruppe enthält dann zwei Listen für Peptide und Accession. Beim Speichern können zuerst alle Peptide (Accessions) der Gruppe gelöscht und dann neu eingefügt werden.


----------



## Bajra (16. Feb 2021)

Hallo, ich bin nochmal und jetzt habe ein Problem mit der Rekursion. Dabei wird keine Abbruchbedingung stattfinden und sobald die dem Wert hat, geht zu Endlosschleife und verursacht somit eine Error "StackOverflowError". 

ich wollte eine if bauen und sagen, gehe nur ein mal da rein und ruf sich nur ein mal die Methoden auf. Oder geht es auch anderes? 

Ich hole die Daten von getChildren(). aus der Datenbank. Die taucht da auf und hören es nicht mehr auf  



```
public Map<Long, Group> getAllPeptideChildren(){
      
      //zwei Map Variablen
        Map<Long, Group> allChildren = new HashMap<>();
        Map<Long, Group> childChildren;
        
        for (Map.Entry<Long, Group> cIt :getChildren().entrySet()) {
            
                        // sobald er hier hereingeht, wiederholt sich unendlich.
                       // aber es geht nicht unten zu der for schleifen
            childChildren = cIt.getValue().getAllPeptideChildren();

                    
            for (Map.Entry<Long, Group> ccIt : childChildren.entrySet()) {
                allChildren.put(ccIt.getKey(), ccIt.getValue());
            }

            if ((cIt.getValue().getPeptides() != null) && (cIt.getValue().getPeptides().size() > 0)) {
                allChildren.put(cIt.getKey(), cIt.getValue());
            }
        }

        return allChildren;
    }
```


----------

