java操作mysql时执行带有日期语句的误区

最近在写服务器端的一些接口,在用java对mysql进行含有日期信息的查询的时候,遇到了一些问题,分享一下 。

首先把数据库中的一个用于用户签到的表的代码部分贴出来:

create table signUpInfo
(
phoneNum nvarchar(11) not null,      #手机号码
signTime timestamp not null,         #时间戳
foreign key(phoneNum) references usersInformation(phoneNum)     #外键,对于我这里主表就不贴了,大家测试可以删去这一句
);
      这句sql语句使用与创建用户签到的一张表,其中时间戳是用来记录当前的时间的,也就是当用户请求签到的时候,就把系统的当前时间和手机号插入到表中,作为用户的一项签到记录。

下面插入一条语句,带表用户签到:

insert into signUpInfo values('18351088222',CURRENT_TIMESTAMP);
这样我们的签到表中就会多了一条记录,我是在晚上11点多做的,那么查询下:

select * from signUpInfo;
结果如下图:

这个时候,我们就有了一条记录,那么就可以用来做测试了。

package com.huan.jsonservlet;


import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;


/**
 * Created by liuhu on 2016/11/28.
 */

public class SignDBService {
    private Connection conn=DBHelper.getConnection();          #链接数据库


    /*
    此函数用于更新数据库中签到表中的数据,向里面插入phoneNum用户的签到信息,返回值为0表示服务器异常,
    返回值为1签到成功,返回值为2表示不在签到时间,返回值为3表示已经签到,不可重复签到。
    */
    public int updateSignUp(String tableName,String phoneNum)
    {
        int result;
        try{
            Statement stmt = conn.createStatement();
            Date currentTime=new Date();     //当前时间
            SimpleDateFormat formatter=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String nowtime=formatter.format(currentTime);    //当前时间的字符串表示
            String dateTime=nowtime.substring(0,10);       //当前时间的日期的字符串表示

            //初始化签到的规定时间
            String startTime1=dateTime+" 07:30:00";
            String endTime1=dateTime+" 08:30:00";
            String startTime2=dateTime+" 13:30:00";
            String endTime2=dateTime+" 23:55:00";       #此时间是为了写博客特地改的

            System.out.println(dateTime);

            //创建三个日历对象,用于包装签到时间
            Calendar now=Calendar.getInstance();
            Calendar start=Calendar.getInstance();
            Calendar end=Calendar.getInstance();

            int flag=0;      //用于标记当前签到时间是否符合要求,不是0就是符合要求
            try {
                now.setTime(formatter.parse(nowtime));
                start.setTime(formatter.parse(startTime1));
                end.setTime(formatter.parse(endTime1));
            } catch (ParseException e) {
                result=0;    //表示服务器异常
                e.printStackTrace();
            }
            //对上午的时间段进行比较
            if(now.compareTo(start)>=0&&now.compareTo(end)<=0)
            {
                flag=1;
            }
            else       //对下午的时间段进行比较
            {
                try {
                    start.setTime(formatter.parse(startTime2));
                    end.setTime(formatter.parse(endTime2));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                if(now.compareTo(start)>=0&&now.compareTo(end)<=0)
                {
                    flag=2;
                }
            }
            //当flag为false时,表示不在签到时间里
            if(flag==0) {
                return 2;
            }
            ResultSet rs=null;

            if (flag == 1) {
                rs = stmt.executeQuery("select * from " + tableName + " where phoneNum=" + phoneNum
                        + " and signTime >= " + startTime1 + " and signTime <= " + endTime2 + ";");
            } else if (flag == 2) {
                rs = stmt.executeQuery("select * from " + tableName + " where phoneNum=" + phoneNum
                        + " and signTime >= " + startTime2 + " and signTime <= " + endTime2 + ";");
            }

            if(rs==null){     //此时表示可以签到
                try {
                    stmt.executeQuery("insert into " + tableName + " values(" + phoneNum
                            + ",CURRENT_TIMESTAMP);");
                    return 1;                          //签到成功
                }
                catch(SQLException e){
                    result=0;    //表示服务器异常
                    e.printStackTrace();
                }
            }
            else{
                return 3;       //此时表示已经签到过了,不可重复签到
            }
//            ResultSet rs=stmt.executeQuery("insert into "+tableName+" values("+phoneNum
//                    +",CURRENT_TIMESTAMP);");
        }catch(SQLException e){
            result=0;    //表示服务器异常
            e.printStackTrace();
        }
        return result;
    }
    public static void main(String[] args){
        SignDBService service=new SignDBService();
        int result=service.updateSignUp("signUpInfo","18351088222");
        System.out.println(result);

    }
}
对于链接数据库部分的代码我也就省略了,不在这里介绍,执行上面的代码,会出现如下的错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '13:30:00 and signTime <= 2016-12-07 23:55:00' at line 1
0
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3970)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3906)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2524)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2677)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2503)
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1369)
at com.huan.jsonservlet.SignDBService.updateSignUp(SignDBService.java:131)
at com.huan.jsonservlet.SignDBService.main(SignDBService.java:159)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

       看到这么多报错,说实话还是挺蒙的,看第一句中 ,提示的是sql语法错误,并提示了 near '13:30:00 and signTime <= 2016-12-07 23:55:00,那就很容易定位错误了,迅速找到这行代码,如下:

if (flag == 1) {
                rs = stmt.executeQuery("select * from " + tableName + " where phoneNum=" + phoneNum
                        + " and signTime >= " + startTime1 + " and signTime <= " + endTime2 + ";");
            } else if (flag == 2) {
                rs = stmt.executeQuery("select * from " + tableName + " where phoneNum=" + phoneNum
                        + " and signTime >= " + startTime2 + " and signTime <= " + endTime2 + ";");
            }
      刚开始看的时候,仔细检查了空格之类的语法,都没有发现什么错误的地方,又将这个语句粘贴到mysql中进行整理测试,也是通过的,在折腾了好久之后,还是没有找到错误,这时候再次去查看错误的时候,猛的一想会不会是因为日期的引号问题啊,当时只是脑子里略过这个想法,然后就抱着试一试的态度,改成了如下:


if (flag == 1) {
                rs = stmt.executeQuery("select * from " + tableName + " where phoneNum=" + phoneNum
                        + " and signTime >= '" + startTime1 + "' and signTime <= '" + endTime2 + "';");
            } else if (flag == 2) {
                rs = stmt.executeQuery("select * from " + tableName + " where phoneNum=" + phoneNum
                        + " and signTime >= '" + startTime2 + "' and signTime <= '" + endTime2 + "';");
            }
        乍一看是不是感觉没什么不同,不,请仔细看,我在signTime的地方都加了单引号,然后再次执行程序,便可以正常运行了,这里面就是sql中关于带有数字的查询时的一个问题,记得上数据库课的时候听老师说过,不过当时是查询学好的时候,由于直接输入了数字组成的学号而报错了,当时老师解释是sql server中不能直接这样写,要加上中括号,这次在mysql中遇到了这个类似的错误,这个当然我们在mysql的窗口中是肯定会想起来的了,这个错误在数据库中直接进行查询的时候是很容易被发现和解决的,但是当我们将这个查询语句移植到java中的时候,就多了引号的这一个坎了,一不注意就会掉入陷阱,而且会是很深的陷阱,而且对于刚开始写java和数据库进行交互的人来说,这个错误是很容易犯并且很难找的,所以这里就分享一下了。


posted on 2016-12-07 23:50  云端翱翔  阅读(241)  评论(0编辑  收藏  举报

导航