QueryOver: pilih kolom dari subquery

Bagaimana saya bisa memilih/memproyeksikan nilai dari subkueri dari tabel berbeda ke dalam kueri utama saya?

Saya memiliki model NH seperti ini:

[Serializable]
public class MyModel
{
    public virtual int Id {get; set;}
    //more mapped values
    ....
    //unmapped values
    public virtual string ValueFromOtherTable {get;set;}
}

Dan saya ingin mengisi ValueFromOtherTable dengan gabung kiri seperti ini:

Select mt.*, ..., ot.ValueFromOtherTable from MyModelTable mt left 
join OtherTable ot ON (somecondition)

di mana MyModelTable adalah tabel yang dipetakan ke kelas MyModel. Saya ingin mengisi ValueFromOtherTable (tanpa pemetaan NH) dengan memilih semua nilai dari mt (untuk mengisi kolom yang dipetakan NH) dan kemudian dengan menggunakan OtherTable saya ingin mengisi ValueFromOtherTable.

Saya tidak dapat menggabungkan kedua tabel melalui QueryOver karena tidak ada korelasi langsung orangtua-anak dalam model, jadi JoinAlias atau JoinQueryOver tidak akan berfungsi. MainQueryOver pertanyaan saya MyModelTable.

ALTERNATIF:

Alternatifnya adalah dengan terlebih dahulu mendapatkan semua nilai dari MyModelTable dan kemudian menggunakan properti di sana untuk menanyakan OtherTable. Namun hal ini akan mengakibatkan masalah SELECT N+1 (untuk setiap model dari MyModel pilih beberapa Tabel Lain...) dan juga membuat kode menjadi sangat rumit.

Apakah ada cara yang baik untuk mengatasi masalah ini atau satu-satunya cara untuk mengisi MyModel dengan menggunakan alternatif yang dijelaskan?


person Philipp    schedule 06.10.2014    source sumber


Jawaban (1)


Salah satu caranya adalah dengan menggunakan Proyeksi, Subquery, dan DTO. Jadi katakanlah kita memiliki DTO (hampir sama dengan MyModel, tetapi dengan properti eksternal baru ... misalnya Hitung). Lalu kita bisa melakukannya seperti ini:

MyModel main = null;
MyModelDTO dto = null;

// the main query
var query = session.QueryOver<MyModel>(() => main);

// the subquery used for projection
var subquery = QueryOver.Of<OtherModel>()
    // select something, e.g. count of the ID
    .SelectList(selectGroup => selectGroup.SelectCount(o => o.ID))
    // some condition
    // kind of JOIN inside of the subquery
    .Where(o => o.xxx == main.yyy); // just example

// now select the properties from main MyModel and one from the subquery
query.SelectList(sl => sl
      .SelectSubQuery(subquery)
         .WithAlias(() => dto.Count)
      .Select(() => main.ID)
        .WithAlias(() => dto .ID)
      ....
    );

// we have to use transformer
query.TransformUsing(Transformers.AliasToBean<MyModelDTO >())

// and we can get a list of DTO
var list = query.List<MyModelDTO>();
person Radim Köhler    schedule 06.10.2014
comment

Ini adalah pemeriksaan "Hasil pemanggilan metode diabaikan". Secara default, ini hanya melaporkan beberapa metode khusus, termasuk semua metode java.lang.BigDecimal. Dalam konfigurasi inspeksi Anda dapat menambahkan kelas dan metode lain yang harus dilaporkan dengan cara ini.

masukkan deskripsi gambar di sini

Kotak centang "Laporkan semua panggilan non-perpustakaan yang diabaikan" memilih semua kelas dalam proyek Anda.

Jika Anda ingin menggunakan anotasi, Anda dapat membuat anotasi metode tunggal atau seluruh kelas dengan JSR 305 anotasi

javax.annotation.CheckReturnValue

Sejak IDEA 2016.3 Anda bahkan dapat menggunakan anotasi rawan kesalahan

com.google.errorprone.annotations.CanIgnoreReturnValue

untuk mengecualikan metode tunggal dari pemeriksaan nilai kembalian. Dengan menggunakan kedua anotasi tersebut, Anda dapat menulis kelas seperti ini:

import javax.annotation.CheckReturnValue;
import com.google.errorprone.annotations.CanIgnoreReturnValue;

@CheckReturnValue
class A {
  String a() { return "a"; }

  @CanIgnoreReturnValue
  String b() { return "b"; }

  void run() {
    a(); // Warning
    b(); // No warning
  }
}
- person Philipp; 06.10.2014
comment
ah oke, menurutku masih banyak pekerjaan yang harus dilakukan :) - person Philipp; 06.10.2014