2012-07-09 22 views
5

JPA için nispeten yeni, bu yüzden bir tür mimari sorum var. ı (yani birçok çalışanın bir bölüm için çalışmak) bir ilişki için pek çok tablo ÇALIŞAN ve BÖLÜMÜ var diyelim: JPA - varlık sınıfı özelliği olarak hesaplanan sütun?

EMPLOYEE 
    EMPLOYEE_ID 
    EMPLOYEE_NAME 
    DEPARTMENT_ID 

DEPARTMENT 
    DEPARTMENT_ID 
    DEPARTMENT_NAME 

yüzden Çalışan ve Bölümü için uygun varlıkları tanımlayabilirsiniz, hiçbir sorun yok. Ancak, tek bir görünümde böyle o bölüm için çalışanların sayısı, bir şeyle bölümlerin listesini görüntülemek istiyorum:

SELECT D.DEPARTMENT_NAME, 
     (SELECT COUNT(*) FROM EMPLOYEE E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID) NUMBER_OF_EMPLOYEES 
FROM DEPARTMENT D 

Bunu kullanarak JPA gerçekleştirmek için doğru bir strateji nedir emin değilim. .. Gerek duyulduğunda yalnızca bir görünüm olduğu için, departman birimi için her zaman çalışan sayısını almak istemiyorum.

Hibernate'in @Formula'nın olası bir yaklaşım olabileceği görülüyor, ancak JPA standardıyla uyumlu değil.

cevap

4

"Yeni" sözdizimini kullanarak QL'nizde herhangi bir nesne oluşturabilirsiniz; sınıfınızın yalnızca sorgunuz tarafından döndürülen değerleri alan bir kurucuya ihtiyacı vardır.

public DepartmentEmployeeCount(String departmentName, Integer employeeCount) 

sen gibi QL şey kullanabilirsiniz: Bir kurucu ile DepartmentEmployeeCount gibi bir sınıf ile Örneğin

, sadece count (*) seçerek sanki

SELECT NEW DepartmentEmployeeCount(D.DEPARTMENT_NAME, count(E.id)) from Department D left join D.employees E GROUP BY D.DEPARTMENT_NAME 

Yoksa sorgu sonucunu sadece bir sayıya çevirebilir.

Alternatif DepartmentEmployeeCount sınıfının olmadan aynı şeyi, bunu, YENİ dışarıda bırakın olabilir: her liste öğesi 2 elemanlı bir dizi nerede

SELECT D.DEPARTMENT_NAME, count(E.id)  

Bu List<Object[]> döneceğini, departmanadi ve sayım .

Yorumlarda yer alan daha sonraki sorularınızı yanıtlamak için, bir Departmanın tüm alanlarını ve geçici bir workerCount alanını doldurmak için bir öneride 2 sorgu yapılması gerekir. Bu hala orijinal sorgunuzdan daha verimli olacaktır (her çalışan sayısı için bir alt seçim).

Yani bir sorgu bölümleri

SELECT D from Department D 

size vererek okumak için List<Department>

Sonra geçici diziyi dönen bir 2 sorgusu: DEPARTMENT_ID ve sayısı ile size List<Object[]> vererek

SELECT D.DEPARTMENT_ID, count(E.id) from Department D left join D.employees E GROUP BY D.DEPARTMENT_ID 

içinde.

Sonra, ilk listenizdeki geçici sayaç özelliğini güncellemek için 2. listeyi kullanırsınız. (Bu aramayı daha kolay hale getirmek için bir Harita seçmeyi deneyebilirsiniz, ancak bence bu Hazırda Beklet özelliği).

+0

Cevabınız için @MattR teşekkür ederiz. Bu çözüm bu basit örnek için işe yarayabilir. Ancak (a) DEPARTMENT tablosunun NAME'ye ek olarak başka birçok sütunu varsa ve açıkçası bunların hepsini yapıcıda listelemek istemiyorum ve (b) bunu hala Bölüm varlığı mülkiyeti olarak kullanmak istiyorum (LAZY getirisi ile) tür) sadece durumda başka bir yerde erişilebilir olması. – AndreiM

+0

