1. DAO 的核心職責
DAO(Data Access Object,數據訪問對象)的主要職責是封裝對數據的訪問邏輯,但它與純粹的數據實體類(如 DTO、POJO)不同,也與 Service 業務邏輯層不同。
DAO 應該做什么?
??數據訪問操作:
-
執行數據庫 CRUD(增刪改查)操作
-
提供查詢接口(如?
findById
,?findAll
,?save
,?delete
) -
處理數據庫事務(通常由?
@Transactional
?管理)
??數據轉換:
-
將數據庫實體(如?
UserEntity
)轉換為業務對象(如?User
) -
處理數據庫特有的數據類型(如?
LocalDateTime
?轉換)
??SQL/HQL/JPQL 管理:
-
編寫 SQL 查詢(如?
@Query
?或 XML 映射) -
處理分頁、排序等數據庫操作
DAO 不應該做什么?
??業務邏輯(屬于 Service 層):
-
例如:計算訂單折扣、驗證用戶權限等
??HTTP 請求/響應處理(屬于 Controller 層):
-
例如:解析?
@RequestBody
、返回?ResponseEntity
??直接暴露數據庫細節:
-
例如:不應該讓上層直接接觸?
Connection
?或?PreparedStatement
2. DAO 與實體類的區別
類別 DAO 類 實體類(Entity/DTO) 用途 封裝數據訪問邏輯 表示數據結構(數據庫表或 API 數據) 是否含邏輯 有簡單的查詢邏輯 通常只是數據容器(純 POJO) 示例 UserRepository.findByName()
User { id, name, email }
Spring 注解 @Repository
@Entity
(JPA)或 無注解(DTO)
3. DAO 的典型實現方式
(1) Spring Data JPA(推薦)
@Repository
public interface UserRepository extends JpaRepository<User, Long> {// 自動實現基本 CRUDList<User> findByName(String name); // 方法名自動解析為 SQL@Query("SELECT u FROM User u WHERE u.email LIKE %?1%")List<User> findByEmailContaining(String email);
}
特點:
-
方法名自動生成查詢(如?
findByName
?→?SELECT * FROM user WHERE name = ?
) -
支持?
@Query
?自定義 SQL/JPQL
(2) MyBatis(SQL 更靈活)
@Repository
public interface UserMapper {@Select("SELECT * FROM user WHERE id = #{id}")User findById(Long id);@Insert("INSERT INTO user(name, email) VALUES(#{name}, #{email})")void insert(User user);
}
特點:
-
直接寫 SQL,適合復雜查詢
-
需配合 XML 或注解映射
?(3) 傳統 JDBC(低層控制)
@Repository
public class UserDao {@Autowiredprivate JdbcTemplate jdbcTemplate;public User findById(Long id) {String sql = "SELECT * FROM user WHERE id = ?";return jdbcTemplate.queryForObject(sql, new UserRowMapper(), id);}
}
特點:
-
完全手動控制 SQL 和執行過程
-
適合需要高度優化的場景
4. DAO 與 Service 的分工
DAO 層
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {List<Order> findByUserId(Long userId);
}
Service 層(業務邏輯)
@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;public BigDecimal calculateTotalPrice(Long userId) {List<Order> orders = orderRepository.findByUserId(userId);return orders.stream().map(Order::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);}
}
關鍵區別:
-
DAO?只關心怎么查數據(
findByUserId
) -
Service?關心業務計算(如匯總訂單金額)
5. 最佳實踐
-
保持 DAO 單一職責:
-
只做數據訪問,不混入業務邏輯。
-
-
使用接口 + 實現:
-
便于替換數據源(如從 MySQL 切到 MongoDB)。
-
-
避免“貧血 DAO”:
-
如果 DAO 只是簡單調用 JPA/MyBatis,可以直接用?
Repository
,無需額外封裝。
-
-
事務管理:
-
事務注解(
@Transactional
)通常放在 Service 層。
-
DAO(Data Access Object)層?在大多數現代Java應用中,特別是使用?MyBatis?或?JPA?框架時,通常對應你所說的?Mapper 類。不過具體實現方式可能略有不同,取決于你使用的技術棧。下面詳細解釋它們的關系和區別:
DAO 層和 Mapper 的關系
概念 | DAO(數據訪問對象) | Mapper(MyBatis 術語) |
---|---|---|
定位 | 數據訪問層,封裝數據庫操作 | MyBatis 對 DAO 的實現方式 |
技術實現 | 可以是接口或類 | 通常是接口(MyBatis)或 XML 映射文件 |
Spring 注解 | @Repository | @Mapper (MyBatis)或?@Repository |
典型方法 | insert(User user) ,?findById(Long id) | @Select ,?@Insert ?等 SQL 注解方法 |
結論:
-
DAO 是一個設計概念,表示數據訪問層。
-
Mapper 是 MyBatis 對 DAO 的具體實現方式(用接口+注解或XML定義SQL)。
-
在 Spring + MyBatis 組合中,Mapper ≈ DAO。
總結
-
DAO 類:負責數據訪問(查詢/存儲),有簡單邏輯(如 SQL 拼接),但不包含業務規則。
-
實體類:純數據結構,無邏輯,用于表示數據庫表或 API 數據。
-
Service 類:處理業務邏輯,調用 DAO 并組合數據。
合理分層能讓代碼更清晰、更易維護!?