【问题标题】:Creating BaseDAO for Each Dao class为每个 Dao 类创建 BaseDAO
【发布时间】:2014-12-02 05:59:40
【问题描述】:

我创建了一个 spring 应用程序,我决定添加一个 BaseDAO 来消除冗余创建, 每个 dao 的更新、删除、findByid 和 findAll 方法。所以我创建了一个 baseDao,每个 dao 都应该扩展这个 BaseDAO。

BaseDaoImpl

public class BaseDAOImpl implements BaseDAO{

    SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sf){
        this.sessionFactory = sf;
    }

    @Override
    public void create(ModelBase modelBase) {

         Session session = this.sessionFactory.getCurrentSession();
         session.persist(modelBase);
    }

    @Override
    public void update(ModelBase modelBase) {

        Session session = this.sessionFactory.getCurrentSession();
         session.update(modelBase);
    }

    @Override
    public Collection findAll(Class aClass) {

        Session session = this.sessionFactory.getCurrentSession();
        Collection  modelCols = session.createQuery("from "+aClass.getSimpleName()).list();
        return modelCols;
    }

    @Override
    public ModelBase findById(Class aClass, Integer id) {
        Session session = this.sessionFactory.getCurrentSession();     
        ModelBase modelBase = (ModelBase) session.load(aClass, new Integer(id));
        return modelBase;
    }



}

然后我将这个 Dao 扩展到每个 DAO

EmployeeDAOImp

public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO{

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sf){
        this.sessionFactory = sf;
    }
}

我创建了一个这样的 BaseService。但是当我尝试从 EmployeeDAO 访问 BaseDAO 方法时,它返回空指针异常。 为什么会发生这种情况。我不想使用谷歌的 genericDAO。因为我们应该创建 DAO 对于每个模型。我想消除这个。所以我就按照这个方法。

【问题讨论】:

  • 请提供您的空指针异常的堆栈跟踪,它将准确描述失败的原因。您的代码中明显的失败是您隐藏了 SessionFactory 的定义。删除 EmployeeDAOImpl 中发布的正文可能会解决您的问题。

标签: java spring spring-mvc


【解决方案1】:

您是否特别关注 Spring Data 项目和 Spring Data JPA?

这将为您节省大量时间,因为您不再需要从头开始编写 DAO / 存储库,您所需要做的就是启用 Spring Data JPA,并添加所需的接口。它应该可以为您节省大量时间。

【讨论】:

  • 我同意。 Spring Data 简化了模型层,减少了普通 DAO 层的样板代码。好的文档和更好的例子。就我而言,我正在使用 JPA+Hibernate 和完全免费的 XML 配置
【解决方案2】:

您将无缘无故地从基类覆盖 setSessionFactory,它已经与扩展类 EmployeeDAOImpl 一起使用,请删除它或尝试以下操作:

public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO{

   //this reference should be from base class,
   // the extending class ref is hiding base ref.
  //  private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sf){
      super.setSessionFactory(sf);
    }
}

【讨论】:

    【解决方案3】:

    类似下面的东西应该可以工作(注意使用构造函数而不是 setter 注入)。在 BaseDAO 中:

    public class BaseDAOImpl implements BaseDAO {
    
      private final SessionFactory sessionFactory;
    
      public BaseDAOImpl(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
      }
    }
    

    然后在 Employee DAO 中:

    public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO {
    
      @Inject
      public EmployeeDAOImpl (SessionFactory sessionFactory) {
        super(sessionFactory);
      }
    }
    

    【讨论】:

      【解决方案4】:

      您可以创建通用 dao。

      @Repository("genericDao")
      public class GenericDaoImpl<T,PK extends Serializable> implements GenericDao<T, PK> {
      
          protected Class<T> entityClass;
      
          public T create(T t) {
             this.entityManager.persist(t);
             return t;
          }
      
          public T read(PK id,Class<T> c) {
             return (T)this.entityManager.find(c, id);
          }
      
          public T update(T t) {
             return this.entityManager.merge(t);
          }
      
          public void delete(T t) {
              t = this.entityManager.merge(t);
             this.entityManager.remove(t);
          }
      
          public List<T> getAll(Class<T> c){
              return this.entityManager.createQuery("SELECT o FROM "+ c.getName() +" o").getResultList();
          }
        }
      

      更新

      你可以像下面这样使用,TimeRange 在下面的例子中是一个 pojo 类。如果你不想要一个服务层。您可以在控制器中使用 timeRangeDao。

      @Service("timeRangeService")
      public class TimeRangeServiceImpl implements TimeRangeService{
          @Autowired
          GenericDao<TimeRange,Long> timeRangeDao;
      
          public List<TimeRange> getAllTimeRanges(){
                  return timeRangeDao.getAll(TimeRange.class);
          }
      
          @Transactional
          public void createTimeRange(TimeRange c) {
                  timeRangeDao.create(c);
          }
      
          @Transactional
          public void update(TimeRange p) {
                  timeRangeDao.update(p);
          }
      
          @Transactional
          public TimeRange getTimeRange(long id) {
                  return timeRangeDao.read(id, TimeRange.class);
          }
      
          @Transactional
          public void delete(long id) {
                  TimeRange timeRange = new TimeRange();
                  timeRange.setId(id);
                  timeRangeDao.delete(timeRange);
          }
      
       }
      

      【讨论】:

      • 但是使用这个通用的 DAo 我必须为每个模型创建 dao。我有 100 多个模型类
      • 对不起,我不明白你的意思。如果你使用通用 dao。您可以使用 GenericDao timeRangeDao;只要提供类,你会没事的。
      • 我怎么用?你能解释一下吗
      猜你喜欢
      • 2014-08-16
      • 2015-10-26
      • 2010-12-10
      • 2011-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-24
      • 2017-03-30
      相关资源
      最近更新 更多