2014-10-09 13 views
6

मैं स्प्रिंग एमवीसी में वेब लिख रहा हूं। मैंने जेनेरिक डीएओ का उपयोग करके सभी डीएओ लिखा। अब मैं अपनी सेवा कक्षाओं को फिर से लिखना चाहता हूं। मैं "सामान्य सेवा" कैसे लिख सकता हूं?स्प्रिंग एमवीसी: जेनेरिक डीएओ और सर्विस क्लासेस

/* ################################# DAO ################################ */ 
package net.example.com.dao; 

import java.util.List; 

public interface GenericDao<T> {  
     public T findById(int id);  
     public List<T> findAll();  
     public void update(T entity); 
     public void save(T entity);  
     public void delete(T entity); 
} 

/* ------------------------------------------------------ */ 

package net.example.com.dao; 

import java.io.Serializable; 
import java.util.List; 

import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Scope; 

@Scope("prototype") 
public abstract class GenericHibernateDaoImpl<T extends Serializable> implements GenericDao<T> { 

     private Class<T> clazz; 

     @Autowired 
     private SessionFactory sessionFactory; 

     public final void setClazz(Class<T> clazzToSet) { 
       this.clazz = clazzToSet;    
     } 

     @SuppressWarnings("unchecked") 
     public T findById(int id) { 
       return (T) getCurrentSession().get(clazz, id); 
     } 

     @SuppressWarnings("unchecked") 
     public List<T> findAll() { 
       return getCurrentSession().createQuery("FROM " + clazz.getName()).list();    
     } 

     public void update(T entity) { 
       getCurrentSession().update(entity);    
     } 

     public void save(T entity) { 
       getCurrentSession().save(entity);    
     } 

     public void delete(T entity) { 
       getCurrentSession().delete(entity);    
     } 

     protected final Session getCurrentSession(){ 
       return sessionFactory.getCurrentSession(); 
     } 
} 

/* ------------------------------------------------------ */ 

package net.example.com.dao; 

import net.example.com.entity.Country; 

public interface CountryDao extends GenericDao<Country> { 

    public Country findByName(String name);  
    public Country findByCode(String code); 

} 

/* ------------------------------------------------------ */ 

package net.example.com.dao; 

import org.springframework.stereotype.Repository; 

import net.example.com.entity.Country; 

@Repository 
public class CountryDaoImpl extends GenericHibernateDaoImpl<Country> implements CountryDao { 

     @Override 
     public Country findByName(String name) { 
       return (Country) getCurrentSession() 
           .createQuery("FROM Country WHERE name = :name") 
           .setString("name", name).uniqueResult(); 
     } 

     @Override 
     public Country findByCode(String code) { 
       return (Country) getCurrentSession() 
           .createQuery("FROM Country WHERE code = :code") 
           .setString("code", code).uniqueResult(); 
     } 

} 

/* ################################# DAO ################################ */ 

और सेवाएं::

/* ################################# SERVICE ################################ */ 

package net.example.com.service; 

import java.util.List; 

public interface GenericManager<T> { // GenericManager<T> is the same as GenericDao<T> 

     public T findById(int id);  
     public List<T> findAll();  
     public void update(T entity); 
     public void save(T entity);  
     public void delete(T entity); 
} 

/* ------------------------------------------------------ */ 

package net.example.com.service; 

import java.util.List; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 

import net.example.com.dao.GenericDao; 

@Service 
public abstract class GenericManagerImpl<T> implements GenericManager<T> { 

     @Autowired 
     protected GenericDao<T> dao; 

     @Override 
     public T findById(int id) { 
       return dao.findById(id); 
     } 

     @Override 
     public List<T> findAll() { 
       return dao.findAll(); 
     } 

     @Override 
     public void update(T entity) { 
       dao.update(entity); 
     } 

     @Override 
     public void save(T entity) { 
       dao.save(entity); 
     } 

     @Override 
     public void delete(T entity) { 
       dao.delete(entity);  
     } 
} 
/* ------------------------------------------------------ */ 

package net.example.com.dao; 

import net.example.com.entity.Country; 

