2015-11-19 7 views
9

चलो कहते हैं कि मैं निम्नलिखित दो तालिकाओं करते हैं:मैं जेपीक्यूएल में शामिल होने के लिए केवल मैप किए गए कॉलम का उल्लेख कैसे करूं?

@Entity public class Foo { 
    @Id private int id; 
    @ManyToOne() 
    @JoinColumn(name = "bar_id") 
    private Bar bar; 
} 
@Entity public class Bar { 
    @Id private int id; 
    private Boolean flag; 
} 

और मैं एक JPQL क्वेरी कि Foo आईडी का एक संग्रह के आधार पर कुछ Bar.flag मूल्यों में परिवर्तन लिखना चाहते हैं। ,

UPDATE Bar SET flag = true WHERE id IN (SELECT bar_id from FOO where id = 3); 

आप इस अनुवाद नहीं कर सकता लेकिन JPQL क्योंकि bar_id स्तंभ इकाई की संपत्ति पर मैप नहीं है:

यदि यह सादा एसक्यूएल थे मैं कुछ इस तरह लिखना चाहते हैं।

bar_idFoo पर सीधे मैप नहीं किया गया है, मैं जेपीक्यूएल में इस प्रकार की क्वेरी कैसे प्राप्त कर सकता हूं?

+0

संग्रह कहां है? –

+0

क्या यह उत्तर नहीं देता है? http://stackoverflow.com/questions/3629259/how-do-i-do-a-jpql-subquery –

+0

@sashok_bg मैंने कोशिश नहीं की है, लेकिन मुझे नहीं लगता कि ऐसा इसलिए होगा क्योंकि मेरे पास नहीं है इकाई में मैप किए गए कच्चे विदेशी कुंजी (उनके उदाहरण में 'p.country_id') – SCdF

उत्तर

3

आप एक काम कर बहु-अपडेट क्वेरी चाहते हैं, निम्नलिखित काम करना चाहिए:

UPDATE Bar b SET flag = true WHERE b IN (SELECT f.bar from FOO f where id = 3);

विचार, संस्थाओं के साथ काम करने के लिए जब आप सबसिलेक्ट बनाते हैं।

0

आप सीधे bar_id तक नहीं पहुंच सकते हैं। Bar इकाई से id जानकारी का उपयोग करने के लिए आपको Foo और Bar के बीच "अतिरिक्त" जुड़ने की आवश्यकता है।

तो, अपने JPQL क्वेरी इस तरह होगा:

UPDATE Bar bar SET bar.flag = true 
WHERE bar.id IN 
    (SELECT barFoo.id from FOO foo 
    JOIN foo.bar barFoo 
    WHERE foo.id = 3); 
2

जेपीए की प्रमुख विशेषताओं में से एक अपने जावा कोड से बुनियादी तथ्य डेटाबेस-विवरण (विदेशी चाबियां) दूर सार संक्षेप है।

@Transactional 
public void updateBarFlagForFoo(final int fooId, final boolean newFlagValue) { 
    final Foo foo = em.find(Foo.class, fooId); 
    foo.getBar().setFlag(newFlagValue); 
} 

या थोक में:

@Transactional 
public void updateFlags(final List<Integer> fooIds, final boolean newFlagValue) { 
    final Query query = em.createQuery(
     "update Bar b set flag = :newFlagValue where b.id in " + 
      "(select f.bar.id from Foo f where f.id in (:fooIds))"); 
    query.setParameter("newFlagValue", newFlagValue); 
    query.setParameter("fooIds", fooIds); 
    query.executeUpdate(); 
} 

ध्यान दें कि इस तरह के एक अद्यतन एक ही भीतर पुनः प्राप्त किसी भी संस्था में परिवर्तन नहीं होगा वहाँ क्वेरी आप रूपरेखा कर रहे हैं को प्राप्त करने के कई तरीके हैं, यहाँ एक जोड़े हैं लेन-देन।

final Foo foo = em.find(Foo.class, 1); 
updateFlags(Arrays.asList(1), true); 

वास्तविक Foo-object को नहीं बदलेगा।

ऐसा करने का मेरा पसंदीदा तरीका कुछ इस तरह होगा:

@Transactional 
public void updateFlags(final List<Integer> fooIds, final boolean newFlagValue) { 
    final List<Bar> bars = findBarsForFooIds(fooIds); 
    for (final Bar bar : bars) { 
     bar.setFlag(newFlagValue); 
    } 
} 

private List<Bar> findBarsForFooIds(final List<Integer> fooIds) { 
    final TypedQuery<Bar> q = 
      em.createQuery("select distinct b from Foo f join f.bar b where f.id in (:fooIds)", 
          Bar.class); 
    q.setParameter("fooIds", fooIds); 
    return q.getResultList(); 
} 

आप निश्चित रूप से बना सकते हैं एक @Column कि bar_id नक्शे, लेकिन मैं इस की सिफारिश नहीं होगा, क्योंकि यह एक तरह से करने के उद्देश्य धरा JPA

संबंधित मुद्दे