I'm pretty new to DDD and JPA.
I'm working on a generic Repository with JPA and Spring. I really like the approaches exposed in the articles DDD: The Generic Repository and JPA implementation patterns: Data Access Objects. My aim is to build the perfect Repository in Domain-Driven Design with JPA and Spring.
I use an internal generic Repository to respect the domain’s contract with the data store, following the first article concepts.
public interface IInternalGenericRepository<K, E> {
List<E> read(String query, Object[] params);
void persist(E entity);
void remove(E entity);
}
public class InternalGenericRepository<K, E> implements IInternalGenericRepository<K, E> {
// Injected through DI in Spring
@PersistenceContext
private EntityManager em;
private final Class<E> entityClass;
public List<E> read(String query, Object[] params) {
Query q = em.createQuery(query);
for (int i = 0; i < params.length; i++) {
q.setParameter(i + 1, params[i]);
}
return q.getResultList();
}
public void persist(E entity) {
em.persist(entity);
}
// ...
}
Then, a Repository for a particular entity (for example: Organization) looks like this.
public interface IOrganizationRepository {
List<Organization> organizationByCityName(String city);
void create(Organization o);
}
@Repository
public class OrganizationRepository implements IOrganizationRepository {
@Autowired
IInternalGenericRepository<Long, Organization> internalRepository;
public List<Organization> organizationByCityName(String city) {
Object[] params = new Object[1];
params[0] = city;
return internalRepository.read("select o from Organization o where o.city.name like ?1",
params);
}
@Override
public void create(Organization o) {
internalRepository.persist(o);
}
}
It looks like a good way to implement DDD Repository with JPA and Spring. The OrganizationRepository is then injected in my services layer.
I'd like to have external views to avoid flaws or misconception. What do you think and how could it be improved?
Thanks.
Edit:
- @Autowired on internalRepository - thanks to axtavt for pointing it out.
- read() can be improved
First of all, it wouldn't work, because Spring can't inject EntityManager
into internal object created with new
. So, you have to write something like this:
public class OrganizationRepository implements IOrganizationRepository {
@PersistenceContext
public void setEntityManager(EntityManager em) {
internalRepository.em = em;
}
...
}
Also your read
method looks a bit too generic. It misses some important use cases, such as getSigleResult
and setFirstResult
/setMaxResults
.
Personally I prefer the second article apporach, because using composition you'll end up with having EntityManager
in OrganizationRepository
in order to implement features missed in IInternalGenericRepository
.
来源:https://stackoverflow.com/questions/2239754/approach-for-a-generic-ddd-repository-with-jpa-spring-does-it-look-wrong