public interface CountryManager extends GenericDao<Country> { // CountryManager is the same as CountryDao 

    public Country findByName(String name);  
    public Country findByCode(String code); 
} 

/* ------------------------------------------------------ */ 

package net.example.com.service; 

import java.util.List; 

import javax.transaction.Transactional; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 

import net.example.com.dao.CountryDao; 
import net.example.com.entity.Country; 

@Service 
@Transactional 
public class CountryManagerImpl extends GenericManagerImpl<Country> implements CountryManager { 

     @Override 
     public List<Country> findAll() { 
       return dao.findAll(); 
     } 

     public Country findById(int id) { 
       return dao.findById(id); 
     } 

     @Override 
     public Country findByName(String name) { 
       return dao.findByName(name); // compiler (and Eclipse) do not see findByName !!!!!!!!! 
     } 

     @Override 
     public Country findByCode(String code) { 
       return dao.findByCode(code); // compiler (and Eclipse) do not see findByCode !!!!!!!!! 
     } 

     @Override 
     public void save(Country country) { 
       dao.save(country); 
     } 

     @Override 
     public void delete(Country country) { 
       dao.delete(country); 
     } 

     @Override 
     public void update(Country country) { 
       dao.update(country); 
     } 

} 

/* ------------------------------------------------------ */ 

/* ################################# SERVICE ################################ */ 

संकलक (और ग्रहण) findByName और findByCode तरीकों नहीं दिख रहा है

मेरी DAOs रहे हैं। मैं समझता हूं क्यों। लेकिन मैं इसे कैसे लिख सकता हूं?

उत्तर

0

मुझे लगता है कि यह जावा ओओ डिजाइन की सीमा है।

List<T> findByPredicate(List<Predicate> predicates, Class<T> returnType); 

कहाँ विधेय वर्ग इस

class Predicate { 
    String columnName; 
    Operator operator; 
    String value; 
} 

की तरह कुछ इसलिए आप "name = 'जॉन' 'व्यक्त कर सकते है, उम्र: आप की तरह कुछ खोज के लिए विधेय पारित करने के लिए एक parametrized तरह से की जरूरत है > = 21, आदि

यह एक आदर्श समाधान नहीं है, कोड कम मानव पठनीय हो जाता है, आपको भविष्यवाणियों को डेटाबेस प्रश्नों में बदलने की आवश्यकता होगी और कुछ प्रकार के कास्टिंग करने की आवश्यकता है जो रनटाइम त्रुटि से ग्रस्त हैं।

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

List<Person> findByName(String name); 

एक अंतरफलक विधि की आपूर्ति करने की जरूरत है और एक कार्यान्वयन स्वचालित रूप से आवेदन बूटस्ट्रैप पर उत्पन्न हो जाएगा। अधिक के लिए स्प्रिंग डेटा जेपीए पर एक नज़र डालें।

1

समस्या यह है कि आप अपने जेनेरिक मैनेजर में सीधे जेनेरिकडाओ को इंजेक्ट करते हैं लेकिन उनमें से कोई भी एक ठोस वसंत बीन नहीं है और आप कभी भी अपने विशिष्ट देशडाओ का उपयोग करने में सक्षम नहीं होंगे।

आप GenericDao autowire नहीं होना चाहिए, लेकिन केवल यह परिभाषित करने और सेटर प्रदान करते हैं:

// Add DAO as a genric parameter 
public abstract class GenericManagerImpl<T, D extends GenericDao<T>> implements GenericManager<T> { 
    private D dao; 

    protected void setDao (D dao) { 
     this.dao = dao; 
    } 

... 

}

फिर, आप अपने ठोस सेवाओं में एक ठोस वसंत सेम इंजेक्षन करना होगा। अर्थात CountryManagerImpl में:

// Instantiate your concrete service with your concrete DAO 
public class CountryManagerImpl extends GenericManagerImpl<Country, CountryDao> implements CountryManager { 

    // Do not redeclare your dao here in order to keep the inherited one 

    // Don't forget to inject 
    @Inject("countryDao") 
    @Override 
    protected void setDao (CountryDao dao) { 
     this.dao = dao; 
    } 

... 

} 

