You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DDD架构下自定义仓库查询参数的分层选择及repository方法DTO入参合理性咨询

关于DDD中Repository查询方法参数的设计建议

Great question—this is a super common sticking point when working through DDD repository design, so let’s break this down clearly.

First, let’s clear up a key misunderstanding: you’re not actually dealing with a traditional DTO here. The object you’re thinking of (PersonDTO/PersonResearchFilters) isn’t meant for data transfer across layers—it’s a query parameter object that encapsulates domain-specific search criteria. That changes everything.

The Repository interface lives in the Domain layer because it defines the contract for how domain models are retrieved—this contract should be entirely domain-focused. If you forced this query object to live in the Application layer, you’d create a backward dependency: the Domain layer would depend on the Application layer, which violates DDD’s dependency rule (inner layers shouldn’t depend on outer layers).

Your search criteria (firstName, birthDate ranges, etc.) are directly tied to the Person domain model—they’re part of the domain’s query language. So wrapping them in a dedicated object (let’s call it PersonResearchFilters, not DTO) makes perfect sense as a Domain layer component.

Better design options to consider

Rename your PersonDTO to PersonResearchFilters and place it in the Domain layer. This makes its purpose explicit and aligns it with domain responsibilities. Example:

// Domain layer
public class PersonResearchFilters {
    private String firstName;
    private String lastName;
    private Date birthDateBefore;
    private Date birthDateAfter;
    private Date inscriptionDateBefore;
    private Date inscriptionDateAfter;
    
    // Getters, constructor, or builder...
}

// Domain layer Repository interface
public interface PersonRepository {
    List<Person> searchByParams(PersonResearchFilters filters);
}

This keeps your Repository interface clean, maintains Domain layer independence, and makes the search intent clear.

2. Avoid DTO confusion entirely

If you’re worried about mixing up query objects with actual DTOs (which belong in the Application layer for cross-layer data transfer), remember:

  • DTOs are for moving data between layers (e.g., sending a PersonResponseDTO from Application to Presentation).
  • Query parameter objects are for defining domain query contracts—they belong where the Repository interface lives (Domain layer).

3. Optional: Use a Builder for the Filters

To make constructing filter objects more readable, add a Builder pattern to PersonResearchFilters:

public class PersonResearchFilters {
    // Fields...
    
    private PersonResearchFilters(Builder builder) {
        this.firstName = builder.firstName;
        // Initialize other fields...
    }
    
    public static Builder builder() {
        return new Builder();
    }
    
    public static class Builder {
        private String firstName;
        // Builder fields...
        
        public Builder firstName(String firstName) {
            this.firstName = firstName;
            return this;
        }
        
        // Other setter methods...
        
        public PersonResearchFilters build() {
            return new PersonResearchFilters(this);
        }
    }
}

Usage becomes much cleaner:

PersonResearchFilters filters = PersonResearchFilters.builder()
    .firstName("Alice")
    .birthDateBefore(new Date())
    .build();
List<Person> results = personRepository.searchByParams(filters);

What to avoid

  • Don’t pass an Application-layer DTO to a Domain-layer Repository method. This creates a harmful dependency and pollutes the Domain layer with concerns that don’t belong there.
  • Don’t use a long list of individual parameters (e.g., searchByParams(String firstName, String lastName, ...)). This makes the method signature unwieldy and hard to maintain as you add more filters.

内容的提问来源于stack exchange,提问作者ihebiheb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 16:57:47