我正在创建一个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();
}
}发布于 2017-04-24 07:49:50
tl;dr
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).
)?
在string中嵌入变量date_from_7_days_ago。因此,它被视为字符串文本,而不是Java变量的传递值。将该变量名替换为PreparedStatement的问号PreparedStatement占位符。
PreparedStatement stmt = conn.prepareStatement( "SELECT sum( total_ ) FROM sells_ WHERE date_ > ? ;" );提示:避免使用保留词(如date和total )命名列和其他数据库标识符。各种SQL数据库总保留一千多个保留字,所以冲突比人们想象的更容易。SQL规范明确承诺不保留任何带有尾下划线的单词。因此,请将所有标识符命名为date_、total_等,这样就不必担心冲突了。
避免遗留日期-时间类
这个问题和另一个答案都使用了一些麻烦的旧日期时间类,这些类的设计都很糟糕,令人困惑,并且存在缺陷。它们现在是遗留的,被java.time类所取代。
java.time.LocalDate类表示一个日期纯值,没有一天的时间,也没有时区.
时区
无论是问题还是其他答案,都忽略了时区这个关键问题。
在确定日期时,时区是必需的。在任何特定时刻,全球各地的日期因地区而异。例如,午夜后几分钟在法国巴黎是一个新的一天,而仍然“昨天”在魁北克省。
以continent/region格式指定continent/region,如America/Montreal、Africa/Casablanca或Pacific/Auckland。不要使用3-4字母的缩写,如EST或IST,因为它们不是真正的时区,不标准化,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );如果您的业务逻辑需求规定了UTC而不是特定的时区,请使用常量ZoneOffset.UTC。
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;为了得到七天前(一周),让对象做日期-数学。
LocalDate weekAgo = LocalDate.minusWeeks( 1 );JDBC
如果您的JDBC驱动程序符合JDBC4.2及更高版本,则可以通过PreparedStatement.setObject和ResultSet.getObject直接使用java.time类型。
myPreparedStatement.setObject( … , weekAgo );并检索:
LocalDate ld = myResultSet.getObject( … , LocalDate.class );至少这两个用于Postgres的JDBC驱动程序可能已经更新为JDBC4.2,尽管我还没有测试它们是否支持java.time类型。
如果您的JDBC驱动程序不符合要求,那么回到使用java.sql。但要尽可能简短地这样做,立即转换为/从java.time。若要进行转换,请查看添加到旧类中的新方法。在这种情况下,我们将不得不回到使用java.sql.Date时使用valueOf和toLocalDate方法。
myPreparedStatement.setObject( … , java.sql.Date.valueOf( weekAgo ) );并检索:
LocalDate ld = myResultSet.getDate( … ).toLocalDate() ;关于java.time
java.time框架内置到Java8和更高版本中。这些类取代了麻烦的旧遗赠日期时间类,如java.util.Date、Calendar和SimpleDateFormat。
尤达-时间项目现在在维护模式中,建议迁移到java.time类。
要了解更多信息,请参见Oracle教程。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310。
在哪里获得java.time类?
三次-额外项目使用其他类扩展java.time。这个项目是将来可能加入java.time的试验场。您可以在这里找到一些有用的类,如Interval、YearWeek、YearQuarter和更多。
发布于 2017-04-24 06:52:22
做
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'没有来自客户端的任何参数绑定。
https://stackoverflow.com/questions/43579354
复制相似问题