फिर आप होगा एक पूर्ण वसंत सेम अपने ठोस CountryDao प्रकार और उसके विशिष्ट तरीकों के साथ इंजेक्शन।

आप क्या हम सामान्य सेवाओं के बारे में RESThub परियोजना पर किया था पर एक नज़र ले जा सकते हैं: https://github.com/resthub/resthub-spring-stack/blob/master/resthub-common/src/main/java/org/resthub/common/service/CrudServiceImpl.java और कुछ ठोस उदाहरण: https://github.com/resthub/todo-backbone-example/blob/master/src/main/java/todo/TodoController.java (एक नियंत्रक के बजाय एक सेवा के साथ, लेकिन यह समान है)

आशा है कि यह मदद मिलेगी।

(और खेद अगर वहाँ कुछ लेखन-त्रुटियों है, मैं डबल नहीं की जांच अभी कर सकते हैं)

और, Btw, आप के बजाय स्प्रिंग डेटा का उपयोग कर GenericDaos उपयोग करने पर विचार करना चाहिए, लेकिन आप अभी भी अपने सेवा के बारे में एक ही जरूरतों को होगा।

+0

मैं http://pastebin.com/rN1C0i3w और यह अभी भी – martin

+0

:-(ठीक है, मैं कई गलतियों को देख सकते हैं (कुछ मेरे हैं काम नहीं करता है :-)): डीएओ प्रकार को आपके जेनेरिक मैनेजर में एक सामान्य प्रकार के रूप में पारित किया जाना चाहिए (मेरे उत्तर में संपादित कोड देखें) और @ इंजेक्शन एनोटेशन को न भूलें। मैंने अपना जवाब अपडेट किया। – bmeurant

+0

कुछ भी नहीं भूलना सुनिश्चित करें, आपको वास्तव में पहले दो पेस्टों को देखना चाहिए ... – bmeurant

1

मुझे अभी भी पता नहीं क्यों लोग वास्तव में पुरातन डीएओ/सेवा - स्प्रिंग डेटा के साथ मॉडल का उपयोग करते हैं; पूरी तरह से अनावश्यक, त्रुटि प्रवण और क्या नहीं।

स्प्रिंग डाटा जेपीए कुछ अत्यंत कि सामान के लिए उपयोगी इंटरफेस हैं: - इन संपुटित सब कुछ आप चाहते हैं, तो आप केवल अपने मानक संस्थाओं और thats की जरूरत है - JpaRepository और JpaSpecificationExecutor सब कुछ वसंत द्वारा नियंत्रित किया जाएगा, तो आप बस इनपुट अपने मानदंडों और पहिया को पुनर्निर्मित किए बिना, वही प्राप्त करें जो आप चाहते हैं। क्या यह हो सकता है कि आपने वास्तव में दस्तावेज़ को पढ़ा नहीं है? इसकी बहुत उपयोगी:

आधिकारिक परिचय: http://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

डॉक: http://docs.spring.io/spring-data/jpa/docs/1.7.0.RELEASE/reference/html/

छोटे howto: प्रतिभा खुद से http://www.cubrid.org/wiki_ngrinder/entry/how-to-create-dynamic-queries-in-springdata

उदाहरण: https://github.com/spring-projects/spring-data-jpa-examples/tree/master/spring-data-jpa-example

उदाहरण कक्षाएं:

public CustomerSpecifications { 

    public static Specification<Customer> customerHasBirthday() { 
    return new Specification<Customer> { 
     public Predicate toPredicate(Root<T> root, CriteriaQuery query, CriteriaBuilder cb) { 
     return cb.equal(root.get(Customer_.birthday), today); 
     } 
    }; 
    } 

    public static Specification<Customer> isLongTermCustomer() { 
    return new Specification<Customer> { 
     public Predicate toPredicate(Root<T> root, CriteriaQuery query, CriteriaBuilder cb) { 
     return cb.lessThan(root.get(Customer_.createdAt), new LocalDate.minusYears(2)); 
     } 
    }; 
    } 
} 

