2015-01-07 6 views
28

वहाँ से स्प्रिंग डाटा जेपीए विधि save का उपयोग कर केवल कुछ क्षेत्रों एक इकाई वस्तु की अद्यतन करने के लिए कोई तरीका है?जेपीए: अद्यतन केवल विशिष्ट क्षेत्रों

@Entity 
public class User { 

    @Id 
    private Long id; 

    @NotNull 
    private String login; 

    @Id 
    private String name; 

    // getter/setter 
    // ... 
} 
अपने CRUD रेपो के साथ

:

उदाहरण के लिए मैं इस तरह एक जेपीए इकाई है वसंत MVC में

public interface UserRepository extends CrudRepository<User, Long> { } 

मैं एक नियंत्रक कि अद्यतन के लिए एक User वस्तु प्राप्त है यह :

@RequestMapping(value = "/rest/user", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE) 
@ResponseBody 
public ResponseEntity<?> updateUser(@RequestBody User user) { 

    // Assuming that user have its id and it is already stored in the database, 
    // and user.login is null since I don't want to change it, 
    // while user.name have the new value 

    // I would update only its name while the login value should keep the value 
    // in the database 
    userRepository.save(user); 

    // ... 
} 

मुझे पता है कि मैं findOne का उपयोग कर, फिर उसके नाम बदल सकते हैं और save उपयोग करके उसे अपडेट उपयोगकर्ता को लोड कर सकता है ... लेकिन यह बहुत कष्टप्रद परिवर्तन प्रत्येक मान हो सकता है अगर मैं 100 क्षेत्रों है और मैं उनमें से 50 को अपडेट करना चाहते ..

वहाँ है ऑब्जेक्ट "सहेजते समय" जैसे कुछ शून्य मानों को छोड़ने का कोई तरीका नहीं है "?

+3

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

+0

क्या ऐसा कोई कारण है जिसके लिए कोई ऑब्जेक्ट अपडेट करने वाले शून्य मानों को छोड़ना बेहतर नहीं है? – Andrea

+0

क्या छोड़ना है यह जानने का कोई भरोसेमंद तरीका नहीं है, नल फ़ील्ड के लिए वैध विकल्प हो सकता है, तो क्या? आप शायद 'एंटीलिटी लिस्टर' या उस तरह कुछ के साथ जगह में कुछ भी कर सकते हैं, लेकिन मैं इसके खिलाफ दृढ़ता से अनुशंसा करता हूं क्योंकि इससे शायद हल होने की तुलना में अधिक समस्याएं हो सकती हैं। –

उत्तर

1

समस्या वसंत डेटा जेपीए संबंधित नहीं है, लेकिन जेपीए कार्यान्वयन lib जो आप संबंधित उपयोग कर रहे हैं। आप हाइबरनेट के मामले में पर एक नजर है हो सकता है: मैं एक ही सवाल था

http://www.mkyong.com/hibernate/hibernate-dynamic-update-attribute-example/

+0

संदर्भ के लिए धन्यवाद .. असल में मैं हाइबरनेट का उपयोग कर रहा हूं। उस पोस्ट में 'डायनामिक-अपडेट' प्रॉपर्टी को बदलने का सुझाव दिया गया है: मैंने एनोटेशन का उपयोग करके इसे करने की कोशिश की है लेकिन वह संपत्ति जेपीए की @ एंटीटी एनोटेशन में समर्थित नहीं है और हाइबरनेट की @ एंटीटी एनोटेशन को बहिष्कृत किया गया है .... क्या आप जानते हैं इसे स्थापित करने का सही तरीका? – Andrea

+0

जैसा कि किसी अन्य उत्तर में सुझाया गया है, 'डायनामिक-अपडेट' बदलने का वास्तविक तरीका '@ डायनामिक अपडेट 'एनोटेशन का उपयोग कर रहा है ... मैंने कोशिश की है लेकिन मैंने कोई बदलाव नहीं देखा है ... कोई सुझाव? – Andrea

