2010-05-29 22 views
5

के साथ जुड़ें मुझे जोड़ों या माध्यमिक चयन करने से बचने के लिए हाइबरनेट क्वेरी को अनुकूलित करने में समस्या हो रही है।द्वितीयक चयन से बचें या हाइबरनेट मानदंड या एचक्यूएल क्वेरी

जब एक हाइबरनेट क्वेरी (मापदंड या HQL), जैसे कि निम्न किया जाता है:

return getSession().createQuery(("from GiftCard as card where card.recipientNotificationRequested=1").list(); 

... और जहां खंड गुण किसी अन्य तालिकाओं के साथ जुड़ जाता है की आवश्यकता नहीं है कि जांच करती है ... लेकिन हाइबरनेट अभी भी अन्य तालिकाओं के साथ पूर्ण जुड़ाव करता है (या माध्यमिक चयन करता है कि मैं fetchMode कैसे सेट करता हूं)।

प्रश्न में वस्तु (गिफ्टकार्ड) में कई जोड़े हैं जो मैं इस मामले में आलसी रूप से लोड करना पसंद करूंगा (लेकिन सभी मामलों में आवश्यक नहीं)। मैं एक समाधान चाहता हूं कि जब मैं क्वेरी निष्पादित करता हूं तो मैं आलसी लोड कर सकता हूं।

यहाँ क्या गिफ्ट कार्ड इकाई लग रहा है की तरह है:

@Entity 
@Table(name = "giftCards") 
public class GiftCard implements Serializable 
{ 
private static final long serialVersionUID = 1L; 

private String id_; 
private User buyer_; 
private boolean isRecipientNotificationRequested_; 


@Id 
public String getId() 
{ 
    return this.id_; 
} 

public void setId(String id) 
{ 
    this.id_ = id; 
} 

@ManyToOne 
@JoinColumn(name = "buyerUserId") 
@NotFound(action = NotFoundAction.IGNORE) 
public User getBuyer() 
{ 
    return this.buyer_; 
} 
public void setBuyer(User buyer) 
{ 
    this.buyer_ = buyer; 
} 

@Column(name="isRecipientNotificationRequested", nullable=false, columnDefinition="tinyint") 
public boolean isRecipientNotificationRequested() 
{ 
    return this.isRecipientNotificationRequested_; 
} 

public void setRecipientNotificationRequested(boolean isRecipientNotificationRequested) 
{ 
    this.isRecipientNotificationRequested_ = isRecipientNotificationRequested; 
} 
} 

उत्तर

2

के रूप में कहा

मैं एक समाधान आप इस एक

@Entity 
public class GiftCard implements Serializable { 

    private User buyer; 

    @ManyToOne 
    @JoinColumn(name="buyerUserId") 
    public User getBuyer() { 
     return this.buyer; 
    } 
} 
की तरह एक मानचित्रण है कि मैं नियंत्रित कर सकते हैं क्या lazily भरी हुई है जब मैं क्वेरी

कैसा प्रदर्शन करते हैं

कोई भी * ToOne रिश्ते, जैसे @OneToOne और @ManyToOne, डिफ़ॉल्ट रूप से, FetchType.EAGER का अर्थ है जिसका अर्थ है कि यह एक होगा लावे लाया। लेकिन, यह वही नहीं हो सकता जो आप चाहते हैं। के रूप में आप क्या कहते हैं मैं को लाइटिंग स्ट्रैटेजी के रूप में अनुवादित किया जा सकता है। POJO in Action किताब इस एक (सूचना विधि हस्ताक्षर) की तरह एक पैटर्न

public class GiftCardRepositoryImpl implements GiftCardRepository { 

    public List<GiftCard> findGiftCardWithBuyer() { 
     return sessionFactory.getCurrentSession().createQuery("from GiftCard c inner join fetch c.buyer where c.recipientNotificationRequested = 1").list(); 
    } 

} 

तो आपके उपयोग के मामले के आधार पर समर्थन करता है, तो आप बना सकते हैं अपने खुद के लगता है ... के साथ ... और ... विधि। यह लाने का ख्याल रखेगा जो आप चाहते हैं

लेकिन इसमें कोई समस्या है: यह सामान्य विधि हस्ताक्षर का समर्थन नहीं करता है। प्रत्येक @ एंटीटी रिपोजिटरी के लिए, आपको अपने कस्टम को ... को परिभाषित करना होगा ... और विधि। इस कारण से, मैं तुम्हें कैसे मैं एक सामान्य भंडार

public interface Repository<INSTANCE_CLASS, UPDATABLE_INSTANCE_CLASS, PRIMARY_KEY_CLASS> { 

    void add(INSTANCE_CLASS instance); 
    void remove(PRIMARY_KEY_CLASS id); 
    void update(PRIMARY_KEY_CLASS id, UPDATABLE_INSTANCE_CLASS updatableInstance); 
    INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id); 
    INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id, FetchingStrategy fetchingStrategy); 
    List<INSTANCE_CLASS> findAll(); 
    List<INSTANCE_CLASS> findAll(FetchingStrategy fetchingStrategy); 
    List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize); 
    List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize, FetchingStrategy fetchingStrategy); 
    List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria); 
    List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria, FetchingStrategy fetchingStrategy); 
    List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria); 
    List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria, FetchingStrategy fetchingStrategy); 

} 

परिभाषित लेकिन, कभी कभी, आप नहीं सामान्य भंडार इंटरफ़ेस द्वारा परिभाषित तरीकों के सभी चाहते हैं दिखा। समाधान: एक सारणी भंडार वर्ग बनाएं जो एक डमी भंडार लागू करेगा।स्प्रिंग फ्रेमवर्क, उदाहरण के लिए, भारी इस तरह का पैटर्न का उपयोग करें इंटरफ़ेस >> AbstractInterface

