2016-06-11 103 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