İyi bir soru, denemedim ama ben * düşünüyorum * yapıcıdaki varlık sınıflarını kullanabilirsiniz (böylece tüm varlık özelliklerini seçmeniz gerekmeyecekti). Eğer denemek için bir şans elde edersem, cevabımı güncelleştiririm ... yani, bir kurucu DepartmentEmployees (Departman, Tamsayı) vardı ve yeni DepartmentEmployees (D, count (E.id) SELECT kullanın bir DepartmentEmployees sınıf (demek) olabilir)) - tam olarak ne istemek değil ama daha yakın ... – MattR

+0

Tamam Ben bu fazladan bir bilgi güncellendi, bu yüzden öğle yemeği üzerinde bu hakkında düşünüyordum. Önerilerden herhangi birini denerseniz veya daha iyi bir çözüm bulursanız, lütfen geri bildiriniz. – MattR

3

Seçenek 1: Bunu önerdim, çünkü MattR'nin önerdiği kurucu rotasını beğenmediniz.Birkaç kez "görüntüle" sözcüğünden bahsettiniz ve kullanıcının görünümünden bahsettiğinizi biliyorum, ancak neden veritabanınızda hesaplanmış sütunları içeren bir görünüm ayarlamamış ve daha sonra hesaplananlarla eşlenen salt okunur bir varlık oluşturulmuyor. kolonlar?

Seçenek 2: Bir görünüm oluşturmak istememem yorumunuza yanıt olarak. Varlığı ve hesaplanan sütunu tutan bir kapsayıcı nesnesi oluşturabilir, daha sonra MattR'nin önerdiği gibi, seçiminizde yeni bir tane kullanırsınız. Bir şey gibi: Sonra

public class DepartmentInfo { 
    private Department department; 

    // this might have to be long or something 
    // just see what construct JPA tries to call 
    private int employeeCount; 

    public DepartmentInfo(Department d, int count) { 
     department = d; 
     employeeCount = count; 
    } 
    // getters and setters here 
} 

sizin seçmek size ilgilendiğiniz özelliklerini almak için DepartmentInfo kullanabilmesi ile

SELECT new my.package.DepartmentInfo(D, 
     (SELECT COUNT(*) FROM EMPLOYEE E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID)) 
FROM DEPARTMENT D 

olur

+0

Bu, gerçekten mümkündür. Ama benim istediğim, mevcut varlığım için ekstra bir özellik, bir sayfada (ve muhtemelen başka bir yerde) kullanabileceğim. Bunun için başka bir görüş ve başka bir varlık yaratmaya değer mi? – AndreiM

+0

Ne istiyorsun _right now_, mevcut varlığınızın bir sayfada ve muhtemelen başka bir sayfada kullanılması için ekstra bir özelliktir. Ve ileride muhtemelen daha fazla 4 daha fazla özellik ve daha fazlası ile 3 ve daha fazlası. Her durumda, cevabım için seçenek 2'yi ekledim. – digitaljoel

+0

Teşekkürler, @digitaljoel, şu ana kadar bu senaryoda en uygun yaklaşıma benziyor. Eğer (kolayca haritalama verilen olabilir gibi görünüyor) çalışana Bölümü'nden bir dernek varsa – AndreiM

1

Sen olarak varlıktaki bir üye oluşturabilir. Ek bir sütun ve ardından sorgunuzdaki bir takma adla başvurun. @Column ek açıklamasındaki sütun adı diğer adla eşleşmelidir.

Say, orijinal sorgu için aşağıdaki gibi bir countEmployees üye ekleyebilir. Ayrıca insertable=false ve updatable=false böylece varlık yöneticisi alışkanlık ekleme veya güncelleme tablolara dahil etmeyi deneyin ekleyin:

public class Department { 

    @Column(name="DEPARTMENT_ID") 
    Long departmentId; 

    @Column(name="DEPARTMENT_NAME") 
    String departmentName; 

    @Column(name="countEmployees", insertable=false, updatable=false) 
    Long countEmployees; 

    //accessors omitted 

} 

Ve Sorgunuzla: Bahar Veri JPA Arşivleri ile çalışırken de geçerlidir

SELECT D.DEPARTMENT_NAME, 
(SELECT COUNT(*) FROM EMPLOYEE E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID) AS countEmployees 
FROM DEPARTMENT D 

.

+0

Aynı şeyi JPA sorgusu kullanarak yapabilir misiniz, doğal değil mi? – Arthur

+0

Bu strateji çalışmıyor. – Partha

İlgili konular