2016-05-31 1 views
1

選択した曜日の平均占有量を計算する必要があります(たとえば、すべての金曜日 - 毎分)。 Date/Time機能がないため、この問題のJPQL/Querydslソリューションは見つかりませんでした。だから私はJava Streamsを利用しようとしています。私(簡体字)対象:Javaストリームを使用してJPAリポジトリからフィールドをグループ化して平均化して新しいコレクションに入れる方法

class Occupancy { 
    private LocalDateTime timeStamp; 
    private int occupied; 
} 

私のレポ:

@Query("select o from Occupancy o") 
public Stream<Occupancy> streamAllOccupancies(); 

サンプル:

try (Stream<Occupancy> stream = repository.streamAllOccupancies()) { 

    Function<Occupancy,LocalTime> OccupancyMinutesGrouping = (Occupancy o) -> { 
     return o.getDateTime().toLocalTime().truncatedTo(ChronoUnit.MINUTES); 
    }; 


    Map<LocalTime,Double> avgMap = stream 
     .filter(o -> o.getDateTime().getDayOfWeek() == DayOfWeek.MONDAY) //example 
     .collect(
      Collectors.groupingBy(
       OccupancyMinutesGrouping, 
       Collectors.averagingInt(Occupancy::getOccupied) 
      ) 
     ); 
} 

それは動作します - しかし、それは私の占有オブジェクトのリストに可能性の変化、このマップである。

new Occupancy(localTime, averagedOccupancy); 

私はまたストリームの効率を心配 - それはデータベースからすべてのレコードを処理する必要があります。ストリームはjpa repoでどのように動作しますか?最初のSQLはすべてのレコードを取得し、ストリームはそれを処理しますか?あるいは、すべてのレコードで順番に処理されていますか?たぶん最善の解決策は、ストリームのネイティブSQLクエリinstedを使用することです?すべてのアイデアは非常に役立つでしょう...

答えて

1

List<Occupancy>への変換については、occupiedフィールドはintタイプですが、平均値は非整数である可能性があります。今

class Occupancy { 
    private LocalDateTime timeStamp; 
    private double occupied; 

    public Occupancy(LocalDateTime ts, double occ) { 
     this.timeStamp = ts; 
     this.occupied = occ; 
    } 
} 

あなただけの結果のマップから1つの以上のストリームを作成することができます:だから私はOccupancyクラスがこのように定義されていることを前提とし

List<Occupancy> occupancies = avgMap.entrySet().stream() 
    .map(e -> new Occupancy(e.getKey(), e.getValue())) 
    .collect(Collectors.toList()); 

中間Mapは(少なくとも場合は避けられないようですあなたのストリームはまだLocalTimeでソートされていません)。

メモリ使用量は、基になるJDBCドライバによって異なります。生成されたストリームは実際には、行全体のResultSetを読み取りますが、JDBC固有のもので、一度にプリバッファされる行の数です。例えば、それはあなたがこのようないくつかのクエリヒントが必要な場合がありますので、デフォルトでMySQLドライバは、メモリにResultSet完全に取得することが知られています:

@QueryHints(value = @QueryHint(name = HINT_FETCH_SIZE, value = "" + Integer.MIN_VALUE)) 

詳細についてはthis blog postを参照してください。

また、実際にJDBCドライバがサーバーからバッファリングせずに行単位でデータをフェッチする場合、DBMSとアプリケーションの間でより多くの往復が必要になるため、パフォーマンスが低下する可能性があります。 DBMSサーバが別のマシンにある場合は特に重要です)。詳細については、JDBCドライバのマニュアルを参照してください。

+0

ありがとうございます。もちろん、2番目のストリームのソリューションは機能しますが、私は1つのストリームとグループ - >平均を使用して結果をリストに入れようと考えました。私は開発にH2を使用していますが、腐食しています。それはMySQLになります。ヒントありがとうございます。 – Aragornx

関連する問題