public abstract class AbstractRepository<INSTANCE_CLASS, UPDATABLE_INSTANCE_CLASS, PRIMARY_KEY_CLASS> implements Repository<INSTANCE_CLASS, UPDATABLE_INSTANCE_CLASS, PRIMARY_KEY_CLASS> { 

    public void add(INSTANCE_CLASS instance) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public void remove(PRIMARY_KEY_CLASS id) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public void update(PRIMARY_KEY_CLASS id, UPDATABLE_INSTANCE_CLASS updatableInstance) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public INSTANCE_CLASS findById(PRIMARY_KEY_CLASS id, FetchingStrategy fetchingStrategy) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public List<INSTANCE_CLASS> findAll() { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public List<INSTANCE_CLASS> findAll(FetchingStrategy fetchingStrategy) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public List<INSTANCE_CLASS> findAll(int pageNumber, int pageSize, FetchingStrategy fetchingStrategy) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public List<INSTANCE_CLASS> findAllByCriteria(Criteria criteria, FetchingStrategy fetchingStrategy) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

    public List<INSTANCE_CLASS> findAllByCriteria(int pageNumber, int pageSize, Criteria criteria, FetchingStrategy fetchingStrategy) { 
     throw new UnsupportedOperationException("Not supported yet."); 
    } 

} 

तो अपने GiftCardRepository के रूप में (देखें लागू करने के बजाय फैली) और सिर्फ ओवरराइड करता है क्या तुम सच में चाहते फिर से लिखा जा सकता है और पठनीय और पोषणीय - -

public class GiftCardRepository extends AbstractRepository<GiftCard, GiftCard, String> { 

    public static final GIFT_CARDS_WITH_BUYER GIFT_CARDS_WITH_BUYER = new GIFT_CARDS_WITH_WITH_BUYER(); 
    public static final GIFT_CARDS_WITHOUT_NO_RELATIONSHIP GIFT_CARDS_WITHOUT_NO_RELATIONSHIP = new GIFT_CARDS_WITHOUT_NO_RELATIONSHIP(); 

    public List<GiftCard> findAll(FetchingStrategy fetchingStrategy) { 
     sessionFactory.getCurrentSession().getNamedQuery(fetchingStrategy.toString()).list(); 
    } 


    /** 
     * FetchingStrategy is just a marker interface 
     * public interface FetchingStrategy {} 
     * 
     * And AbstractFetchingStrategy allows you to retrieve the name of the Fetching Strategy you want, by overriding toString method 
     * public class AbstractFetchingStrategy implements FetchingStrategy { 
     * 
     *  @Override 
     *  public String toString() { 
     *   return getClass().getSimpleName(); 
     *  } 
     * 
     * } 
     * 
     * Because there is no need to create an instance outside our repository, we mark it as private 
     * Notive each FetchingStrategy must match a named query 
     */ 
    private static class GIFT_CARDS_WITH_BUYER extends AbstractFetchingStrategy {}  
    private static class GIFT_CARDS_WITHOUT_NO_RELATIONSHIP extends AbstractFetchingStrategy {} 
} 

अब हम एक बहु में हमारे नामित क्वेरी बाह्यरूप xml फ़ाइल

// app.hbl.xml 
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
    <query name="GIFT_CARDS_WITH_BUYER"> 
     <![CDATA[ 
      from 
       GiftCard c 
      left join fetch 
       c.buyer 
      where 
       c.recipientNotificationRequested = 1 
     ]]> 
    </query> 
    <query name="GIFT_CARDS_WITHOUT_NO_RELATIONSHIP"> 
     <![CDATA[ 
      from 
       GiftCard 
     ]]> 
    </query> 
</hibernate-mapping> 

तो अगर आप क्रेता के साथ गिफ्ट कार्ड प्राप्त करना चाहते हैं, बस फोन

Repository<GiftCard, GiftCard, String> giftCardRepository; 

List<GiftCard> giftCardList = giftCardRepository.findAll(GiftCardRepository.GIFT_CARDS_WITH_WITH_BUYER); 

और कोई रिश्ता बिना हमारे गिफ्ट कार्ड को पुनः प्राप्त करने के लिए, बस फोन

List<GiftCard> giftCardList = giftCardRepository.findAll(GiftCardRepository.GIFT_CARDS_WITHOUT_NO_RELATIONSHIP); 

या उपयोग आयात स्थिर

import static packageTo.GiftCardRepository.*; 

और

List<GiftCard> giftCardList = giftCardRepository.findAll(GIFT_CARDS_WITHOUT_NO_RELATIONSHIP); 

मुझे आशा है कि यह आपके लिए उपयोगी हो सकता है!

+0

बहुत रोचक ... यह विचार के लिए बहुत अच्छा खाना है। और यह एक साइड सवाल लाता है। मैं एक क्वेरी कैसे करूं जो लक्षित गिफ्टकार्ड के अलावा किसी भी संबंधित वस्तुएं नहीं लाती? –

+0

@ बेन बेन्सन गिफ्टकार्ड रिपोजिटरी (आखिरी पंक्ति) देखें, नाम फ़ाइल नाम और नीचे कोड जोड़ें। अगर मेरा जवाब आपकी जरूरतों को पूरा करता है, तो इसे स्वीकार के रूप में चिह्नित करें। धन्यवाद –

2

जेपीए में डिफ़ॉल्ट ManyToOne संघों के लिए प्रकार लाने के लिए उत्सुक है (यानी गैर आलसी) ताकि आप के साथ की कोशिश कर सकते:

@ManyToOne(fetch=FetchType.LAZY) 

फिर , किसी भी जेपीए क्वेरी में एसोसिएशन को उत्सुकता से left join fetch का उपयोग करके लाया जा सकता है।