2016-03-29 4 views
0

Derzeit arbeite ich in Spring Boot mit Postgres JDBC-Treiber und ich habe eine Verbindung mit meiner Datenbank. Wenn ich jedoch das erste Mal versuche einzufügen, erhalte ich keine Fehler, aber auf der DB-Seite sehe ich keine Einfügung. Beim zweiten Versuch erhalte ich den folgenden Fehler:Postgres kein Fehler und keine Einfügung

Cannot get out of auto-commit mode with error: org.postgresql.util.PSQLException: This connection has been closed. 
SQLException: org.postgresql.util.PSQLException: This connection has been closed. 

Bei beiden Versuchen kann ich nicht einfügen. Mein Debugger sagt mir, dass ich folgendes geschickt haben:

preparedStatement: INSERT INTO event (StartTime, EndTime, Description, name, DisplayPicLoc, attendenceCount) VALUES ('2016-2-29 19:0:0.000000 -5:0:0','2016-3-1 19:0:0.000000 -5:0:0','b','b',NULL,0) 

Das Datenbankschema I eingerichtet haben, ist dies:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; 

CREATE TABLE event (eventID UUID DEFAULT uuid_generate_v4() NOT NULL primary key, 
        StartTime timestamp NOT NULL, 
        EndTime timestamp NOT NULL, 
        Description varchar(1500), 
        name varchar(80) NOT NULL, 
        DisplayPicLoc varchar(80), 
        attendenceCount int); 

wie Meine Java-Server-Side-Code aussieht:

@Controller 
public class CalendarController { 
    @RequestMapping(value="/event", method=RequestMethod.POST) 
    public @ResponseBody 
    String uploadEvent(@RequestParam("title") String title, 
         @RequestParam("description") String description, 
         @RequestParam("start") Date start, 
         @RequestParam("end") Date end){ 

    Timestamp startTime = null; 
    Timestamp endTime = null; 

    try{ 
     startTime = new Timestamp(start.getTime()); 
     endTime = new Timestamp(end.getTime()); 
    } 
    catch(Exception e){ 
     System.err.print("Date conversion error: " + e); 
     return "failure"; 
    } 

    System.out.println("Event received with Title: " + title + 
      " Description: " + description + 
      " Start: " + startTime + 
      " End: " + endTime); 

    Savepoint savepoint = null; 
    Connection connection = DatabaseConnection.connection; 
    try{ 
     connection.setAutoCommit(false); 
    } 
    catch(SQLException e){ 
     System.err.println("Cannot get out of auto-commit mode with error: " + e); 
    } 
    if(connection==null){ 
     new DatabaseConnection(); 
    } 
    try{ 
     savepoint = connection.setSavepoint(); 
     String query = "INSERT INTO event " + 
       "(StartTime, EndTime, Description, name, DisplayPicLoc, attendenceCount) " + 
       "VALUES (?,?,?,?,?,?);"; 
     PreparedStatement preparedStatement = connection.prepareStatement(query); 
     preparedStatement.setTimestamp(1, startTime); 
     preparedStatement.setTimestamp(2, endTime); 
     preparedStatement.setString(3, description); 
     preparedStatement.setString(4, title); 
     preparedStatement.setString(5, null); 
     preparedStatement.setInt(6, 0); 

     System.out.println("preparedStatement: " + preparedStatement); 

     preparedStatement.executeUpdate(); 
     //connection.close(); 
     return "success"; 
    } 
    catch(SQLException e){ 
     System.err.println("SQLException: " + e); 
     if(connection!=null && savepoint!=null){ 
      try{ 
       connection.rollback(savepoint); 
      } 
      catch(SQLException error){ 
       System.err.println("SQLException: " + error); 
      } 
     } 
    } 
    finally{ 
     if(connection != null) { 
      try { 
       connection.close(); 
      } 
      catch(SQLException e) { 
       System.err.println("SQLException: " + e); 
      } 
     } 
    } 
    return "failure"; 
} 

}

Wo bin ich falsch gelaufen?

+1

Es gibt keine 'commit() 'in Ihrem Code –

+0

Könnten Sie uns einen Code der' DatabaseConnection' Klasse zeigen, vor allem wie 'DatabaseConnection.connection;' deklariert und initialisiert wird? Es sieht wie eine statische Variable aus, die zwischen verschiedenen Threads geteilt wird. Warum verwendest du keinen Verbindungspool? – krokodilko

+0

@a_horse_with_no_name Wo sollte ich das commit() setzen? Ich habe online nachgesehen, aber ich bin mir nicht sicher, ob ich das verstehe. – Bob

Antwort

0

Mein Adice ist die Verwendung eines Verbindungspools anstelle einer einzelnen Verbindung, die statisch von allen Klassen und Threads geteilt wird.
Ich werde nicht auf Details eingehen, wie ein Verbindungspool funktioniert und wie er in Ihrem Projekt konfiguriert wird. Es gibt viele hervorragende Antworten und Tutorials auf SO und im Internet.
Sie können von hier aus starten: https://en.wikipedia.org/wiki/Connection_pool
und hier:
Creating a database connection pool
how to do connection pooling in java?
How to establish a connection pool in JDBC?

PostgreSQL-Treiber verfügt über eine eigene Implementierung der Verbindung Umfrage ist, benutzen Sie bitte diesen Link für weitere Details studieren: http://www.postgresql.org/docs/7.4/static/jdbc-datasource.html
I Erraten Sie, dass Ihre Anwendung in einem Container läuft (Tomcat? JBoss? etc). Wenn ja, dann haben fast alle Webcontainer ihre eigene Verbindungspool-Implementierung
Wenn n, dann können Sie Apache DBCP oder c3p0:JDBC Bibliotheken verwenden.


Kurz gesagt - der Verbindungspool erheblich vereinfacht alle Aufgaben im Zusammenhang mit der Erstellung und Datenbankverbindungen zu schließen.In allen Orten, an denen Sie eine Verbindung benötigen, ist ein Muster, das gleiche:

  • eine Verbindung aus dem Pool (Datasource) erhalten
  • wiederum autocommit ein- oder ausgeschaltet (abhängig von Bedürfnissen)
  • eine Datenbankoperation tun (einfügen, aktualisieren wählen - was auch immer)
  • tun ein commit (nur wenn autocommit ausgeschaltet wurde)
  • schließen resuorces
  • schließen die Verbindung (senden sie es an den Pool)

Wenn Sie Java 7 verwenden, können Sie versuchen-mit-Ressourcen Code weiter zu vereinfachen (Anschluss und vorbereitete Anweisung automatisch geschlossen sind):
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

String query = "INSERT INTO event " + 
       "(StartTime, EndTime, Description, name, DisplayPicLoc, attendenceCount) " + 
       "VALUES (?,?,?,?,?,?);"; 
try(Connection conn = DataSource.getConnection(); 
    PreparedStatement ps = conn.prepareStatement(query)){ 
     ps.setTimestamp(1, startTime); 
     .... 
     .... 
     ps.setInt(6, 0); 
     ps.executeUpdate(); 
     return true; // success 
} catch(SQLException e){ 
    System.err.println("SQLException: " + e); 
    return false; // failure 
} 
Verwandte Themen