2012-10-23 18 views
19

मैं एक परियोजना के लिए वसंत डेटा पर विचार कर रहा हूं। क्या प्रति डिफ़ॉल्ट जेनरेट की गई बचत विधि को ओवरराइड करना संभव है? और यदि हाँ, कैसे?वसंत डेटा: सहेजें विधि ओवरराइड

+0

आप क्या हासिल करना चाहते हैं? शायद एओपी एक बेहतर दृष्टिकोण है? –

+1

यह निर्धारित करने के लिए आईडी का उपयोग न करें कि संबंधित इकाई नई है या नहीं। इकाई एक अपरिवर्तनीय अर्थ है यदि कोई उपयोगकर्ता इसे बदलता है, तो सिस्टम को बदले गए डेटा के साथ एक नया बनाना चाहिए (या उस डेटा के बराबर मौजूदा का उपयोग करना चाहिए। केवल एक ही चिंता है कि मेरे पास वसंत डेटा है + querydsl मेरे प्रोजेक्ट के लिए बहुत ही आशाजनक दिखता है। –

+0

['Persistable'] को लागू करने के बारे में क्या है (http://static.springsource.org/spring-data/data-commons/docs/1.3.2.RELEASE/api/org/springframework/data/domain/Persistable.html) क्या यह आपके लिए काम करेगा? क्या आप स्प्रिंग डेटा जेपीए या कुछ अन्य बैक-एंड डेटाबेस का उपयोग कर रहे हैं? –

उत्तर

4

यह अच्छी तरह से काम करने के लिए नहीं मिला है इसलिए मैंने अपने आवश्यक तर्क को एक सेवा वर्ग में रखा और रिपोजिटरी को सहेजने की विधि को छोड़ दिया।

public class **CustomSimpleJpaRepository** extends SimpleJpaRepository { 

@Transactional 
public <S extends T> S save(S entity) { //do what you want instead } 
} 

तो यह सुनिश्चित कर लें इस विस्तार करके डिफ़ॉल्ट SimpleJpaRepository के बजाय प्रयोग किया जाता है:

6

मैं तुम्हें SimpleJpaRepository विस्तार लगता है

public class CustomJpaRepositoryFactory extends JpaRepositoryFactory { 

    protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) { 

     Class<?> repositoryInterface = metadata.getRepositoryInterface(); 
     JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType()); 

     SimpleJpaRepository<?, ?> repo = isQueryDslExecutor(repositoryInterface) ? new QueryDslJpaRepository(
      entityInformation, entityManager) : new CustomSimpleJpaRepository(entityInformation, entityManager); 
    repo.setLockMetadataProvider(lockModePostProcessor.getLockMetadataProvider()); 

     return repo; 
    } 
} 

अभी तक पूर्ण नहीं किया गया, हम भी अपने स्वयं के कारखाने की आवश्यकता है कॉन्फ़िगरेशन xml में इसका उपयोग करने के लिए बीन:

public class CustomRepositoryFactoryBean <T extends JpaRepository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> { 

protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { 
    return new **CustomJpaRepositoryFactory**(entityManager); 
} 

}

config:

<jpa:repositories base-package="bla.bla.dao" factory-class="xxxx.**CustomRepositoryFactoryBean**"/> 

आशा है कि यह मदद करता है।

+0

'isQueryDslExecutor()' विधि निजी कोड प्रतीत होता है और 'लॉकमोडपोस्टप्रोसेसर' वर्ग मौजूद नहीं है। मेरे पास 'LockModeRepositoryPostProcessor' है, हालांकि एक ही विधि के साथ। इस अपका क्या मतलब था? – coderatchet

1

जेपीए इवेंट श्रोताओं जैसे @PrePersist, @PreUpdate का उपयोग करें। यह अंतर्निहित जेपीए प्रदाता इस विशेषताओं का समर्थन करता है तो यह काम करेगा। यह जेपीए 2 फीचर है इसलिए नवीनतम हाइबरनेट, एक्लिप्ससेंक इत्यादि का समर्थन करना चाहिए।

+0

यह काम नहीं करता है क्योंकि तर्क/कोड को चलाने की आवश्यकता है डेटाबेस को एक्सेस करना चाहिए और मैं अपनी इकाई कक्षाओं में डेटा एक्सेस लेयर के संदर्भ नहीं रखना चाहता हूं। –

+0

कई समस्याएं हैं। सबसे पहले, इन एनोटेशन में प्रदाता विशिष्ट व्यवहार हो सकता है; दूसरा, वे बहुत सीमित हैं जो वे कर सकते हैं; तीसरा, यह ओप प्रश्न का उत्तर नहीं देता है क्योंकि यह वसंत डेटा से असंबंधित है; और, आखिरकार, इनमें से कोई भी एनोटेशन सहेजने की विधि को ओवरराइड करने के उद्देश्य से नहीं है, यहां तक ​​कि जेपीए की सभी चीजों के लिए लगातार तरीका भी नहीं है। यह जवाब व्यापक रूप से डाउनवॉटेड होना चाहिए। –

19

बस सामान्य रूप से अपना कस्टम इंटरफ़ेस बनाएं और उन विधियों को घोषित करें जिन्हें आप CrudRepository (या JpaRepository इत्यादि) द्वारा उजागर किए गए उसी हस्ताक्षर के साथ ओवरराइड करना चाहते हैं। मान लीजिए आप एक MyEntity इकाई और एक MyEntityRepository भंडार है और आप डिफ़ॉल्ट स्वत: जनरेट saveMyEntityRepository जो एक ही इकाई उदाहरण लेता है की विधि ओवरराइड करने के लिए चाहते हैं, तो निर्धारित करें:

public interface MyEntityRepositoryCustom { 
    <S extends MyEntity> S save(S entity); 
} 

और के रूप में आप की तरह इस पद्धति को लागू अपने हमेशा की तरह MyEntityRepositoryImpl,:

@Transactional 
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom { 
    public <S extends MyEntity> S save(S entity) { 
    // your implementation 
    } 
} 

और फिर, हमेशा की तरह, MyEntityRepository लागू MyEntityRepositoryCustom करते हैं।

ऐसा करने के बाद, स्प्रिंग डेटा जेपीए डिफ़ॉल्ट कार्यान्वयन के बजाय MyEntityRepositoryImpl की save विधि को कॉल करेगा। कम से कम यह मेरे लिए स्प्रिंग डेटा जेपीए 1.7.2 में delete विधि के साथ काम करता है।

+4

यह वास्तव में काम करता है। इसे काम करने के लिए महत्वपूर्ण बिट नामकरण सम्मेलन को संरक्षित करना है। यही है, MyEntityRepositoryImpl क्लास नाम '<मुख्य भंडार इंटरफ़ेस नाम> IMpl' और _not_ जैसे उदाहरण के लिए बनाया जाना चाहिए 'MyEntityRepositoryCustomImpl'। यह बाद के मामले में काम नहीं करेगा। –

+2

कूल, लेकिन आप MyEntityRepositoryImpl से डिफ़ॉल्ट JPARepository.save विधि को कैसे कॉल करते हैं? –

+1

@DanielPinyol आप स्प्रिंग को अपने 'MyEntityRepositoryImpl' में इकाई प्रबंधक इंजेक्ट करने दें और फिर डिफ़ॉल्ट' JPARepository 'कार्यान्वयन के बजाए' जारी रखें (ऑब्जेक्ट) 'पर कॉल करें। आप इस उद्देश्य के लिए '@ PersistenceContext' का उपयोग कर सकते हैं। –

3

डिफ़ॉल्ट जेनरेट की गई बचत विधि के ओवरराइड प्रदान करने के लिए आपको अपने कस्टम रिपोजिटरी कार्यान्वयन के अंदर स्प्रिंग डेटा रिपोजिटरी कार्यान्वयन के एकत्रीकरण का उपयोग करने की आवश्यकता है।

भंडार इंटरफ़ेस:

public interface UserRepository extends CrudRepository<User, String>{ 

} 

आपका भंडार कार्यान्वयन:

@Repository("customUserRepository") 
public class CustomUserRepository implements UserRepository { 

    @Autowired 
    @Qualifier("userRepository") // inject Spring implementation here 
    private UserRepository userRepository; 

    public User save(User user) { 
     User user = userRepository.save(entity); 
     // Your custom code goes here 
     return user; 
    } 

    // Delegate other methods here ... 

    @Override 
    public User findOne(String s) { 
     return userRepository.findOne(s); 
    } 
} 

तो आपकी सेवा में अपने कस्टम कार्यान्वयन का उपयोग करें:

@Autowired 
@Qualifier("customUserRepository") 
private UserRepository userRepository; 
0

अगर आप उपयोगी हो सकता है ar और मूल विधि का पुन: उपयोग करने जा रहा है। लागू करने वाले वर्ग में बस EntityManager इंजेक्ट करें।

public interface MyEntityRepositoryCustom { 
    <S extends MyEntity> S save(S entity); 
} 

public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom { 

    // optionally specify unitName, if there are more than one 
    @PersistenceContext(unitName = PRIMARY_ENTITY_MANAGER_FACTORY) 
    private EntityManager entityManager; 

    /** 
    * @see org.springframework.data.jpa.repository.support.SimpleJpaRepository 
    */ 
    @Transactional 
    public <S extends MyEntity> S save(S entity) { 
     // do your logic here 
     JpaEntityInformation<MyEntity, ?> entityInformation = JpaEntityInformationSupport.getMetadata(MyEntity.class, entityManager); 
     if (entityInformation.isNew(entity)) { 
      entityManager.persist(entity); 
      return entity; 
     } else { 
      return entityManager.merge(entity); 
     } 
    } 
} 
संबंधित मुद्दे