23

और के रूप में एम Deinum बताते हैं, इस सवाल का जवाब नहीं, तुम नहीं बचा उपयोग कर सकते है। मुख्य समस्या यह है कि वसंत डेटा नहीं जानता कि नल के साथ क्या करना है। क्या शून्य मान सेट नहीं है या यह सेट है क्योंकि इसे हटाया जाना चाहिए?

अब आपसे सवाल पूछते हैं, मुझे लगता है कि आपके पास भी वही विचार था जो मेरे पास था, जो कि सहेजने से मुझे सभी बदले गए मूल्यों को मैन्युअल रूप से सेट करने से बचने की अनुमति मिलती।

तो क्या सभी मैनुअल मैपिंग से बचना संभव है? खैर, अगर आप इस सम्मेलन का पालन करना चुनते हैं कि नल का हमेशा अर्थ है 'सेट नहीं' और आपके पास मूल मॉडल आईडी है, तो हाँ। आप Springs BeanUtils का उपयोग कर अपने आप को मैपिंग से बच सकते हैं।

आप कर सकता है निम्नलिखित:

  1. मौजूदा ऑब्जेक्ट
  2. उपयोग BeanUtils मूल्यों को कॉपी करने के
  3. सहेजें वस्तु

अब पढ़ें, स्प्रिंग के BeanUtils वास्तविक नहीं का समर्थन नहीं करता शून्य मानों की प्रतिलिपि बनाना, इसलिए यह किसी भी मान को ओवरराइट करेगा जो बाहर निकलने वाले मॉडल ऑब्जेक्ट पर शून्य के साथ सेट नहीं है।

How to ignore null values using springframework BeanUtils copyProperties?

तो यह सब एक साथ डाल आप इस

@RequestMapping(value = "/rest/user", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE) 
@ResponseBody 
public ResponseEntity<?> updateUser(@RequestBody User user) { 

    User existing = userRepository.read(user.getId()); 
    copyNonNullProperties(user, existing); 
    userRepository.save(existing); 

    // ... 
} 

public static void copyNonNullProperties(Object src, Object target) { 
    BeanUtils.copyProperties(src, target, getNullPropertyNames(src)); 
} 

public static String[] getNullPropertyNames (Object source) { 
    final BeanWrapper src = new BeanWrapperImpl(source); 
    java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); 

    Set<String> emptyNames = new HashSet<String>(); 
    for(java.beans.PropertyDescriptor pd : pds) { 
     Object srcValue = src.getPropertyValue(pd.getName()); 
     if (srcValue == null) emptyNames.add(pd.getName()); 
    } 
    String[] result = new String[emptyNames.size()]; 
    return emptyNames.toArray(result); 
} 
+4

मुझे लगता है कि यह 'userRepository.save (मौजूदा) होना चाहिए;' 'save (उपयोगकर्ता) नहीं;' – dbahdano

+0

उपर्युक्त टिप्पणी मेरे लिए बहुत धन्यवाद। –

+0

यदि डेटाटाइप पूर्णांक है तो इसका डिफ़ॉल्ट शून्य mysql में अपडेट किया गया है। स्ट्रिंग के लिए यह ठीक काम करता है कि हम इसे int, char, double जैसे अन्य डेटाटाइप के लिए कैसे कर सकते हैं। –

2

जेपीए का उपयोग करते हुए की तरह कुछ के साथ खत्म हो जाएगा आप इसे इस तरह से कर सकते हैं: सौभाग्य से, वहाँ यहाँ एक समाधान है।

CriteriaBuilder builder = session.getCriteriaBuilder(); 
CriteriaUpdate<User> criteria = builder.createCriteriaUpdate(User.class); 
Root<User> root = criteria.from(User.class); 
criteria.set(root.get("lastSeen"), date); 
criteria.where(builder.equal(root.get("id"), user.getId())); 
session.createQuery(criteria).executeUpdate(); 
संबंधित मुद्दे