MySQL Neuen Datensatz mit "new" anlegen

Dimadon

Aktives Mitglied
Hallo Leute,

ich bin ganz frisch hier und würde mich wirklich sehr freuen wenn der ein oder andere mir bei meinem Problem behilflich sein könnte.
Ich schreibe derzeit an einem kleinen Pinnwand_Programm. Hierzu habe ich eine locale Datenbankanbindung geschrieben und eine Mapperklasse die nach der Fertigstellung des Programms mit der Datenbank sprechen soll. Mit der Insert Methode hat alles wunderbar funktioniert nur möchte ich nun wissen ob meine MappeKlasse funktioniert. Hierzu habe eine kleine Testklasse(TestCon) angelegt die nun mit new einen neuen User anlegen soll. Sprich über diese Klasse zum Mapper der sich die Datenbankanbindung holt und schließlich den Datensatz in den Datenbank einbindet.

Hier der Code:
Java:
public class TestCon {
	
	public static void main(String[] args){
	
		User a = new User();
		a.setVorname("Jens");
		a.setNachname("Merkel");
		a.setNickname("merkelj");
		UserMapper.userMapper().insert(a);
	}
          }

Java:
public class UserMapper {

	private static UserMapper userMapper = null;

  
  protected UserMapper() {
  }


  public static UserMapper userMapper() {
    if (userMapper == null) {
      userMapper = new UserMapper();
    }

  return userMapper;
  }

 
  public User
  	findByKey(int Uid) {
    // DB-Verbindung holen
    Connection con = LocalDBConnection.connection();

    try {
//      Leeres SQL-Statement (JDBC) anlegen
      Statement stmt = con.createStatement();

      // Statement ausfüllen und als Query an die DB schicken
      ResultSet rs = stmt
          .executeQuery("SELECT Uid, vorname, nachname, nichkname FROM users "
              + "WHERE Uid=" + Uid + " ORDER BY lastName");

      /*
       * Da id Primärschlüssel ist, kann max. nur ein Tupel zurückgegeben
       * werden. Prüfe, ob ein Ergebnis vorliegt.
       */
      if (rs.next()) {
        // Ergebnis-Tupel in Objekt umwandeln
        User c = new User();
        c.setUid(rs.getInt("Uid"));
        c.setVorname(rs.getString("vorname"));
        c.setNachname(rs.getString("nachname"));
        c.setNickname(rs.getString("nickname"));

        return c;
      }
    }
    catch (SQLException e) {
      e.printStackTrace();
      return null;
    }

    return null;
  }

  /**
   * Auslesen aller Kunden.
   * 
   * @return Ein Vektor mit Customer-Objekten, die sämtliche Kunden
   *         repräsentieren. Bei evtl. Exceptions wird ein partiell gef�llter
   *         oder ggf. auch leerer Vetor zurückgeliefert.
   */
  public Vector<User> findAll() {
    Connection con = LocalDBConnection.connection();
    // Ergebnisvektor vorbereiten
    Vector<User> result = new Vector<User>();

    try {
      Statement stmt = con.createStatement();

      ResultSet rs = stmt.executeQuery("SELECT Uid, vorname, nachname, nickname "
          + "FROM users " + "ORDER BY lastName");

      // Für jeden Eintrag im Suchergebnis wird nun ein Customer-Objekt
      // erstellt.
      while (rs.next()) {
        User c = new User();
        c.setUid(rs.getInt("Uid"));
        c.setVorname(rs.getString("vorname"));
        c.setNachname(rs.getString("nachname"));
        c.setNickname(rs.getString("nickanme"));

        // Hinzufügen des neuen Objekts zum Ergebnisvektor
        result.addElement(c);
      }
    }
    catch (SQLException e) {
      e.printStackTrace();
    }

    // Ergebnisvektor zurückgeben
    return result;
  }