public interface CustomerRepository extends JpaRepository<Customer>, JpaSpecificationExecutor { 
    // Your query methods here 
} 

और अब तो आप बस अपने भंडार Autowire कर सकते हैं:

@Autowired 
CustomerRepository customerRepo; 

और पुनः प्राप्त डेटा इस तरह:

List<Customer> customersWithBirthDay = customerRepo.findAll(CustomerSpecifications.customerHasBirthDay()); 

इसके कि आसान।

+0

क्या आपने तालिकाओं के बीच जटिल नीतियों के खिलाफ यह कोशिश की है? मुझे उस एपीआई के साथ बहुत बुरा अनुभव हुआ है। – John

+0

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

+0

+1 मैं यहां बिंदु के सार से सहमत हूं: सामान्य तरीके से डीएओ और सेवाओं का उपयोग स्प्रिंग ऐप्स (जावा ईई भी) में किया जाता है, यह दिमागी दबदबात्मक रूप से अप्रभावी है। इतना अनावश्यक, व्यर्थ कोड जो केवल रास्ते में आता है। स्प्रिंग डेटा बेहतर है, हालांकि अभी भी मेरा पसंदीदा दृष्टिकोण नहीं है, जो कि केवल एक सामान्य उद्देश्य वर्ग (कहना है, "ऐपडेटाबेस") है जो मानक जेपीए एपीआई को लपेटता है, जिससे इसे उपयोग करना आसान हो जाता है ("सेव" जैसी विधियों के साथ, "हटाएं", "ढूंढें (jpql, args)", आदि)। –

0

इस प्रयास करें:

public interface GenericDao<T> { 

    public List<T> loadAll() throws Exception; 
    public Long saveOrUpdate(T domain) throws Exception; 
    public void saveOrUpdate(List domainList) throws Exception; 
    public void delete(T domain) throws Exception; 
    public T get(Serializable id) throws Exception; 
    public List<T> getListByCriteria(DetachedCriteria detachedCriteria); 
    public List<T> getListByCriteria(DetachedCriteria detachedCriteria, 
            int offset, int size); 
    public List<T> filterListWithCondition(T domain) throws Exception; 

} 

public class GenericDaoImpl<T> extends HibernateDaoSupport implements GenericDao<T> { 

     @Autowired 
     SessionFactory sessionFactory; 

     private Class<T> entityClass; 
     private MySQLIntegrityConstraintViolationException sqlException = new MySQLIntegrityConstraintViolationException("Duplicate Record inserted"); 

     @Autowired 
     public void setSession(SessionFactory sessionFactory){ 
     this.setSessionFactory(sessionFactory); 
     } 

     public GenericDaoImpl() { 
      entityClass = (Class<T>) ((ParameterizedType) getClass() 
          .getGenericSuperclass()).getActualTypeArguments()[0]; 
     } 

     public List<T> loadAll() throws Exception{ 
      Session session = getHibernateTemplate().getSessionFactory().openSession(); 
      List<T> list = session.createQuery("from "+entityClass.getName()).list(); 
      session.close(); 
      return list; 
     } 

     public void delete(T domain) throws Exception { 

       Session session = sessionFactory.openSession(); 
       Transaction tx = session.beginTransaction(); 

       session.delete(domain); 
       tx.commit(); 
       session.close(); 

     } 

     public Long saveOrUpdate(T domain) throws Exception { 

      try { 
       Session session = sessionFactory.openSession(); 
       Transaction tx = session.beginTransaction(); 

       session.saveOrUpdate(domain); 
       tx.commit(); 
       Serializable ids = session.getIdentifier(domain); 
       session.close(); 
       return (Long)ids; 

      } catch (ConstraintViolationException e) { 
       throw new ConstraintViolationException("Duplicate Record inserted", sqlException, ""); 
      } 

     } 

