जेपीए और हाइबरनेट के साथ गणना किए गए गुणों को कैसे मैप करें


104

मेरे जावा बीन में चाइल्डकाउंट प्रॉपर्टी है। यह गुण डेटाबेस कॉलम में मैप नहीं किया गया है । इसके बजाय, यह डेटाबेस द्वाराCOUNT() मेरे जावा बीन और उसके बच्चों के शामिल होने पर एक फ़ंक्शन के साथ गणना की जानी चाहिए । यह बेहतर होगा अगर इस संपत्ति की मांग / "आलसी" पर गणना की जा सकती है, लेकिन यह अनिवार्य नहीं है।

सबसे खराब स्थिति में, मैं इस बीन की संपत्ति HQL या मानदंड एपीआई के साथ सेट कर सकता हूं, लेकिन मैं पसंद नहीं करूंगा।

हाइबरनेट @Formulaएनोटेशन मदद कर सकता है, लेकिन मैं मुश्किल से कोई प्रलेखन पा सकता था।

किसी भी मदद की बहुत सराहना की। धन्यवाद।

जवाबों:


162

जेपीए व्युत्पन्न संपत्ति के लिए कोई समर्थन प्रदान नहीं करता है, इसलिए आपको प्रदाता विशिष्ट एक्सटेंशन का उपयोग करना होगा। जैसा कि आपने उल्लेख किया है, @Formulaहाइबरनेट का उपयोग करते समय इसके लिए एकदम सही है। आप एसक्यूएल टुकड़े का उपयोग कर सकते हैं:

@Formula("PRICE*1.155")
private float finalPrice;

या अन्य तालिकाओं पर भी जटिल प्रश्न:

@Formula("(select min(o.creation_date) from Orders o where o.customer_id = id)")
private Date firstOrderDate;

कहाँ idहैidवर्तमान इकाई ।

निम्नलिखित ब्लॉग पोस्ट पढ़ने के लायक है: हाइबरनेट व्युत्पन्न गुण - प्रदर्शन और पोर्टेबिलिटी

अधिक विवरण के बिना, मैं अधिक सटीक उत्तर नहीं दे सकता लेकिन उपरोक्त लिंक सहायक होना चाहिए।

यह सभी देखें:


