簡體   English   中英

選擇7天之前JDBC

[英]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();
            }
        }

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).
)

?

您將變量date_from_7_days_ago嵌入到SQL字符串中。 因此,它被視為字符串文字,而不是Java變量的傳遞值。 用問號替換該變量名? PreparedStatement占位符。

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

提示:避免使用保留字(例如datetotal命名列和其他數據庫標識符。 各種SQL數據庫總共保留一千多個保留字,因此發生沖突比人們意識到的容易。 SQL規范明確承諾絕不保留帶下划線的任何單詞。 因此,將所有標識符date_total_ ,這樣就total_擔心沖突了。

避免使用舊的日期時間類

問題和其他答案都使用麻煩的舊日期時間類,事實證明它們設計不良,混亂且有缺陷。 它們現在已被遺留,由java.time類取代。

java.time.LocalDate類表示沒有日期和時區的僅日期值。

時區

問題和其他答案都忽略了時區這一關鍵問題。

確定日期時需要時區。 在任何給定時刻,日期都會在全球范圍內變化。 例如, 法國巴黎午夜過后幾分鍾是新的一天,而在魁北克蒙特利爾仍然是“昨天”。

continent/region的格式指定正確的時區名稱 ,例如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 ) ;

要獲得7天(一周)的時間,請讓該對象執行date-math。

LocalDate weekAgo = LocalDate.minusWeeks( 1 );

JDBC

如果您的JDBC驅動程序符合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及更高版本中。 這些類取代了麻煩的舊的舊式日期時間類,例如java.util.DateCalendarSimpleDateFormat

現在處於維護模式Joda-Time項目建議遷移到java.time類。

要了解更多信息,請參見Oracle教程 並在Stack Overflow中搜索許多示例和說明。 規格為JSR 310

在哪里獲取java.time類?

ThreeTen-Extra項目使用其他類擴展了java.time。 該項目為將來可能在java.time中添加內容提供了一個試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

    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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM