阿里一面经典考题:Java项目中,数据库操作应该放在哪一层?别再写在Controller里了
阿里一面经典考题Java项目中数据库操作应该放在哪一层别再写在Controller里了前言后端面试经常被问到架构分层相关问题Java代码在哪一层操作数据库不少初学者分不清层次边界有人把数据库查询写在Controller也有人分不清Service和DAO职责。一旦回答模糊面试官会直接质疑你的工程编码规范、架构认知。本文结合经典后端分层架构讲清楚数据库操作归属层级、每层职责、常见错误写法同时整理面试标准回答看完面试不踩坑。一、标准分层架构后端经典四层架构主流Java Web / SpringBoot项目标准分层自上而下Controller 控制层接收前端请求、参数校验、响应封装Service 业务层编写业务逻辑、事务控制、组装数据DAO / Mapper 持久层数据访问层专门负责和数据库交互数据库MySQL/Oracle等存储数据✅ 核心结论Java中直接操作数据库的代码放在 DAOMapper持久层。二、每层详细职责划清边界1. Controller 控制层职责接收HTTP请求调用Service返回结果。❌ 禁止直接写SQL、调用数据库。Controller只处理请求流转不碰数据库。2. Service 业务层职责业务逻辑编排、事务控制、复杂计算、多个DAO调用组合。✅ Service可以调用DAO但Service内部不直接写SQL、不直接操作数据库。简单理解Service指挥DAO去查库自己不亲手操作数据库。3. DAO / Mapper 持久层Data Access Object职责编写SQL语句XML/注解SQL建立与数据库交互执行查询、新增、更新、删除返回原始数据给ServiceMyBatis项目中就是Mapper接口 Mapper.xmlJPA项目中就是Repository都属于持久层。这是唯一允许直接和数据库打交道的层级。4. 数据库磁盘存储数据接收DAO发送的SQL执行并返回结果。三、标准调用流向前端 → Controller → Service → DAO(Mapper) → MySQL数据返回反向回流MySQL → DAO → Service → Controller → 前端四、举一段规范示例SpringBoot MyBatis// Controller 只调用Service不操作数据库RestControllerpublicclassUserController{AutowiredprivateUserServiceuserService;GetMapping(/user/{id})publicUsergetUser(Longid){returnuserService.getById(id);}}// Service业务逻辑调用Mapper不写SQLServicepublicclassUserServiceImplimplementsUserService{AutowiredprivateUserMapperuserMapper;OverridepublicUsergetById(Longid){returnuserMapper.selectById(id);}}// MapperDAO持久层真正执行数据库操作MapperpublicinterfaceUserMapper{UserselectById(Longid);}五、高频错误写法面试扣分点❌ 错误1Controller 直接注入Mapper操作数据库业务散落在接口层无法复用、难以添加事务代码极度混乱。❌ 错误2在Service中拼接SQL、直接使用JDBC连接数据库破坏分层SQL散落在业务代码中难以维护。❌ 错误3DAO层处理复杂业务判断DAO只做简单CRUD业务判断、多表数据组装统一交给Service。六、面试官延伸追问预判附赠回答思路追问1为什么不能把数据库操作写到Controller答代码无法复用多个接口需要相同查询时重复编码事务只能标注在Service层Controller无法统一管理事务职责混乱不符合单一职责、分层解耦思想不方便统一对数据库操作做日志、缓存统一封装。追问2Service和DAO的分界线是什么DAO单纯CRUD只负责和数据库通信Service业务逻辑、流程控制、事务、多个DAO组合调用。七、面试一句话标准答案在经典四层架构中直接操作数据库的代码放在DAO/Mapper持久层Service业务层调用持久层负责业务逻辑与事务不直接操作数据库Controller只处理请求转发禁止访问数据库。总结分层思想不只是编码规范更是工程化、团队协作的基础。记住核心要点DAO负责操作数据库Service负责业务Controller负责接收请求。面试按这套逻辑作答架构分层问题稳稳拿下。