2016-06-11 95 views
0

我正在嘗試遵循重用最佳實踐的代碼。 我有一些常用的方法一般DAO接口:生成服務圖層類

public interface DaoInterface<T> { 
     T findById(int id); 
     //...more methods... 
    } 

及其實現類:

public class GenericDao<T> implements DaoInterface<T> { 

     @SuppressWarnings("unchecked") 
     private final Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 

     @Autowired 
     protected SessionFactory sessionFactory; 

     @Override 
     @SuppressWarnings("unchecked") 
     public T findById(int id) { 
      Session session = sessionFactory.getCurrentSession(); 
      return (T) session.get(persistentClass, id); 
     } 

     //...more methods... 
    } 

然後我的每一個具體的實現類擴展GenericDao並實現其接口。

我在我的應用程序中也有服務層。一些服務的方法完全將他們的工作委託給DAO類。所以在每個具體的Service實現中,我會自動裝入合適的DAO類並調用它的方法。 所以現在看起來:

public interface CustomerService { 
    Customer findById(int id); 
} 

和實施:

@Service 
@Transactional(readOnly = true, rollbackFor = Exception.class) 
public class CustomerServiceImpl implements CustomerService { 

    @Autowired 
    private CustomerDao customerDao; 

    @Override 
    public Customer findById(int id) { 
     return customerDao.findById(id); 
    } 
} 

我的問題是 - 如何在泛型化的方式相同DAO類服務?所以,我的具體類的外觀:

public class CustomerServiceImpl extends GenericService<Customer> implements CustomerService { 
..... 
} 

的問題是,我不能自動裝配在通用服務DAO類:

@Autowired 
private GenericDao<T> dao; 

,這樣我可以打電話給dao的方法。 我應該在構造函數中完成它嗎?

還有一個問題 - 哪裏是註釋方法與@Transactional - 在泛型類或每個實現類中的正確位置?

+0

有太多可能的答案,或者對這種格式太好的答案太長。請添加詳細信息以縮小答案集或隔離幾個段落中可以回答的問題。 –

+0

主要問題是如何在'GenericService '類中自動裝入類型爲''的'GenericDao'? – DimaSan

回答

2

你必須創建一個通用的DAO的實例,並把在服務層的一些決定:

@Repository 
public class GenericDao implements DaoInterface<T> { 
//The type must be aquired at runtime,otherwise it may not be thread safe 

    @Autowired 
    protected SessionFactory sessionFactory; 

    @Override 
    @SuppressWarnings("unchecked") 
    public T findById(int id,Class<?> persistenceClass) { 
     Session session = sessionFactory.getCurrentSession(); 
     return (T) session.get(persistenceClass, id); 
    } 

    //...more methods... 
} 

此外,如果你需要一個良好的通用存儲庫層來看看爲Spring Data Jpa

這將讓只有一個 GenericDao的實例。

接下來你有兩個選擇:

  1. 創建您的所有需求
  2. 爲每個實體

    abstract class GenericService<T> { 
        @Autowired 
        protected GenericDao dao; 
        @SuppressWarnings("unchecked") 
        protected final Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
    
        @Override 
        public T findById(int id) { 
         return dao.findById(id,persistenceClass); 
        } 
    } 
    

    現在你的服務必須每一個擴展創建一流服務單服務使用提供的持久性類型的GenericService並完成作業。

+0

感謝您的詳細解答!這是解決方案。還有一個問題 - 我應該用'@ Repository'註釋標記子DAO類還是從'GenericDao'繼承它? – DimaSan

+0

不,您必須在每個要實例化的實現上指定@Repository(或任何其他Spring Bean Annotaion)。 –

+0

我明白了,但是沒有必要在'GenericDao'類中指定這個註釋,因爲我不會直接使用它。我對嗎? – DimaSan