Java中Service与DAO类调用及设计规范咨询
Hey there! Let's walk through your three questions with practical, architecture-aligned answers:
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 fromJiraService, managing transactions across multiple DAO calls becomes messy and error-prone. - Single responsibility:
JiraServiceshould focus solely on interacting with the JIRA API. LetCustomerService,IssueService, andProjectServicehandle 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); } }
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 singlefindByCriteria(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.
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:
- Inject both
CustomerDAOandProjectDAOinto aProjectService. - Write a Service method that first fetches the customer ID from
CustomerDAO, then uses that ID to query the Project table viaProjectDAO.
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