     public void saveOrUpdate(List domainList) throws Exception { 
      try { 
       Session session = sessionFactory.openSession(); 
       Transaction tx = session.beginTransaction(); 

       Object dom = null; 

       for(int i =0; i<domainList.size(); i++) { 

        dom = domainList.get(i); 
        session.saveOrUpdate(dom); 

        if (i % 10 == 0) { 
          //10, same as the JDBC batch size 
          //flush a batch of inserts and release memory: 
         session.flush(); 
         session.clear(); 
        } 

       } 

       tx.commit(); 
       session.close(); 

      } catch (ConstraintViolationException e) { 
       throw new ConstraintViolationException("Duplicate Record inserted", sqlException, ""); 
      } 

     } 

     public T get(Serializable id) throws Exception{ 

       Session session = getHibernateTemplate().getSessionFactory().openSession(); 
       T o = (T) session.get(entityClass, id); 
       return (T)o; 

     } 

     public List<T> getListByCriteria(DetachedCriteria detachedCriteria, 
             int offset, int size) { 
      return (List<T>) getHibernateTemplate().findByCriteria(detachedCriteria, offset, size); 
     } 

     public List<T> getListByCriteria(DetachedCriteria detachedCriteria) { 
      return (List<T>) getHibernateTemplate().findByCriteria(detachedCriteria); 
     } 

     public List<T> filterListWithCondition(T domain) throws Exception { 
      return (List<T>) getHibernateTemplate().findByExample(domain); 
     } 

} 

public interface GenericService<T> { 

    public List<T> loadAll() throws Exception; 
    public Long saveOrUpdate(T domain) throws Exception; 
    public void saveOrUpdate(List domainList) throws Exception; 
    public void delete(T domain) throws Exception; 
    public T get(Serializable id) throws Exception; 
    public List<T> getListByCriteria(DetachedCriteria detachedCriteria); 
    public List<T> getListByCriteria(DetachedCriteria detachedCriteria, int offset, int size); 
    public List<T> filterListWithCondition(T domain) throws Exception; 

} 

public class GenericServiceImpl<T, T2 extends GenericDao<T>> implements GenericService<T> { 

    @Autowired 
    private T2 genericDao; 

    @Override 
    public List<T> loadAll() throws Exception { 
     return genericDao.loadAll(); 
    } 

    @Override 
    public Long saveOrUpdate(T domain) throws Exception{ 
     return genericDao.saveOrUpdate(domain); 
    } 

    @Override 
    public void delete(T domain) throws Exception { 
     genericDao.delete(domain); 
    } 

    @Override 
    public T get(Serializable id) throws Exception { 
     return genericDao.get(id); 
    } 

    @Override 
    public List<T> getListByCriteria(DetachedCriteria detachedCriteria) { 
     return genericDao.getListByCriteria(detachedCriteria); 
    } 

    @Override 
    public List<T> getListByCriteria(DetachedCriteria detachedCriteria, 
      int offset, int size) { 
     return genericDao.getListByCriteria(detachedCriteria, offset, size); 
    } 

    @Override 
    public List<T> filterListWithCondition(T domain) throws Exception { 
     return genericDao.filterListWithCondition(domain); 
    } 

    @Override 
    public void saveOrUpdate(List domainList) throws Exception { 
     genericDao.saveOrUpdate(domainList); 
    } 

} 
+0

स्टैक ओवरफ़्लो में आपका स्वागत है! चूंकि यह कोड का एक लंबा ब्लॉक है, मुझे लगता है कि यदि आपने ओपी के मुद्दे को ठीक करने के लिए वास्तव में क्या बदला है, तो आपने जवाब दिया है। – josliber

0

// कार्यान्वयन GenericDao और GenericService

// StateDaO

public interface StateDao extends GenericDao<State> { 

} 

// StateDaoImpl

@Repository("stateDao") 

public class StateDaoImpl extends GenericDaoImpl<State> implements StateDao { 

    @Autowired 
    SessionFactory sessionFactory; 
// another specific businness operation perform 

} 

// StateService

public interface StateService extends GenericService<State> { 


} 

// StateServiceImpl

@Repository("stateService") 

public class StateServiceImpl extends GenericServiceImpl<State, StateDao> implements StateService { 

    @Resource 
    StateDao stateDao; 

//using stateDao object of another specific operation 
} 
अब
संबंधित मुद्दे