  /**
   * Auslesen aller Kunden-Objekte mit gegebenem Nachnamen
   * 
   * @param name Nachname der Kunden, die ausgegeben werden sollen
   * @return Ein Vektor mit Customer-Objekten, die sämtliche Kunden mit dem
   *         gesuchten Nachnamen repräsentieren. Bei evtl. Exceptions wird ein
   *         partiell gefüllter oder ggf. auch leerer Vetor zurückgeliefert.
   */
  public Vector<User> findByNachname(String name) {
    Connection con = LocalDBConnection.connection();
    Vector<User> result = new Vector<User>();

    try {
      Statement stmt = con.createStatement();

      ResultSet rs = stmt.executeQuery("SELECT Uid, vorname, nachname, nickname "
              + "FROM users " + "ORDER BY lastName");


      // Für jeden Eintrag im Suchergebnis wird nun ein Customer-Objekt
      // erstellt.
      while (rs.next()) {
        User c = new User();
        c.setUid(rs.getInt("Uid"));
        c.setVorname(rs.getString("firstName"));
        c.setNachname(rs.getString("lastName"));

        // Hinzufügen des neuen Objekts zum Ergebnisvektor
        result.addElement(c);
      }
    }
    catch (SQLException e) {
      e.printStackTrace();
    }

    // Ergebnisvektor zurückgeben
    return result;
  }

  /**
   * Einfügen eines <code>Customer</code>-Objekts in die Datenbank. Dabei wird
   * auch der Primärschlüssel des übergebenen Objekts geprüft und ggf.
   * berichtigt.
   * 
   * @param c das zu speichernde Objekt
   * @return das bereits übergebene Objekt, jedoch mit ggf. korrigierter
   *         <code>id</code>.
   */
  public User insert(User c) {
    Connection con = LocalDBConnection.connection();
    

    try {
      Statement stmt = con.createStatement();

      /*
       * Zunächst schauen wir nach, welches der momentan höchste
       * Primärschlüsselwert ist.
       */
      ResultSet rs = stmt.executeQuery("SELECT MAX(Uid) AS maxid "
          + "FROM users ");

      // Wenn wir etwas zurückerhalten, kann dies nur einzeilig sein
      if (rs.next()) {
        /*
         * c erhält den bisher maximalen, nun um 1 inkrementierten
         * Primärschlüssel.
         */
        c.setUid(rs.getInt("maxid") + 1);

        stmt = con.createStatement();

        // Jetzt erst erfolgt die tatsächliche Einfügeoperation
        stmt.executeUpdate("INSERT INTO users (Uid, vorname, nachname, nickname) "
            + "VALUES (" + c.getUid() + ",'" + c.getVorname() + "','"
            + c.getNachname() +  ",'" + c.getNickname() +"')");
      }
    }
    catch (SQLException e) {
      e.printStackTrace();
    }

    /*
     * Rückgabe, des evtl. korrigierten Customers.
     * 
     * HINWEIS: Da in Java nur Referenzen auf Objekte und keine physischen
     * Objekte übergeben werden, wäre die Anpassung des Customer-Objekts auch
     * ohne diese explizite Rückgabe au�erhalb dieser Methode sichtbar. Die
     * explizite Rückgabe von c ist eher ein Stilmittel, um zu signalisieren,
     * dass sich das Objekt evtl. im Laufe der Methode verändert hat.
     */
    return c;
  }

  /**
   * Wiederholtes Schreiben eines Objekts in die Datenbank.
   * 
   * @param c das Objekt, das in die DB geschrieben werden soll
   * @return das als Parameter übergebene Objekt
   */
  public User update(User c) {
    Connection con = LocalDBConnection.connection();

    try {
      Statement stmt = con.createStatement();

      stmt.executeUpdate("UPDATE users " + "SET vorname=\""
          + c.getVorname() + "\", " + "nachname=\"" + c.getNachname() + "\" , " + "nickname=\"" + c.getNickname() + "\" "
          + "WHERE Uid=" + c.getUid());

    }
    catch (SQLException e) {
      e.printStackTrace();
    }

    // Um Analogie zu insert(Customer c) zu wahren, geben wir c zurück
    return c;
  }

