选择7天前JDBC

时间:2017-04-24 03:30:37

标签: java sql postgresql date jdbc

我正在为餐馆数据库程序创建一个JDBC,用户可以看到过去7天内的利润报告。

我不知道如何选择过去七天,所以该计划显示七天前的总利润。

我想知道如何实现这一点,我的代码看起来像这样:

   public static void showSevenDaysAgoSells() {
            double value = 0.0;
            try {       
                System.out.println("----Showing last seven days profit----");
                PreparedStatement stmt = conn.prepareStatement("SELECT sum(total) FROM sells WHERE date > date_from_7_days_ago");
                java.sql.Date date= new java.sql.Date(new java.util.Date().getTime());
                stmt.setObject(1, LocalDate.now(ZoneId.of("America/Caracas")).minusWeeks(1));               
                stmt.executeQuery();
                ResultSet rs = stmt.executeQuery();
                rs.next();
                String sum = rs.getString(1);
                value = Double.parseDouble(sum);
                System.out.println("DAYS" + "\t" +  "TOTAL");
                System.out.println(date+ "\t" + sum);
                } catch(Exception e) {
                e.printStackTrace();
            }
        }

2 个答案:

答案 0 :(得分:3)

TL;博士

PreparedStatement stmt = conn.prepareStatement(
    "SELECT sum( total_ ) FROM sells_ WHERE date_ > ? ;"
);

...和...

stmt.setObject(                            // Use JDBC 4.2 method for passing/fetching java.time types.
    1 ,                                    // Specify which placeholder `?` in PreparedStatement (1, 2, 3, etc.). In this case, `1`. 
    LocalDate.now(                         // Get current date (today) in desired/expected time zone. 
        ZoneId.of( "America/Montreal" )
    ).minusWeeks( 1 )                      // Go back in time a week (7 days).
)

?

您在SQL字符串中嵌入了变量date_from_7_days_ago。因此它被视为字符串文字,而不是Java变量的传递值。将该变量名称替换为PreparedStatement的问号?占位符。

PreparedStatement stmt = conn.prepareStatement( "SELECT sum( total_ ) FROM sells_ WHERE date_ > ? ;" );

提示:避免使用datetotal等保留字来命名列和其他数据库标识符。各种SQL数据库总共保留了超过一千个保留字,因此碰撞比人们意识到的要容易。 SQL规范明确承诺永远不会保留带尾随下划线的任何单词。因此,请将您的所有标识符date_total_命名为永远不要担心冲突。

避免遗留日期时间类

问题和其他答案都使用了经过证明设计不当,容易混淆和有缺陷的麻烦的旧日期时间类。它们现在已经遗留下来,取而代之的是java.time类。

java.time.LocalDate类表示没有时间且没有时区的仅限日期的值。

时区

问题和其他答案都忽略了时区的关键问题。

确定日期时需要时区。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );

如果您的业务逻辑要求指的是UTC而不是特定时区,请使用常量ZoneOffset.UTC

LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;

要获得七天前(一周),请让对象执行date-math。

LocalDate weekAgo = LocalDate.minusWeeks( 1 );

JDBC

如果JDBC driver符合JDBC 4.2及更高版本,则可以通过PreparedStatement.setObjectResultSet.getObject直接使用java.time类型。

myPreparedStatement.setObject( … , weekAgo );

并检索:

LocalDate ld = myResultSet.getObject( … , LocalDate.class );

至少这两个Postgres的JDBC驱动程序可能已经针对JDBC 4.2进行了更新,尽管我还没有测试它们是否支持java.time类型。

如果您的JDBC驱动程序不符合,那么请回到使用java.sql。但是尽可能简短地这样做,立即转换为/从java.time转换。要转换,请查看添加到旧类的新方法。在这种情况下,我们必须使用valueOftoLocalDate方法回归使用java.sql.Date

myPreparedStatement.setObject( … , java.sql.Date.valueOf( weekAgo ) );

并检索:

LocalDate ld = myResultSet.getDate( … ).toLocalDate() ;

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:-1)

待办事项

    final long OneDayMillis = 86400000l;
    PreparedStatement stmt = conn.prepareStatement("SELECT sum(total) FROM sells WHERE date > ?");
    java.sql.Date date = new java.sql.Date(System.currentTimeMillis()-OneDayMillis*7l);
    stmt.setDate(1, date);

考虑到服务器的当前日期可能与客户端计算机的当前日期不同,因此最好将服务器端日期与SQL语句一起使用,如

SELECT sum(total) FROM sells WHERE date > current_date - integer '7'

没有任何来自客户端的参数绑定。