2013-02-20 58 views
36

जेपीए (हाइबरनेट) में, जब हम स्वचालित रूप से आईडी फ़ील्ड उत्पन्न करते हैं, तो यह माना जाता है कि उपयोगकर्ता को इस कुंजी के बारे में कोई जानकारी नहीं है। इसलिए, इकाई प्राप्त करते समय, उपयोगकर्ता आईडी के अलावा किसी अन्य फ़ील्ड के आधार पर क्वेरी करेगा। हम उस मामले में इकाई कैसे प्राप्त करते हैं (क्योंकि em.find() का उपयोग नहीं किया जा सकता है)।जेपीए: आईडी के अलावा फील्ड वैल्यू के आधार पर इकाई कैसे प्राप्त करें?

मुझे समझ में आता है कि हम एक प्रश्न का उपयोग कर सकते हैं और परिणामों को बाद में फ़िल्टर कर सकते हैं। लेकिन, क्या एक और सीधा तरीका है (क्योंकि यह समझ में आता है कि यह एक बहुत ही आम समस्या है)।

उत्तर

0

पर एक नज़र डालें।

हाइबरनेट में अंतर्निहित find() है, लेकिन आपको एक विशेष वस्तु प्राप्त करने के लिए अपनी खुद की क्वेरी बनाना है। मैं का उपयोग करना चाहिये हाइबरनेट के Criteria:

Criteria criteria = session.createCriteria(YourClass.class); 
YourObject yourObject = criteria.add(Restrictions.eq("yourField", yourFieldValue)) 
          .uniqueResult(); 

यह आपके वर्तमान वर्ग पर एक criteria पैदा करेगा, प्रतिबंध कहा कि कॉलम "yourField" मूल्य yourFieldValue के बराबर है। uniqueResult() यह एक अद्वितीय परिणाम लाने के लिए कहता है। यदि अधिक ऑब्जेक्ट्स मेल खाते हैं, तो आपको एक सूची को पुनः प्राप्त करना चाहिए।

List<YourObject> list = criteria.add(Restrictions.eq("yourField", yourFieldValue)).list(); 

यदि आपके कोई और प्रश्न हैं, तो कृपया बेझिझक पूछें। उम्मीद है की यह मदद करेगा।

24

यह एक "समस्या" के रूप में आप यह नहीं कहा है

+0

इस हाइबरनेट विशिष्ट है? क्या मैं इसे जेपीए के साथ भी इस्तेमाल कर सकता हूं? – Neo

+1

बस पढ़ें कि यह जेपीए के साथ भी काम कर सकता है। – Neo

+0

'मानदंड' हाइबरनेट विशिष्ट है क्योंकि यह 'org.hibernate' पैकेज से आता है। –

0

public Object findByYourField(Class entityClass, String yourFieldValue) 
{ 
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); 
    CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery(entityClass); 
    Root<Object> root = criteriaQuery.from(entityClass); 
    criteriaQuery.select(root); 

    ParameterExpression<String> params = criteriaBuilder.parameter(String.class); 
    criteriaQuery.where(criteriaBuilder.equal(root.get("yourField", params)); 

    TypedQuery<Object> query = entityManager.createQuery(criteriaQuery); 
    query.setParameter(params, yourFieldValue); 

    List<Object> queryResult = query.getResultList(); 

    Object returnObject = null; 

    if (CollectionUtils.isNotEmpty(queryResult)) 
    { 
     returnObject = queryList.get(0); 
    } 

    return returnObject; 
} 
+5

मैं विश्वास नहीं कर सकता कि कितना कोड इतना आसान है। यह एक एपीआई विफल आईएमओ है। –

-2

CrudRepository और जेपीए क्वेरी का उपयोग करते हुए नीचे इस तरह एक कस्टम विधि लिखें मेरे लिए काम करता है:

import org.springframework.data.jpa.repository.Query; 
import org.springframework.data.repository.CrudRepository; 
import org.springframework.data.repository.query.Param; 

public interface TokenCrudRepository extends CrudRepository<Token, Integer> { 

/** 
* Finds a token by using the user as a search criteria. 
* @param user 
* @return A token element matching with the given user. 
*/ 
    @Query("SELECT t FROM Token t WHERE LOWER(t.user) = LOWER(:user)") 
    public Token find(@Param("user") String user); 

} 