  /**
   * Löschen der Daten eines <code>Customer</code>-Objekts aus der Datenbank.
   * 
   * @param c das aus der DB zu löschende "Objekt"
   */
  public void delete(User c) {
    Connection con = LocalDBConnection.connection();

    try {
      Statement stmt = con.createStatement();

      stmt.executeUpdate("DELETE FROM users " + "WHERE Uid=" + c.getUid());
    }
    catch (SQLException e) {
      e.printStackTrace();
    }
  }

Java:
public class LocalDBConnection {
	 
	private static Connection con = null;

	public static Connection connection() {
		
		
		// Wenn es bisher keine Conncetion zur DB gab, ... 
		
			try {
				
				Class.forName("com.mysql.jdbc.Driver").newInstance();
				
				Connection con = DriverManager.getConnection(
						"jdbc:mysql://localhost/socialmediapinnwand","","");
				con.setReadOnly(false);
				con.close();
			}
		

			catch(Exception e){
			
				System.out.println("*****FEHLER*****->" +e);
			}

		
		// Zurückgegeben der Verbindung
		return con;
		
	}

Es wäre echt super wenn mir hier jemand weiterhelfen kann.
 
Danke für das rasche Feedback. Das Problem ist das ich bei der Ausführung immer eine NullPointerException bekomme und die Daten nicht eingetragen werden. Ich weiß leider nicht woran es liegt. Mir ist bekannt was der NullPointerException ist aber was ich hierbei falsch gemacht habe ist mir leider nicht klar....

Edit: Den NullPointerException erhalten ich für:

Java:
UserMapper.userMapper().insert(a);

und

Java:
      Statement stmt = con.createStatement();
 
Zuletzt bearbeitet:
Per Consolenausgabe erhalte ich folgenden Bericht:

Exception in thread "main" java.lang.NullPointerException
at de.hdm.socialmediapinnwand.server.UserMapper.insert(UserMapper.java:148)
at de.hdm.socialmediapinnwand.server.TestCon.main(TestCon.java:9)
 
Zuletzt bearbeitet:
Also deine Connection ist null, das ist dein Problem.
Das Verbinden funktioniert, sonst würde es den "FEHLER" schmeissen.

Dein Problem ist, dass du die connection gleich wieder schließt bevor du sie zurückgibst.

con.close(); erst aufrufen wenn du die Verbindung schließen möchtest,
also keine Daten mehr lesen oder anlegen.

Deshalb sagts dir auch null-pointer, weil con.close() die connection wohl
auf null setzt danach.
 
Ok...Dank dir schonmal...Und wie kann ich das beheben? Habe mal versucht die close nach der Rückgabe zu setzen, jedoch ohne Erfolg. Die Fehlermeldung bleibt leider 🙁
 
Close garnicht aufrufen xDD

Erst wenn du dein Programm schließt, oder wenn du nur diesen einen Testaufruf
machst, dann nach dem Adden eines neuen Accounts.
 
Leider ohne Erfolg...Auch wenn ich die con.close() komplett weglasse erhalte ich die Exception in thread "main" java.lang.NullPointerException....
 
Neben den richtigen Antworten, ist mir noch ein weiterer grober Schnitzer aufgefallen.

Dieses nennen wir Check-then-act Problem und bedeutet, das du etwas prüfst, hier die maximale ID in der DB, und darauf eine Entscheidung aufbaust (hier Einfügen eines Datensatzes).

Aber natürlich kann in der Zeit zwischen Lesen der maximalen ID und der weiteren Ausführung jemand anderes bereits einen Datensatz eingefügt haben und wenn du das versuchst, knallt die DB mit einem Fehler, weil die ID doch nicht so eindeutig war.

Daher ist es angebrachter diese Arbeit die DB machen zu lassen. In praktisch allen DB gibt es eine Möglichkeit eine ID automatisch inkrementieren zu lassen. In mySQL nennt sich das dann AUTO_INCREMENT, in anderen Sequenz,...

Desweiteren gebe ich den Ratschlag, besser Prepared-Statements zu nutzen und NICHT per String-Bastelei einen SQL-Befehl zusammen zubauen.
Dein Ansatz ist anfällig gegen sogenannte SQL-Injection Angriffe und dieses ist ein schwerwiegendes Problem, welches einfach durch Prepared-Statements verhindert werden kann.

Dein NPE-Problem rührt anscheinend daher, das du die Connection nicht richtig verwaltest. Dieses ist oft der Fall, zumal man eigentlich "gepoolte" Connections verwendet. Das sollte ein Framework, was du statt "plain" JDBC nehmen solltest, bereits anbieten.
 
Ok hab dein Fehler jetzt gefunden.

Schau dir nochmal genau an welche Connection du zurückgibst.

Als Tip:

beachte den Unterschied zwischen lokaler und Klassenvariable.

return this.con != return con in deinem Fall.

Du hast zwei verschieden con Objekte, da du einmal als
Instanz und einmal als Methodenvariable die Connection con
initialisierst.

Wahrscheinlich ein übersehener Leichtsinnsfehler xD
(Deshalb hab ichs auch jetzt erst bemerkt)
 
@ turtle: Danke für den Hinweiß bezüglicher des Fehlers. Auto_Inkrement habe ich mir bereits überlegt einzubauen. Aber ich habe hier nicht so weit gedacht wie du 🙂 Macht aber sicher Sinn.

Dein Hinweiß zu meinem Fehler kann ich leider nicht ganz nachvollziehen. Worin liegt genau mein Fehler jetzt? Im Aufbau der Anbindung oder etwa wo anders?
 
Hier
Java:
    public class LocalDBConnection {
         
