jdbc代码中的错误 - > com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:SQL语法中有错误

时间:2018-03-10 13:58:26

标签: java jdbc

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:您的SQL语法中有错误;查看与您的MySQL服务器版本对应的手册,以便在' @ gmail.com'附近使用正确的语法。在第1行

我不知道问题在哪里

public List<UserModel> listUser(String emailParam) throws SQLException {
    List<UserModel> users = new ArrayList<>();

    Connection conn = null;
    PreparedStatement pre = null;
    ResultSet rs = null;

    // Get Connection
    conn = dataSource.getConnection();

    // fetch query
    String fetchUser = "SELECT * FROM user WHERE email = " + emailParam;
    pre = conn.prepareStatement(fetchUser);

    // execute query
    rs = pre.executeQuery();

    // fetch data using resultSet interface;
    while (rs.next()) {
        Integer id = rs.getInt("id");
        String firstName = rs.getString("firstName");
              ...
        String email = rs.getString("email");
        Boolean isActive = rs.getBoolean("isActive");
        Boolean isLibrarian = rs.getBoolean("isLibrarian");

        // insert into user constructor
        UserModel theUser = new UserModel(id, firstName, lastName, gender,
                department, idNo, contactNo, address, email, null,
                isLibrarian, isActive);

        // insert into ArrayList
        users.add(theUser);
    }

    // close connection
    close(conn, pre, rs);

    return users;
}

问题在哪里提前谢谢。

2 个答案:

答案 0 :(得分:2)

错误发生在AssertionError: 16 columns passed, passed data had 18 columns

listUser()

您在插入用户时设法使用预准备语句,并且在查询时需要执行相同的操作:

    // fetch query
    String fetchUser = "SELECT * FROM user WHERE email = " + emailParam;
    pre = conn.prepareStatement(fetchUser);

答案 1 :(得分:2)

总的来说,准备陈述有两个主要用法: 1)最小化执行查询时的准备时间 2)为了安全 - 除其他外“查询重写”

我还对本文底部的选择中的语法错误进行了观察。

如果您要准备语句,那么最好先做一次,然后“记住”您获得的preparedStatement。不要一遍又一遍地准备相同的查询。

对于准备好的查询处理,大多数(如果不是全部)DBMS的工作如下: 1)将模板查询发送到DBMS进行解析和优化。这个的输出可以通过几个不同的名称来识别,但出于此目的,我们可以将其称为“可执行计划”。这是PrepareXXX电话。 2)DBMS会记住第二阶段的所有细节,即当您通过prepdQuery.executeQuery()(或类似)调用发送数据时。这具有发送数据并将其插入准备好的查询的可执行计划的效果。

这将始终涉及两次网络旅行(一次准备,一次执行)。但是....

...如果您需要使用不同的数据(例如,不同的电子邮件)再次运行相同的查询,只需执行第二步 - 这将绕过与解析和计划相关的开销。这将显着提高您的吞吐量 - 特别是对于单行操作,例如上面显示的插入(很可能是选择)。

替代方法是字符串连接方法,它总是需要解析等和执行 - 但至少它只能通过网络进行一次。这适用于运行时间较长的查询(解析时间与执行时间相比无关紧要)或查询逻辑是动态的(根据用户输入在运行时组成)。

但是,如果您确实发送了与用户输入连接的查询文本,请确保解决上面的第2点(查询重写)。

此外,最后,您的连锁SQL缺少单引号。 查询必须如下所示(必须引用文本) select ... from ... where email ='email@domain.com';

因此,您的连接必须如下所示: String fetchUser =“SELECT * FROM user WHERE email ='”+ emailParam +“'”;

什么是查询重写?如果用户输入的emailParam看起来像这样: emailParam =“';从用户全部删除;选择'你好' 尝试将其插入您的选择但不要运行它,除非您有用户表的备份副本(或者您很幸运)。 另外,请注意,你从不在周围放置引号?准备好的查询中的占位符 - 即使参数是文本或日期值。