और आप इस तरह खोजने कस्टम विधि आह्वान:

public void destroyCurrentToken(String user){ 
    AbstractApplicationContext context = getContext(); 

    repository = context.getBean(TokenCrudRepository.class); 

    Token token = ((TokenCrudRepository) repository).find(user); 

    int idToken = token.getId(); 

    repository.delete(idToken); 

    context.close(); 
} 
6

यदि आपके पास इकाई Foo के लिए भंडार है और सभी प्रविष्टियों का चयन करने की आवश्यकता है सटीक स्ट्रिंग मान boo (अन्य आदिम प्रकारों या इकाई प्रकारों के लिए भी काम करता है) के साथ। अपने भंडार इंटरफेस में इस रखो:

List<Foo> findByBoo(String boo); 

यदि आप परिणामों के आदेश की जरूरत है:

List<Foo> findByBooOrderById(String boo); 

reference पर अधिक देखें।

+0

क्या आप इस उत्तर का संदर्भ जोड़ सकते हैं? – Jolley71717

+0

ध्यान दें कि यह केवल वसंत के लिए मान्य है, सामान्य रूप से हाइबरनेट या जेपीए नहीं। – Scadge

0

मैंने एक पुस्तकालय लिखा है जो ठीक से ऐसा करने में मदद करता है। यह केवल उन फ़ील्ड को प्रारंभ करके ऑब्जेक्ट द्वारा खोज की अनुमति देता है जिन्हें आप फ़िल्टर करना चाहते हैं: https://github.com/kg6zvp/GenericEntityEJB

4

असल में, आपको एक विशिष्ट अद्वितीय फ़ील्ड जोड़ना चाहिए। मैं आमतौर पर xxxUri फ़ील्ड का उपयोग करता हूं।

class User { 

    @Id 
    // automatically generated 
    private Long id; 

    // globally unique id 
    @Column(name = "SCN", nullable = false, unique = true) 
    private String scn; 
} 

और आप व्यवसाय विधि इस तरह करेंगे।

public User findUserByScn(@NotNull final String scn) { 
    CriteriaBuilder builder = manager.getCriteriaBuilder(); 
    CriteriaQuery<User> criteria = builder.createQuery(User.class); 
    Root<User> from = criteria.from(User.class); 
    criteria.select(from); 
    criteria.where(builder.equal(from.get(User_.scn), scn)); 
    TypedQuery<User> typed = manager.createQuery(criteria); 
    try { 
     return typed.getSingleResult(); 
    } catch (final NoResultException nre) { 
     return null; 
    } 
} 
+0

मुझे लगता है कि यहां कुछ याद आ रही है: 'मानदंड। चयन (रूट); 'रूट' कहां परिभाषित किया गया था? –

+1

@JorgeCampos फिक्स्ड। धन्यवाद। –

+0

यह सहायक था। धन्यवाद। –

0

सर्वोत्तम अभ्यास @NaturalId एनोटेशन का उपयोग कर रहा है। इसे कुछ मामलों के लिए व्यावसायिक कुंजी के रूप में उपयोग किया जा सकता है, यह बहुत जटिल है, इसलिए कुछ फ़ील्ड वास्तविक दुनिया में पहचानकर्ता के रूप में उपयोग कर रहे हैं। उदाहरण के लिए, मेरे पास उपयोगकर्ता आईडी के साथ उपयोगकर्ता कुंजी प्राथमिक कुंजी के रूप में है, और ईमेल भी अद्वितीय क्षेत्र है। इसलिए हम अपने प्राकृतिक आईडी

@Entity 
@Table(name="user") 
public class User { 
    @Id 
    @Column(name="id") 
    private int id; 

    @NaturalId 
    @Column(name="email") 
    private String email; 

    @Column(name="name") 
    private String name; 
} 

हमारे रिकॉर्ड प्राप्त करने के लिए के रूप में ईमेल का उपयोग कर सकते हैं, बस 'session.byNaturalId()' का उपयोग

Session session = sessionFactory.getCurrentSession(); 
User user = session.byNaturalId(User.class) 
        .using("email","[email protected]") 
        .load()