        private static Connection con = null;
     
        public static Connection connection() {
           
           
            // Wenn es bisher keine Conncetion zur DB gab, ...
           
                try {
                   
                    Class.forName("com.mysql.jdbc.Driver").newInstance();
                   
                    Connection con = DriverManager.getConnection(
                            "jdbc:mysql://localhost/socialmediapinnwand","","");
                    con.setReadOnly(false);
                    con.close();
                }
           
     
                catch(Exception e){
               
                    System.out.println("*****FEHLER*****->" +e);
                }
     
           
            // Zurückgegeben der Verbindung
            return con;
           
        }

Diese Zeile:
Java:
        Connection con = DriverManager.getConnection(
                            "jdbc:mysql://localhost/socialmediapinnwand","","");

Da darf Connection natürlich nicht nochmal stehen, sondern nur
Java:
con = DriverManager.getConnection(
                            "jdbc:mysql://localhost/socialmediapinnwand","","");

Sonst bleibt dein eigentliches con objekt null wie oben zu Anfangs zugewiesen.
 
Super dank dir.....Ist ja auch logisch wenn man es sieht 🙂 OH man.... Jetzt läuft der Fehler nicht mehr...

Jedoch erhalte ich keinen Eintrag in der Datenbank... und diese Fehlermeldung 🙁

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'merkelj)' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.Util.getInstance(Util.java:384)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4232)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4164)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2832)
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1755)
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1679)
at de.hdm.socialmediapinnwand.server.UserMapper.insert(UserMapper.java:182)
at de.hdm.socialmediapinnwand.server.TestCon.main(TestCon.java:21)
 
Zuletzt bearbeitet:
Die Meldung ist doch jetzt logisch 😀

Du hast wohl noch ein Fehler in deiner SQL Syntax.

Das hängt jetzt davon ab was das für eine Datenbank ist und wie deine
Daten aussehen.

Probier am besten vorher deine SQL Statements direkt in der Datenbank
mit Selektionsskripten aus, und bau sie dann erst in dein programm aus wenn
du weißt dass sie stimmen.
 
Ok Fehler gefunden....Nun noch eine Fragen: Es wird zwar ein Datensatz eingepflegt jedoch ohne Inhalt..Muss ich den Vor- bzw. Nachnamen anders deklarieren?

Update: Fehler gefunden: Hatte '...' vergessen....

Ich danke euch sehr bei der Hilfe...Tolles Forum, tolle Leute:applaus:
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben