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

Java中Service与DAO类调用及设计规范咨询

Hey there! Let's walk through your three questions with practical, architecture-aligned answers:

1. Should JiraService call DAOs directly or via their corresponding Service classes?

You should always call Service classes instead of DAOs directly from JiraService. Here's why:

  • Layered architecture principles: Service classes are designed to encapsulate business logic, handle transactions, and coordinate data operations. DAOs are strictly for raw data access (CRUD) without any business context.
  • Transaction management: When you need to save customer, issue, and project records atomically (all succeed or all fail), you can annotate the Service method with @Transactional (if using Spring) to handle this. If you call DAOs directly from JiraService, managing transactions across multiple DAO calls becomes messy and error-prone.
  • Single responsibility: JiraService should focus solely on interacting with the JIRA API. Let CustomerService, IssueService, and ProjectService handle their respective data persistence logic. For example:
    @Service
    public class JiraService {
        private final CustomerService customerService;
        private final IssueService issueService;
        private final ProjectService projectService;
    
        // Constructor injection
        public JiraService(CustomerService cs, IssueService is, ProjectService ps) {
            this.customerService = cs;
            this.issueService = is;
            this.projectService = ps;
        }
    
        public void createJiraIssueAndLinkEntities(Customer customer, JiraIssueResponse jiraResponse) {
            // 1. Save customer via CustomerService
            Long customerId = customerService.saveCustomer(customer);
            // 2. Save issue data via IssueService
            String issueId = issueService.saveIssue(jiraResponse);
            // 3. Link both to project via ProjectService (all in one transaction if Service method is @Transactional)
            projectService.linkCustomerAndIssue(customerId, issueId);
        }
    }
    
2. Is it best practice to include all query variants in DAOs if they're supposed to only handle basic CRUD?

DAOs should handle all data access operations—including query variants—so long as those queries don't include business logic. Here's how to balance it:

  • Basic CRUD is the foundation, but query variants (like "find projects by customer name", "find projects by issue ID", or combined filters) are still raw data retrieval tasks, which belong in DAOs.
  • Avoid bloating DAOs with duplicate logic: Use patterns like Query Builders or Spring Data JPA Specifications to create dynamic queries instead of writing dozens of similar methods. For example, instead of findByCustomerName, findByIssueId, findByCustomerNameAndIssueId, you could have a single findByCriteria(Criteria criteria) method that builds the query dynamically.
  • Draw the line at business logic: If a query requires applying business rules (e.g., "find all projects for VIP customers"), handle the VIP check in the Service layer first, then pass the filtered customer IDs to the DAO. The DAO shouldn't know what a "VIP customer" is—that's business logic, not data access.
3. How can a DAO call methods from another DAO? (e.g., get customer ID via CustomerDAO first, then query Project table)

DAOs should never call other DAOs directly—this creates tight coupling and violates the single responsibility principle. Instead, move this coordination logic to the Service layer. Here's how to implement your example:

  1. Inject both CustomerDAO and ProjectDAO into a ProjectService.
  2. Write a Service method that first fetches the customer ID from CustomerDAO, then uses that ID to query the Project table via ProjectDAO.

Example code:

@Service
public class ProjectService {
    private final CustomerDAO customerDAO;
    private final ProjectDAO projectDAO;

    public ProjectService(CustomerDAO customerDAO, ProjectDAO projectDAO) {
        this.customerDAO = customerDAO;
        this.projectDAO = projectDAO;
    }

    public List<Project> getProjectsByCustomerName(String customerName) {
        // First get the customer via CustomerDAO
        Customer customer = customerDAO.findByCustomerName(customerName);
        if (customer == null) {
            return Collections.emptyList();
        }
        // Then use the customer ID to query projects
        return projectDAO.findByCustomerId(customer.getId());
    }
}

This way, each DAO only handles operations for its own table, and the Service layer takes care of orchestrating multiple DAOs to fulfill the business need.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:22:54