2013-09-30 11 views
6

Ich versuche Spring's JdbcTemplate Klasse zu verwenden, um eine Zeile in eine MySQL-Tabelle mit dem Namen transaction einzufügen und die generierte ID zu erhalten. Der entsprechende Code ist:Zeile einfügen und generierte ID

public Transaction insertTransaction(final Transaction tran) { 

    // Will hold the ID of the row created by the insert 
    KeyHolder keyHolder = new GeneratedKeyHolder(); 

    getJdbcTemplate().update(new PreparedStatementCreator() { 
     public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { 

      PreparedStatement ps = connection.prepareStatement(INSERT_TRAN_SQL); 
      ps.setString(1, tran.getTransactionType().toString()); 

      Date sqlDate = new Date(tran.getDate().getTime()); 
      ps.setDate(2, sqlDate); 
      ps.setString(3, tran.getDescription()); 

      return ps; 
     } 
    }, keyHolder); 

    tran.setId(keyHolder.getKey().longValue()); 
    return tran; 
} 

Aber die folgende Ausnahme wird durch den Aufruf geworfen getJdbcTemplate().update

java.sql.SQLException: Generierte Schlüssel angefordert nicht. Sie müssen Statement.RETURN_GENERATED_KEYS zu Statement.executeUpdate() oder Connection.prepareStatement() angeben.

Kann ich die Zeile einfügen und die generierte ID erhalten, ohne JdbcTemplate zu verlassen? Ich verwende Spring 2.5, MySQL 5.5.27 und MySQL Connector 5.1.26.

+0

Mit MySQL Ich glaube, Sie anrufen müssen 'LAST_INSERT_ID()'. Siehe [hier] (http://stackoverflow.com/questions/7501464/how-to-get-the-id-of-inserted-row-in-mysql). –

Antwort

7

Bereiten Sie einfach Ihre Statement als

PreparedStatement ps = connection.prepareStatement(
          INSERT_TRAN_SQL, Statement.RETURN_GENERATED_KEYS); 

Die zugrunde liegende JDBC-Treiber (verwendet indirekt über die Spring JdbcTemplate hier) erfordert einen Hinweis, dass Sie möchten, folgt den erzeugten Schlüssel abzurufen. Dies kann entweder geschehen, während ein PreparedStatement als

connection.prepareStatement(strSQL, Statement.RETURN_GENERATED_KEYS); 

oder zum Zeitpunkt der Ausführung an, wie gut ein Statement als

statement.executeUpdate(strSQL, Statement.RETURN_GENERATED_KEYS); 

Dies ist, was Ihre java.sql.SQLException zeigen vorbereitet.

+1

Hallo, nur eine Frage, wenn die Abfrage erfolgreich ist, gibt es die generierte ID zurück, aber was gibt es zurück, wenn die Abfrage nicht ausgeführt werden kann, damit ich den Fehler in meinem Code korrekt behandeln könnte? –

9

Es ist ein einfacher Weg, um dieses Verhalten zu erhalten:

protected JdbcTemplate   jdbcTemplate; 
private SimpleJdbcInsert   insert; 

    this.jdbcTemplate = new JdbcTemplate(this.databaseSetup.getDataSource()); 
    this.insert = new SimpleJdbcInsert(this.jdbcTemplate).withTableName(this.tableName).usingGeneratedKeyColumns(this.pkColumn); 

Dann erstellen Sie eine Karte namens Parameter, die die Werte für die einzelnen Spaltennamen in der Tabelle conmtains und legen Sie einen Datensatz wie folgt aus:

final Map<String, Object> parameters = new HashMap<>(); 
    parameters.put("empName", employee.getName()); // store the String name of employee in the column empName 
    parameters.put("dept", employee.getDepartment()); // store the int (as Integer) of the employee in the column dept 
    final Number key = this.insert.executeAndReturnKey(parameters); 
    final long pk = key.longValue(); 
+0

Wäre toll, wenn Sie in Ihrer Antwort ein Beispiel für die zugeordneten Werte angeben würden. Aus der aktuellen Antwort ist es nicht offensichtlich, eine Map zu verwenden, ohne weiter in die externe Dokumentation und was durch Key und Value dargestellt wird. Dies würde eine Verbesserung verdienen, wenn diese Informationen verfügbar wären. – Hazok

+0

Ich dachte, es wäre ziemlich offensichtlich, dass, wenn ich eine Map-Parameter mit Werten für jede Spalte Namen, wie ich erwähnt Spaltenname hätte es offensichtlich sein sollte, dass die Schlüssel sind Strings und Werte als unbestimmt kann jede Objekt Zuordnung zu einem SQL-Typ sein.Übrigens: Es tut nie weh, die Dokumentation zu überprüfen, niemals einer bestimmten Antwort zu vertrauen und sie nicht doppelt zu überprüfen. – GerritCap

+0

Das ist offensichtlich, Dokumentation zu überprüfen und einer bestimmten Antwort nicht zu vertrauen. Es ist auch offensichtlich, dass eine gute Frage zu Stackoverflow alle notwendigen Details enthält und nichts Ungewissheit übrig lässt. Es ist auch offensichtlich, dass jemand, der den Java-JDBC-Stack für den ersten verwendet, diese Art von Dingen nicht als offensichtlich erkennen wird;) – Hazok

0

Sie können die nächste Sequenznummer wie in Schritt 1, es abrufen dann 2 in der Insert-Anweisung wie im Schritt geführt werden:

1-

Integer nextSeq = (Integer) getJdbcTemplate().queryForObject(
     "select SEQ_CUSTOMER_ID.nextVal from dual", new Object[] {}, Integer.class); 

2-

getJdbcTemplate().update(
     "INSERT INTO customer " 
     + "(CUST_ID, NAME, UPDATED) VALUES (?, ?, ?)", 
     new Object[] { nextSeq ,customer.getName(), 
       customer.getUpdated() }); 
Verwandte Themen