धन्यवाद पास्कल। क्या आपके पास कोई विचार है कि निम्नलिखित काम क्यों नहीं कर रहा है? @Formula (value = "(आइकॉन से सेलेक्ट काउंट ( ) का चयन करें जहाँ ic.category_id = c.id और c.id = id)") पब्लिक इंटेगर getCountInternal () {रिटर्न काउंटइंटरनल; } क्वेरी ठीक है और मुझे लगता है कि यह लॉग में चल रही है। मैपिंग ठीक लगता है: मुख्य org.hibernate.cfg.Ejb3Column - बाइंडिंग फॉर्मूला (सेलेक्ट काउंट ) ( blah blah blah लेकिन countInternal अपने प्रारंभिक मूल्य (-1) पर सेट रहता है :( मैंने गेट एनोटेशन के बजाय फ़ील्ड एनोटेशन की कोशिश की है, लेकिन यह अभी भी काम नहीं करता है।
फ्रेंकोइस

धन्यवाद, इसने वास्तव में मेरे काम में बहुत मदद की!
मिथुल

13
@NeilMcGuigan: @Formulaएनोटेशन SQL का उपयोग करता है, HQL का नहीं।
user1438038

7
बस सीखा है कि क्वेरी के आसपास कोष्ठकों का होना कितना महत्वपूर्ण है। हमेशा SQL एक्सेप्शन के साथ समाप्त होता है, क्योंकि होस्ट ऑब्जेक्ट के लोड होने पर यह क्वेरी निश्चित रूप से एक सबक्वेरी बन जाती है। MySQL को कोष्ठक के बिना इनलाइन चयन पसंद नहीं था।
सॉरीमिसजैकसन

1
लेख की नई कड़ी है: blog.eyallupu.com/2009/07/hibernate-derived-properties.html
Adnan

53

जैसा कि इस लेख में बताया गया है , आपके पास तीन विकल्प हैं:

  • या तो आप एक @Transientविधि का उपयोग करके विशेषता की गणना कर रहे हैं
  • आप @PostLoadइकाई श्रोता का भी उपयोग कर सकते हैं
  • या आप हाइबरनेट विशिष्ट @Formulaएनोटेशन का उपयोग कर सकते हैं

जबकि हाइबरनेट आपको JF के साथ @Formula का उपयोग करने की अनुमति देता है , आप इसका उपयोग कर सकते हैं कुछ गणना के परिणाम के साथ एक क्षणिक संपत्ति को आबाद करने के @PostLoad कॉलबैक का :

@Column(name = "price")
private Double price;

@Column(name = "tax_percentage")
private Double taxes;

@Transient
private Double priceWithTaxes;

@PostLoad
private void onLoad() {
    this.priceWithTaxes = price * taxes;
}

अधिक जटिल प्रश्नों के लिए, आप हाइबरनेट का उपयोग कर सकते हैं @Formula, जैसा कि इस लेख में बताया गया है :

@Formula(
    "round(" +
    "   (interestRate::numeric / 100) * " +
    "   cents * " +
    "   date_part('month', age(now(), createdOn)" +
    ") " +
    "/ 12) " +
    "/ 100::numeric")
private double interestDollars;

7
यह हालांकि अधिक जटिल प्रश्नों के लिए अनुमति नहीं देता है
ह्यूबर्ट ग्रौजसकोविआक

2
मैंने उत्तर को अपडेट किया है इसलिए अब आपके पास अधिक जटिल प्रश्नों का भी समाधान है।
व्लाद मिहालसी

1

Blaze-Persistence Entity Views पर एक नज़र डालें जो जेपीए के शीर्ष पर काम करता है और प्रथम श्रेणी डीटीओ समर्थन प्रदान करता है। आप एंटिटी व्यूज़ के भीतर विशेषताओं के लिए कुछ भी प्रोजेक्ट कर सकते हैं और यदि संभव हो तो यह संघों के लिए मौजूदा जॉइन नोड्स का भी पुन: उपयोग करेगा।

यहाँ एक उदाहरण मानचित्रण है

@EntityView(Order.class)
interface OrderSummary {
  Integer getId();
  @Mapping("SUM(orderPositions.price * orderPositions.amount * orderPositions.tax)")
  BigDecimal getOrderAmount();
  @Mapping("COUNT(orderPositions)")
  Long getItemCount();
}

इसे प्राप्त करने से इसके समान JPQL / HQL क्वेरी उत्पन्न होगी

SELECT
  o.id,
  SUM(p.price * p.amount * p.tax),
  COUNT(p.id)
FROM
  Order o
LEFT JOIN
  o.orderPositions p
GROUP BY
  o.id

यहाँ कस्टम उप-प्रदाता प्रदाताओं के बारे में एक ब्लॉग पोस्ट है जो आपके लिए भी दिलचस्प हो सकती है: https://blazebit.com/blog/2017/entity-view-mapping-subqueries.html


0

मैंने अपने कोड पर यह कोशिश की है

 @Formula(value = "(select DATEDIFF(expiry_date,issue_date)  from document_storage)")
    private String  myColumn;

मूंछों पर कॉलम को प्रदर्शित करने का प्रयास करने से पहले ही मैं जो त्रुटियां करता हूं, उन्हें चलाता हूं और अपना दृश्य प्रदर्शित करता हूं

java.lang.NullPointerException
    at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1241)
    at java.base/java.lang.String$CaseInsensitiveComparator.compare(String.java:1235)
    at java.base/java.util.TreeMap.getEntryUsingComparator(TreeMap.java:374)
    at java.base/java.util.TreeMap.getEntry(TreeMap.java:343)
    at java.base/java.util.TreeMap.get(TreeMap.java:277)
    at com.mysql.cj.result.DefaultColumnDefinition.findColumn(DefaultColumnDefinition.java:182)

जो सवाल मैंने पूछा था कि क्या MySQL के साथ JPA / Hibernate का उपयोग करके परिकलित कॉलम के मान प्राप्त करने का कोई तरीका है?

मैं क्या गलत कर रहा हूं ?

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.