如何使用 Spring 4 MVC PathVariable 参数查询数据库

How to query a database using Spring 4 MVC PathVariable parameter

要解决的问题: 我正在尝试根据 @RequestMapping API 调用中给定的参数查询数据库。


我当前遇到错误的代码片段:

@RequestMapping(value ="/{serialNumber}", method = RequestMethod.GET)
    @ResponseBody
    public void searchByStudent(@PathVariable("serialNumber") String serialNumber) {
        SqlRowSet resultSet = this.jdbcTemplate.queryForRowSet("SELECT * FROM STORE_ITEMS WHERE SERIALNUMBER = :serialNumber");
        System.out.println(resultSet);
    }

这是我在通过 Postman(在浏览器中)访问 URL 时收到的 错误:

HTTP Status 500 - Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [SELECT * FROM STORE_ITEMS WHERE SERIALNUMBER = :serialNumber]; nested exception is java.sql.SQLSyntaxErrorException: [Vertica][VJDBC](4856) ERROR: Syntax error at or near ":"

type Exception report

message Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [SELECT * FROM STORE_ITEMS WHERE SERIALNUMBER = :serialNumber]; nested exception is java.sql.SQLSyntaxErrorException: [Vertica][VJDBC](4856) ERROR: Syntax error at or near ":"

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [SELECT * FROM STORE_ITEMS WHERE SERIALNUMBER = :serialNumber]; nested exception is java.sql.SQLSyntaxErrorException: [Vertica][VJDBC](4856) ERROR: Syntax error at or near ":"
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause

org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [SELECT * FROM STORE_ITEMS WHERE SERIALNUMBER = :serialNumber]; nested exception is java.sql.SQLSyntaxErrorException: [Vertica][VJDBC](4856) ERROR: Syntax error at or near ":"
    org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:91)
    org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
    org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
    org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:415)
    org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:470)
    org.springframework.jdbc.core.JdbcTemplate.queryForRowSet(JdbcTemplate.java:511)
    com.company.project.controller.DatabaseController.searchBySerialNumber(DatabaseController.java:64)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:497)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause

java.sql.SQLSyntaxErrorException: [Vertica][VJDBC](4856) ERROR: Syntax error at or near ":"
    com.vertica.util.ServerErrorData.buildException(Unknown Source)
    com.vertica.dataengine.VDataEngine.prepareImpl(Unknown Source)
    com.vertica.dataengine.VDataEngine.prepare(Unknown Source)
    com.vertica.dataengine.VDataEngine.prepare(Unknown Source)
    com.vertica.jdbc.common.SStatement.executeNoParams(Unknown Source)
    com.vertica.jdbc.common.SStatement.executeQuery(Unknown Source)
    org.springframework.jdbc.core.JdbcTemplateQueryStatementCallback.doInStatement(JdbcTemplate.java:454)
    org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:404)
    org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:470)
    org.springframework.jdbc.core.JdbcTemplate.queryForRowSet(JdbcTemplate.java:511)
    com.company.project.controller.DatabaseController.searchBySerialNumber(DatabaseController.java:64)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:497)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause

com.vertica.support.exceptions.SyntaxErrorException: [Vertica][VJDBC](4856) ERROR: Syntax error at or near ":"
    com.vertica.util.ServerErrorData.buildException(Unknown Source)
    com.vertica.dataengine.VDataEngine.prepareImpl(Unknown Source)
    com.vertica.dataengine.VDataEngine.prepare(Unknown Source)
    com.vertica.dataengine.VDataEngine.prepare(Unknown Source)
    com.vertica.jdbc.common.SStatement.executeNoParams(Unknown Source)
    com.vertica.jdbc.common.SStatement.executeQuery(Unknown Source)
    org.springframework.jdbc.core.JdbcTemplateQueryStatementCallback.doInStatement(JdbcTemplate.java:454)
    org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:404)
    org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:470)
    org.springframework.jdbc.core.JdbcTemplate.queryForRowSet(JdbcTemplate.java:511)
    com.company.project.controller.DatabaseController.searchBySerialNumber(DatabaseController.java:64)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:497)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.52 logs.

我的输出控制台出错:

INFO: SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana]

附加信息:

  • 正在使用的数据库:Vertica(根据输出控制台,我不确定这是否是问题所在)
  • 结果集将包含大约五位数的对象

问题:我该如何解决这个问题?我知道这不是最安全的查询方式,但我试图确保我的逻辑首先起作用。另外,是否有更好的方法使用 jdbcTemplate 进行查询?

您正在尝试调用创建简单 Statement 而非 PreparedStatement 的方法,但您正在尝试使用参数。

来自 javadoc

Execute a query for a SqlRowSet, given static SQL.

Uses a JDBC Statement, not a PreparedStatement. If you want to execute a static query with a PreparedStatement, use the overloaded queryForRowSet method with null as argument array.

我从来没有真正用过这种方式来查询数据库。正如您所说,这可能不是最安全的方式,更不用说最舒适的方式了。但是尝试使用重载的queryForRowSet方法

@RequestMapping(value ="/{serialNumber}", method = RequestMethod.GET)
@ResponseBody
public void searchByStudent(@PathVariable("serialNumber") String serialNumber) {
    SqlRowSet resultSet = this.jdbcTemplate.queryForRowSet("SELECT * FROM STORE_ITEMS WHERE SERIALNUMBER = ?", new Object[] {serialNumber});
    System.out.println(resultSet);
}