获取比你实际所需要的更多数据并不好,此外,当您不打算修改实体时,获取实体(通过在持久化上下文中加入的方式获取实体)是最常见的错误之一,它隐含性能损失。
因此,使用DTO可允许我们仅提取所需的数据。在这个应用程序中,我们依赖 @SqlResultSetMapping和EntityManager来实现。
假设三个实体TopCategory和MiddleCategory是一对多关系,MiddleCategory和BottomCategory 是一对多关系,现在需要分别从TopCategory、MiddleCategory和BottomCategory 中提取各自的namet、namem和nameb字段组成CategoryDto:
TopCategory代码如下,我们使用了注释@SqlResultSetMapping构造获得CategoryDto的字段,TopCategory是父级根实体(DDD聚合中的实体根)。
@SqlResultSetMapping(name = "CategoryDtoMapping", classes = { @ConstructorResult( targetClass = CategoryDto.class, columns = { @ColumnResult(name = "namet"), @ColumnResult(name = "namem"), @ColumnResult(name = "nameb") } )} ) @Entity @Table(name = "top_category") public class TopCategory implements Serializable {
private static final long serialVersionUID = 1L;
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "topCategory", orphanRemoval = true) private List<MiddleCategory> middleCategories = new ArrayList<>();
// helper methods public void addMiddleCategory(MiddleCategory middleCategory) { middleCategories.add(middleCategory); middleCategory.setTopCategory(this); }
public void removeMiddleCategory(MiddleCategory middleCategory) { middleCategory.setTopCategory(null); middleCategories.remove(middleCategory); }
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public List<MiddleCategory> getMiddleCategories() { return middleCategories; }
public void setMiddleCategories(List<MiddleCategory> middleCategories) { this.middleCategories = middleCategories; }
}
|
然后实现自己的DAO仓储,在其中调用EntityManager的createNativeQuery,其他方式点击标签#DTO可看到更多EntityManager调用方式。
@Repository @Transactional public class Dao<T, ID extends Serializable> implements GenericDao<T, ID> {
@PersistenceContext private EntityManager entityManager;
@Override public <S extends T> S persist(S entity) { Objects.requireNonNull(entity, "Cannot persist a null entity"); entityManager.persist(entity);
return entity; }
@Transactional(readOnly=true) public List<CategoryDto> fetchCategories() { Query query = entityManager.createNativeQuery( "SELECT t.name AS namet, m.name AS namem, b.name AS nameb " + "FROM middle_category m " + "INNER JOIN top_category t ON t.id=m.top_category_id " + "INNER JOIN bottom_category b ON m.id=b.middle_category_id", "CategoryDtoMapping"); List<CategoryDto> result = query.getResultList();
return result; }
protected EntityManager getEntityManager() { return entityManager; } }
|
下面是Dao客户端Service的调用方式:
@Service public class CategoryService {
private final Dao dao;
public CategoryService(Dao dao) { this.dao = dao; }
public List<CategoryDto> fetchCategories() { return dao.fetchCategories(); } }
|
源代码可以在这里找到