[英]Select 7 days ago JDBC
我在餐廳數據庫程序中創建了JDBC,用戶可以在其中查看最近7天的利潤報告。
我不知道如何選擇最近7天,因此程序顯示了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();
}
}
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).
)
?
您將變量date_from_7_days_ago
嵌入到SQL字符串中。 因此,它被視為字符串文字,而不是Java變量的傳遞值。 用問號替換該變量名?
PreparedStatement
占位符。
PreparedStatement stmt = conn.prepareStatement( "SELECT sum( total_ ) FROM sells_ WHERE date_ > ? ;" );
提示:避免使用保留字(例如date
和total
命名列和其他數據庫標識符。 各種SQL數據庫總共保留一千多個保留字,因此發生沖突比人們意識到的容易。 SQL規范明確承諾絕不保留帶下划線的任何單詞。 因此,將所有標識符date_
, total_
,這樣就total_
擔心沖突了。
問題和其他答案都使用麻煩的舊日期時間類,事實證明它們設計不良,混亂且有缺陷。 它們現在已被遺留,由java.time類取代。
java.time.LocalDate
類表示沒有日期和時區的僅日期值。
問題和其他答案都忽略了時區這一關鍵問題。
確定日期時需要時區。 在任何給定時刻,日期都會在全球范圍內變化。 例如, 法國巴黎午夜過后幾分鍾是新的一天,而在魁北克蒙特利爾仍然是“昨天”。
以continent/region
的格式指定正確的時區名稱 ,例如America/Montreal
, Africa/Casablanca
或Pacific/Auckland
。 切勿使用EST
或IST
等3-4個字母的縮寫,因為它們不是真實的時區,不是標准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
如果您的業務邏輯要求規定了UTC而不是特定的時區,請使用常量ZoneOffset.UTC
。
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;
要獲得7天(一周)的時間,請讓該對象執行date-math。
LocalDate weekAgo = LocalDate.minusWeeks( 1 );
如果您的JDBC驅動程序符合JDBC 4.2及更高版本,則可以通過PreparedStatement.setObject
和ResultSet.getObject
直接使用java.time類型。
myPreparedStatement.setObject( … , weekAgo );
並檢索:
LocalDate ld = myResultSet.getObject( … , LocalDate.class );
至少針對Postgres的這兩個JDBC驅動程序可能已針對JDBC 4.2更新,盡管我尚未測試它們是否支持java.time類型。
如果您的JDBC驅動程序不符合要求,則退回到使用java.sql。 但是,請盡可能簡短地進行操作,立即將其轉換為java.time。 要進行轉換,請查看添加到舊類中的新方法。 在這種情況下,我們將不得不使用valueOf
和toLocalDate
方法來使用java.sql.Date
。
myPreparedStatement.setObject( … , java.sql.Date.valueOf( weekAgo ) );
並檢索:
LocalDate ld = myResultSet.getDate( … ).toLocalDate() ;
java.time框架內置於Java 8及更高版本中。 這些類取代了麻煩的舊的舊式日期時間類,例如java.util.Date
, Calendar
和SimpleDateFormat
。
現在處於維護模式的Joda-Time項目建議遷移到java.time類。
要了解更多信息,請參見Oracle教程 。 並在Stack Overflow中搜索許多示例和說明。 規格為JSR 310 。
在哪里獲取java.time類?
ThreeTen-Extra項目使用其他類擴展了java.time。 該項目為將來可能在java.time中添加內容提供了一個試驗場。 您可以在這里找到一些有用的類,比如Interval
, YearWeek
, YearQuarter
,和更多 。
做
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'
沒有客戶端的任何參數綁定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.