2013-04-22 4 views
8

मुझे पता है कि सर्वोत्तम अभ्यास में सेवा और दाओ परत दोनों हैं और सेवा स्तर पर @ ट्रान्सैक्शनल एनोटेशन जोड़ने के लिए। लेकिन मेरे मामले में इसका मतलब है कि मेरी अधिकांश सेवा कक्षाएं डीएओ विधियों को दोहराने के लिए बनाई गई हैं ... यह काफी परेशान है।सेवा कक्षाओं में दोहराने वाले डीएओ तरीकों से कैसे बचें? @ ट्रांसेक्शनल एनोटेटेड डीएओ और सर्विस क्लासेस - क्या यह स्वीकार्य अभ्यास है?

उदाहरण के लिए।

public interface FooDAO { 
public List<FooVO> list(int cathegoryId); 
public List<FooVO> list(int cathegoryId, int ownerId); 
} 

@Service 
@Transactional 
public class FooService { 
    protected @Autowired FooDAO dao; 
    public List<FooVO> list(int cathegoryId) { 
     dao.list(cathegoryId); 
    } 
    public List<FooVO> list(int cathegoryId, int authorId) { 
     dao.list(cathegoryId, authorId) 
    } 
} 

वह कितना मूर्ख है?

ज्यादातर मामलों में मुझे वास्तव में फैंसी सेवा विधियों की आवश्यकता नहीं होती है क्योंकि आमतौर पर यह प्राप्त करने का मामला है। एक कैथोरी विवरण और कैथीगरी से मेल खाने वाली इकाइयों की एक सूची। यही कारण है कि मैं एक सरल समाधान की तलाश में हूं। डीएओ को दोहराने से बचने के लिए जेनेरिक का उपयोग करने के रूप में शानदार: डी http://www.javablog.fr/javahibernate-dont-repeat-the-dao-with-a-genericdao.html

मैंने उत्तर की खोज की है। दूसरों के बीच में मैंने Where does the @Transactional annotation belong? पढ़ा है लेकिन अभी भी मेरा जवाब नहीं मिला है।

तो मुझे आश्चर्य है कि @ ट्रांसेक्शनल के साथ डीएओ विधियों को एनोटेट करना वास्तव में इतना बुरा विचार है। http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/#apistrategy से प्रेरित मैंने एक समाधान निकाला।

क्या होगा यदि:

  • मैं केवल एक सेवा वर्ग है (जो वास्तव में जरूरत है) और अन्य सभी (सरल) के मामलों के लिए @Transactional
  • के साथ अपने तरीकों पर टिप्पणी: मैं @Transactional साथ डीएओ तरीकों पर टिप्पणी (प्रचार = Propagation.MANDATORY) और @Transactional के साथ मेरी नियंत्रक तरीकों (प्रचार = Propagation.REQUIRES_NEW)

** अद्यतन 1 **

वह कुछ इस तरह दिखेगा:

public interface FooDAO { 
@Transactional(propagation = Propagation.MANDATORY, readOnly=true) 
public List<FooVO> list(int cathegoryId); 
... 
} 

@Service 
public class FooService { 
    protected @Autowired FooDAO dao; 

    @Transactional // propagation REQUIRED 
    public List<FooVO> magic(FooVO fooVO) { 
     //do sth complicated here ;) 
    } 
    // We do not repeat DAO methods in the Service class. 
    // No wrapping methods here !!! 
} 

@Controller 
public class FooMagicController { 
    protected @Autowired FooService fooService; 
    ... 
     fooService.magic(fooVO); 
    ... 
} 
@Controller 
public class FooController { 
    protected @Autowired FooDAO dao; //DAO wired directly in the Controller class !!! 

    @Transactional(propagation = Propagation.REQUIRES_NEW) 
    @RequestMapping(".....") 
    public String listFoo(Model model,...) throws Exception { 
     model.addAttribute("list", dao.list(13)); 
     return "xyz"; 
    } 
} 

प्रत्येक मामले डीएओ सत्र जो प्रबंधित किया जाता है "ऊपर" का उपयोग करता है।

