存储库设计模式——每个 Dao 都应该有一个存储库吗?
Repository design pattern - should there be one repo for every Dao?
我的应用程序中有几个 DAO,它们访问数据库以进行 CRUD 操作。让我们说有新闻、天气和体育 DAO。所以我对我需要多少存储库感到困惑。我应该只使用一个存储库说 DataRepository 并让我保存我的数据库和所有 dao 的。并在其中封装 CRUD 操作的方法?还是每个 DAO 都应该有自己的存储库?
我的意思是存储库应该 return 只有调用层理解的数据对象。所以它就像是对 DAO 的封装,但我不确定我是应该为每个 DAO 创建一个还是每个应用程序只有一个 repo,等等。
如果您阅读本文 article,我们就会开始理解该模式是过度设计或过度抽象的。它变成了隐藏细节与最小化查询语句。
但似乎每个 DAO 应该有一个 Repo,因为接口本身看起来像这样:
interface Repository<T> {
void add(T item);
void remove(Specification specification);
List<T> query(Specification specification);
}
其中 T 可以是数据 DAO 访问的 type/table。现在只需要澄清一下。你能想象我有 30 种不同的类型,所以我需要 30 种不同的 Repo 实现。这是荒唐的。似乎存储库模式本身就像一个 DAO,没有什么不同。我很困惑。
我不确定这就是你要找的,但在我的应用程序中,我使用了描述的 DAO
模式和 Spring
So im confused on how many Repositories i would need.
恕我直言,每个实体至少需要一个存储库,因为它们会导致简单的设计,但由于您要使它们通用并且它们在层次结构中,可以简单地与 child [=45= 一起使用]
下面是例子
定义常用的所有基本方法的接口
public interface GenericDAO<T, ID extends Serializable> {
T findById(ID id, LockModeType lock);
void save(T entity);
T update(T entity);
List<T> findAll();
}
通用实现
public abstract class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> {
@PersistenceContext
protected EntityManager em;
private final Class<T> entityClass;
public GenericDAOImpl(Class<T> entityClass) {
this.entityClass = entityClass;
}
@Override
public T findById(ID id, LockModeType lock) {
return em.find(entityClass, id, lock);
}
@Override
public void save(T entity) {
em.persist(entity);
}
@Override
public T update(T entity) {
return em.merge(entity);
}
@Override
public List<T> findAll() {
CriteriaQuery<T> c = em.getCriteriaBuilder().createQuery(entityClass);
c.select(c.from(entityClass));
return em.createQuery(c).getResultList();
}
.
.
.
}
富class
@Entity
public class Foo implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String text;
}
Foo 存储库
public interface FooRepositiry extends GenericDAO<Foo, Long> {
Foo findTextById(Long id);
}
已实施 Foo 存储库
@Transactional
@Repository
public class FooRepoImpl extends GenericDAOImpl<Foo, Long> implements FooRepositiry {
public FooRepoImpl() {
super(Foo.class);
}
@Override
public Foo findTextById(Long id) {
CriteriaQuery<Foo> c = em.getCriteriaBuilder().createQuery(Foo.class);
// .
// .
// .
return em.createQuery(c).getSingleResult();
}
}
酒吧也一样class
@Transactional
@Repository
public class BarRepoImpl extends GenericDAOImpl<Bar, Long> implements BarRepo {
public BarRepoImpl() {
super(Bar.class);
}
@Override
public List<Bar> findAllBarWithText(String text) {
CriteriaQuery<Bar> c = em.getCriteriaBuilder().createQuery(Bar.class);
return em.createQuery(c).getResultList();
}
}
这里这个通用实现需要两个东西来工作:一个 EntityManager 和一个
实体 class。 subclass 必须提供实体 class 作为构造函数参数。 EntityManager 是通过使用 PersistenceContext
提供的,或者您可以使用 getter-setter
方法。由于 GenericDAOImpl
是抽象的,因此您不能直接使用它,而是间接使用它,并且大多数常用方法都是通用的并且在层次结构中向上,这使它们成为重用的理想候选者。
中了解更多相关信息
我的应用程序中有几个 DAO,它们访问数据库以进行 CRUD 操作。让我们说有新闻、天气和体育 DAO。所以我对我需要多少存储库感到困惑。我应该只使用一个存储库说 DataRepository 并让我保存我的数据库和所有 dao 的。并在其中封装 CRUD 操作的方法?还是每个 DAO 都应该有自己的存储库?
我的意思是存储库应该 return 只有调用层理解的数据对象。所以它就像是对 DAO 的封装,但我不确定我是应该为每个 DAO 创建一个还是每个应用程序只有一个 repo,等等。
如果您阅读本文 article,我们就会开始理解该模式是过度设计或过度抽象的。它变成了隐藏细节与最小化查询语句。
但似乎每个 DAO 应该有一个 Repo,因为接口本身看起来像这样:
interface Repository<T> {
void add(T item);
void remove(Specification specification);
List<T> query(Specification specification);
}
其中 T 可以是数据 DAO 访问的 type/table。现在只需要澄清一下。你能想象我有 30 种不同的类型,所以我需要 30 种不同的 Repo 实现。这是荒唐的。似乎存储库模式本身就像一个 DAO,没有什么不同。我很困惑。
我不确定这就是你要找的,但在我的应用程序中,我使用了描述的 DAO
模式和 Spring
So im confused on how many Repositories i would need.
恕我直言,每个实体至少需要一个存储库,因为它们会导致简单的设计,但由于您要使它们通用并且它们在层次结构中,可以简单地与 child [=45= 一起使用]
下面是例子
定义常用的所有基本方法的接口
public interface GenericDAO<T, ID extends Serializable> {
T findById(ID id, LockModeType lock);
void save(T entity);
T update(T entity);
List<T> findAll();
}
通用实现
public abstract class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> {
@PersistenceContext
protected EntityManager em;
private final Class<T> entityClass;
public GenericDAOImpl(Class<T> entityClass) {
this.entityClass = entityClass;
}
@Override
public T findById(ID id, LockModeType lock) {
return em.find(entityClass, id, lock);
}
@Override
public void save(T entity) {
em.persist(entity);
}
@Override
public T update(T entity) {
return em.merge(entity);
}
@Override
public List<T> findAll() {
CriteriaQuery<T> c = em.getCriteriaBuilder().createQuery(entityClass);
c.select(c.from(entityClass));
return em.createQuery(c).getResultList();
}
.
.
.
}
富class
@Entity
public class Foo implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String text;
}
Foo 存储库
public interface FooRepositiry extends GenericDAO<Foo, Long> {
Foo findTextById(Long id);
}
已实施 Foo 存储库
@Transactional
@Repository
public class FooRepoImpl extends GenericDAOImpl<Foo, Long> implements FooRepositiry {
public FooRepoImpl() {
super(Foo.class);
}
@Override
public Foo findTextById(Long id) {
CriteriaQuery<Foo> c = em.getCriteriaBuilder().createQuery(Foo.class);
// .
// .
// .
return em.createQuery(c).getSingleResult();
}
}
酒吧也一样class
@Transactional
@Repository
public class BarRepoImpl extends GenericDAOImpl<Bar, Long> implements BarRepo {
public BarRepoImpl() {
super(Bar.class);
}
@Override
public List<Bar> findAllBarWithText(String text) {
CriteriaQuery<Bar> c = em.getCriteriaBuilder().createQuery(Bar.class);
return em.createQuery(c).getResultList();
}
}
这里这个通用实现需要两个东西来工作:一个 EntityManager 和一个
实体 class。 subclass 必须提供实体 class 作为构造函数参数。 EntityManager 是通过使用 PersistenceContext
提供的,或者您可以使用 getter-setter
方法。由于 GenericDAOImpl
是抽象的,因此您不能直接使用它,而是间接使用它,并且大多数常用方法都是通用的并且在层次结构中向上,这使它们成为重用的理想候选者。