QueryOver: เลือกคอลัมน์จากแบบสอบถามย่อย

ฉันจะเลือก / ค่าโครงการจากแบบสอบถามย่อยจากตารางอื่นลงในแบบสอบถามหลักของฉันได้อย่างไร

ฉันมีโมเดล NH เช่นนี้:

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

และฉันต้องการเติม ValueFromOtherTable ด้วยการรวมด้านซ้ายดังนี้:

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

โดยที่ MyModelTable เป็นตารางที่แมปกับคลาส MyModel ฉันต้องการเติม ValueFromOtherTable (ไม่มีการแมป NH) โดยการเลือกค่าทั้งหมดจาก mt (เพื่อเติมคอลัมน์ที่แมป NH) จากนั้นโดยใช้ OtherTable ฉันต้องการเติม ValueFromOtherTable

ฉันไม่สามารถเข้าร่วมทั้งสองตารางผ่าน QueryOver ได้ เนื่องจากไม่มีความสัมพันธ์ระหว่างพ่อแม่และลูกโดยตรงในโมเดล ดังนั้น JoinAlias หรือ JoinQueryOver จะไม่ทำงาน MainQueryOver คำถามของฉัน MyModelTable

ทางเลือก:

ทางเลือกอื่นคือรับค่าทั้งหมดจาก MyModelTable ก่อน จากนั้นจึงใช้คุณสมบัติที่นั่นเพื่อสืบค้น OtherTable อย่างไรก็ตาม สิ่งนี้จะส่งผลให้เกิดปัญหา SELECT N+1 (สำหรับแต่ละรุ่นจาก MyModel ให้เลือก OtherTable...) และยังทำให้โค้ดซับซ้อนมากด้วย

มีวิธีที่ดีในการแก้ไขปัญหานี้หรือเป็นวิธีเดียวที่จะเติม MyModel โดยใช้ทางเลือกอื่นที่อธิบายไว้หรือไม่


person Philipp    schedule 06.10.2014    source แหล่งที่มา


คำตอบ (1)


วิธีหนึ่งคือใช้ Projections, Subquery และ DTO สมมติว่าเรามี DTO (เกือบจะเหมือนกับ MyModel แต่มีคุณสมบัติภายนอกใหม่ ... เช่น Count) จากนั้นเราก็สามารถทำได้ดังนี้:

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

นี่คือการตรวจสอบ "ผลลัพธ์ของการเรียกเมธอดที่ถูกละเว้น" ตามค่าเริ่มต้น ระบบจะรายงานวิธีพิเศษเพียงสองสามวิธีเท่านั้น รวมถึงวิธีทั้งหมดของ java.lang.BigDecimal ในการกำหนดค่าการตรวจสอบ คุณสามารถเพิ่มคลาสและวิธีการอื่นๆ ที่ควรรายงานด้วยวิธีนี้

ป้อนคำอธิบายรูปภาพที่นี่

ช่องทำเครื่องหมาย "รายงานการโทรที่ไม่ใช่ไลบรารีที่ถูกละเว้นทั้งหมด" จะเลือกคลาสทั้งหมดในโปรเจ็กต์ของคุณ

หากคุณต้องการใช้คำอธิบายประกอบ คุณสามารถใส่คำอธิบายประกอบวิธีการเดียวหรือทั้งคลาสด้วย JSR 305 คำอธิบายประกอบ

javax.annotation.CheckReturnValue

ตั้งแต่ IDEA 2016.3 คุณสามารถใช้คำอธิบายประกอบที่มีแนวโน้มว่าจะเกิดข้อผิดพลาด

com.google.errorprone.annotations.CanIgnoreReturnValue

เพื่อแยกวิธีการเดียวออกจากการตรวจสอบค่าส่งคืน เมื่อใช้คำอธิบายประกอบทั้งสอง คุณสามารถเขียนคลาสได้ดังนี้:

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
อ่าโอเค ฉันเดาว่ายังมีงานอีกมากรออยู่ข้างหน้า :) - person Philipp; 06.10.2014