DAO pattern - use Static or non Static methods?

2019-02-21 02:05发布

问题:

My application is using a DAO pattern. Should I make the implementing methods "static" or not?

I'm talking about this concrete implementation:

  • findByIdentifier(String identifier)

But also about the Generic implementations:

  • E getByID(K ID);
  • List findAll();
  • save(E entity);
  • update(E entity);
  • delete(E entity);

Thanks for the advice!

public interface DaoBase<K, E> {
    E getByID(K ID);
    List<E> findAll();
    void save(E entity);
    void update(E entity);
    void delete(E entity);
}



public interface DaoLanguage extends DaoBase<Long, LanguageEntity> {    
    LanguageEntity findByIdentifier(String identifier);
}

I'm using JPA to persist all entity classes.

public class JpaDaoLanguage extends JpaDaoBase<Long, LanguageEntity> implements DaoLanguage {
    public LanguageEntity findByIdentifier(String identifier) {
        LanguageEntity language = (LanguageEntity) entityManager.createQuery(
                "select lan from LanguageEntity as lan where lan.identifier = ?1")
                .setParameter(1, identifier)
                .getSingleResult();
        return language;
    }
}

Generic Base implemenation

public abstract class JpaDaoBase<K, E> implements DaoBase<K, E> {
    protected EntityManager entityManager;
    protected Class<E> entityClass;

    @SuppressWarnings("unchecked")
    public JpaDaoBase() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass()
                .getGenericSuperclass();
        this.entityClass = (Class<E>) genericSuperclass
                .getActualTypeArguments()[1];

        EntityManagerFactory factory = Persistence
                .createEntityManagerFactory("CyberLabPersistenceUnit");
        entityManager = factory.createEntityManager();
    }

    @Override
    public E getByID(K ID) {
        return entityManager.find(entityClass, ID);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<E> findAll() {
        Query q = entityManager.createQuery("SELECT e FROM "
                + entityClass.getName() + " e ");
        return (List<E>) q.getResultList();
    }

    @Override
    public void save(E entity) {
        entityManager.persist(entity);
    }

    @Override
    public void update(E entity) {
        entityManager.merge(entity);
    }

    @Override
    public void delete(E entity) {
        entityManager.remove(entity);
    }
}

回答1:

Try this: write a unit test for the code you have that uses this DAO.

One of your goals should be tests that pass very quickly, and don't have dependencies on external resources (a good unit test should not require an actual database to be present.) So instead of having your test call the real DAO, create a mock DAO that returns a fixed language entity, and have your test code use the mock instead of the real DAO. Does that still work? Can you successfully substitute your mock DAO for the real DAO if the real DAO has static implementations of these methods?

Statics make your code brittle. Avoid them when you can.