Postgres没有错误,没有插入

时间:2016-03-29 08:31:04

标签: spring postgresql jdbc spring-boot

目前,我正在使用postgres jdbc驱动程序进行Spring启动,并且我与数据库建立了连接。但是,我第一次尝试插入时,没有收到错误,但在DB端,我看不到插入。在第二次尝试时,我收到以下错误:

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.

在两次尝试中,我都无法插入。我的调试器告诉我,我发送了以下内容:

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)

我设置的数据库架构是:

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);

我的java服务器端代码如下所示:

@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";
}

}

我哪里出错?

1 个答案:

答案 0 :(得分:0)

我的忠告是使用连接池而不是在所有类和线程之间静态共享的单个连接 我不打算详细介绍连接池的工作原理以及如何在项目中配置它。在SO和互联网上有很多优秀的答案和教程 你可以从这里开始:https://en.wikipedia.org/wiki/Connection_pool
在这里:
Creating a database connection pool
how to do connection pooling in java?
How to establish a connection pool in JDBC?

PostgreSQL驱动程序有自己的连接调查实现,请详细研究此链接:http://www.postgresql.org/docs/7.4/static/jdbc-datasource.html 我想你的应用程序是在某个容器中运行的(Tomcat?JBoss?等)。如果是,则几乎所有Web容器都有自己的连接池实现
如果是n,那么您可以使用Apache DBCPc3p0:JDBC个库。

简而言之 - 连接池大大简化了与创建和关闭数据库连接相关的所有任务。在您需要连接的所有地方,模式都是相同的:

  • 从池中获取连接(DataSource)
  • 打开或关闭自动提交(根据需要)
  • 做一些数据库操作(插入,更新,选择 - 无论如何)
  • 执行提交(仅在关闭自动提交时)
  • close resuorces
  • 关闭连接(将其返回池中)

如果您使用的是Java 7,则可以使用try-with-resources进一步简化代码(连接和预处理语句会自动关闭):
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
}