क्या यह बहुत बुरा विचार है? क्या मुझे प्राप्त करने के लिए कोई बेहतर तरीका है?

+0

मुझे इसी तरह का प्रश्न मिला है: http://stackoverflow.com/questions/4462785/transactional-controller-vs- सेवा "हां, आपके नियंत्रक विधियों में @ ट्रांसेक्शनल जोड़ना पूरी तरह मान्य है।" लेकिन "नियंत्रक को दृढ़ता परत के बारे में पता नहीं होना चाहिए, और आपको अपने व्यावसायिक तर्क को डेस्कटॉप एप्लिकेशन में पुन: उपयोग करना पड़ सकता है जहां आपकी नियंत्रक परत मौजूद नहीं है .." –

उत्तर

2

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

यदि आपको लगता है कि आपको किसी सेवा वर्ग (यानी एपीआई के साथ कक्षाएं जो शुद्ध डीएओ एपीआई से अधिक होती हैं) की आवश्यकता नहीं है तो मुझे लगता है कि सेवा कक्षाओं से बचने के लिए बेहतर है और डीएओ कार्यान्वयन का उपयोग सीधे नियंत्रक में ऑटो वायर्ड ।

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

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

अद्यतन 1

यहाँ नमूना परियोजनाओं में से एक

नियंत्रक से मेरी नियंत्रक और सेवा वर्ग हैं

public class HomePageController { 


@Autowired 
private VideoService videoService; 

    //Controller method 
@RequestMapping(value = "/tag/mostviewed") 
public @ResponseBody 
Map<String, List<Video>> showMostViewedVideosForTag(){ 
      //service api 
      videoService.getMostViewedVideo(curatorTagName) 
     } 

} 

सेवा वर्ग

@Service(value = "videoService") 
@Transactional(readOnly = true) 
public class VideoServiceImpl implements VideoService { 

@Autowired 
private VideoDAO videoDAO; 

@Autowired 
private TagDAO tagDAO; 

// WRAPPER API FOR THE DAO 

@Override 
public List<Video> getMostViewedVideo(String tagName) { 
    return videoDAO.getMostViewedVideo(tagName); 
} 


// A non wrapper API which does some business logic 
@Override 
@Transactional 
public void assignTagsToVideo(String videoId, String userId, String... tags) { 

     for (String tag : tags) { 
      if (tagHeritageDAO.getTagHeritage(tag, videoId, userId) == null) { 
       Tag tagObj = tagDAO.getTag(tag); 
       if (tagObj != null) { 
        //some logic here to add tags to video 
       } 
      } 
     } 

    videoDAO.update(video); 
} 
} 

जैसा कि आप देख केवल सेवा तार है नियंत्रक वर्ग में डी, और दाओ सेवा वर्ग के लिए तारित हैं। मिश्रित मोड से मेरा यही मतलब है। क्षमा करें अगर मैं आपको उलझन में डालता हूं।

+0

हाँ, अंतिम अनुच्छेद मेरे मामले का वर्णन करता है। तो आप कहते हैं कि ट्रांसेक्शन डीएओ के साथ मिश्रण लेनदेन सेवा सभी के बाद एक बुरा अभ्यास नहीं है, है ना? और, चूंकि आपने मुझे कुछ और सलाह नहीं दी है, शायद इस स्थिति में सबसे अच्छा समाधान, जैसा कि मैं समझता हूं? –

+0

हां। मैं इसे मिश्रित मोड में उपयोग करता हूं, ताकि मेरा नियंत्रक केवल सेवा कक्षाओं से बात कर सके, न कि दाओ के लिए। यह तर्क का बेहतर अलगाव है। –

+1

प्रतीक्षा करें प्रतीक्षा करें, मिश्रित मोड का मतलब मेरे लिए कुछ और है। इसका मतलब है कि कुछ नियंत्रक सेवाओं का उपयोग करते हैं और कुछ डीएओ का उपयोग करते हैं। मुझे पता है कि यह भ्रमित हो सकता है आदि (मेरा मतलब उन लोगों के लिए है जो मेरे कोड के साथ काम करते हैं) लेकिन मेरे मामले में यह समझ में आता है। –

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