SSM 框架實現增刪改查(CRUD)功能代碼詳解
以 “用户管理” 模塊為案例,基於 SSM(Spring+SpringMVC+MyBatis)框架實現用户的新增、查詢(單條 / 列表)、修改、刪除功能,全程遵循 “POJO→Mapper→Service→Controller” 的分層開發邏輯,附完整代碼與配置説明。
一、前期準備:項目結構與依賴
1.1 項目目錄結構
採用 Maven Web 項目結構,各層職責明確:
ssm-crud-demo/├── src/main/java/│ └── com/│ ├── pojo/ # 實體類(對應數據庫表)│ │ └── User.java│ ├── mapper/ # 持久層(MyBatis接口+XML)│ │ ├── UserMapper.java│ │ └── UserMapper.xml│ ├── service/ # 業務邏輯層(接口+實現)│ │ ├── UserService.java│ │ └── UserServiceImpl.java│ └── controller/ # 控制層(SpringMVC)│ └── UserController.java├── src/main/resources/ # 配置文件│ ├── jdbc.properties # 數據庫配置│ ├── mybatis-config.xml # MyBatis全局配置│ ├── spring-mybatis.xml # Spring+MyBatis整合配置│ └── spring-mvc.xml # SpringMVC配置└── src/main/webapp/ # Web資源 └── WEB-INF/ └── web.xml # Web核心配置
1.2 Maven 依賴(pom.xml 核心配置)
需引入 Spring、SpringMVC、MyBatis、MySQL 驅動、連接池等依賴:
<properties> <spring.version>4.3.20.RELEASE</spring.version> <mybatis.version>3.4.6</mybatis.version></properties><dependencies> <!-- Spring核心 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- SpringMVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- MyBatis及整合包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <!-- 數據庫相關 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!-- Web基礎 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- JSON支持(用於接口返回) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.8</version> </dependency></dependencies>
二、第一步:數據庫表與 POJO 實體類
2.1 數據庫表設計(MySQL)
創建tb_user表,存儲用户信息:
CREATE TABLE tb_user ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID', username VARCHAR(50) NOT NULL COMMENT '用户名', age INT COMMENT '年齡', email VARCHAR(100) COMMENT '郵箱', create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間') ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
2.2 POJO 實體類(User.java)
對應tb_user表,屬性與字段一一映射,生成 getter/setter 方法:
package com.pojo;import java.util.Date;public class User { private Integer id; // 對應表中id字段 private String username; // 對應表中username字段 private Integer age; // 對應表中age字段 private String email; // 對應表中email字段 private Date createTime; // 對應表中create_time字段 // 無參構造(MyBatis映射必需) public User() {} // 帶參構造(用於新增/修改時快速創建對象) public User(String username, Integer age, String email) { this.username = username; this.age = age; this.email = email; } // 省略getter和setter方法(需手動生成或用Lombok) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; }}
三、第二步:持久層(MyBatis)實現
持久層負責與數據庫交互,通過 “Mapper 接口 + XML 映射文件” 實現 CRUD 的 SQL 操作。
3.1 Mapper 接口(UserMapper.java)
定義 CRUD 方法,方法名需與 XML 中 SQL 的id一致:
package com.mapper;import com.pojo.User;import org.apache.ibatis.annotations.Param;import java.util.List;public interface UserMapper { // 1. 新增用户 int insertUser(User user); // 2. 根據ID查詢單個用户 User selectUserById(@Param("id") Integer id); // @Param指定參數名,匹配XML中#{id} // 3. 查詢所有用户(無參數) List<User> selectAllUsers(); // 4. 根據ID修改用户(僅修改非空字段) int updateUserById(User user); // 5. 根據ID刪除用户 int deleteUserById(@Param("id") Integer id);}
3.2 Mapper XML 映射文件(UserMapper.xml)
編寫 SQL 語句,綁定 Mapper 接口,實現 “SQL 與代碼分離”:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- namespace必須與Mapper接口全路徑一致 --><mapper namespace="com.mapper.UserMapper"> <!-- 結果集映射:數據庫字段→POJO屬性(解決字段名與屬性名不一致問題,如create_time→createTime) --> <resultMap id="UserResultMap" type="com.pojo.User"> <id column="id" property="id"/> <!-- 主鍵映射 --> <result column="username" property="username"/> <result column="age" property="age"/> <result column="email" property="email"/> <result column="create_time" property="createTime"/> <!-- 字段名與屬性名不一致,需顯式映射 --> </resultMap> <!-- 1. 新增用户:useGeneratedKeys獲取自增主鍵,keyProperty映射到POJO的id屬性 --> <insert id="insertUser" parameterType="com.pojo.User" useGeneratedKeys="true" keyProperty="id"> INSERT INTO tb_user (username, age, email) VALUES (#{username}, #{age}, #{email}) </insert> <!-- 2. 根據ID查詢用户:resultMap引用上面定義的結果集映射 --> <select id="selectUserById" parameterType="int" resultMap="UserResultMap"> SELECT id, username, age, email, create_time FROM tb_user WHERE id = #{id} </select> <!-- 3. 查詢所有用户:返回List<User>,resultMap指定映射規則 --> <select id="selectAllUsers" resultMap="UserResultMap"> SELECT id, username, age, email, create_time FROM tb_user ORDER BY create_time DESC </select> <!-- 4. 根據ID修改用户:<if>標籤實現“非空字段才修改”(避免覆蓋原有值) --> <update id="updateUserById" parameterType="com.pojo.User"> UPDATE tb_user <set> <!-- <set>標籤自動處理逗號,避免SQL語法錯誤 --> <if test="username != null and username != ''">username = #{username},</if> <if test="age != null">age = #{age},</if> <if test="email != null and email != ''">email = #{email},</if> </set> WHERE id = #{id} </update> <!-- 5. 根據ID刪除用户 --> <delete id="deleteUserById" parameterType="int"> DELETE FROM tb_user WHERE id = #{id} </delete></mapper>
四、第三步:業務邏輯層(Service)實現
Service 層封裝業務邏輯,調用 Mapper 接口操作數據庫,同時通過 Spring 的@Transactional管理事務。
4.1 Service 接口(UserService.java)
定義業務方法,與 Mapper 接口方法對應,但可增加業務邏輯(如參數校驗):
package com.service;import com.pojo.User;import java.util.List;public interface UserService { // 1. 新增用户(業務:校驗用户名非空) boolean addUser(User user); // 2. 根據ID查詢用户 User getUserById(Integer id); // 3. 查詢所有用户 List<User> getAllUsers(); // 4. 修改用户(業務:校驗ID非空) boolean updateUser(User user); // 5. 刪除用户(業務:校驗ID存在) boolean deleteUser(Integer id);}
4.2 Service 實現類(UserServiceImpl.java)
注入 Mapper 接口,實現業務方法,添加事務註解:
package com.service;import com.mapper.UserMapper;import com.pojo.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import java.util.List;// @Service標記為Spring管理的Service組件@Servicepublic class UserServiceImpl implements UserService { // 注入MyBatis的Mapper接口(Spring通過MyBatis-Spring自動生成代理對象) @Autowired private UserMapper userMapper; /** * 新增用户:添加事務,若出現異常則回滾;業務校驗用户名非空 */ @Override @Transactional // 聲明式事務:方法執行失敗時自動回滾數據庫操作 public boolean addUser(User user) { // 業務校驗:用户名不能為空 if (user.getUsername() == null || user.getUsername().trim().isEmpty()) { throw new IllegalArgumentException("用户名不能為空!"); } // 調用Mapper接口插入數據,返回影響行數(1為成功,0為失敗) int rows = userMapper.insertUser(user); return rows > 0; } /** * 根據ID查詢用户:查詢操作無需事務 */ @Override public User getUserById(Integer id) { if (id == null || id <= 0) { throw new IllegalArgumentException("用户ID無效!"); } return userMapper.selectUserById(id); } /** * 查詢所有用户 */ @Override public List<User> getAllUsers() { return userMapper.selectAllUsers(); } /** * 修改用户:事務管理,校驗ID非空 */ @Override @Transactional public boolean updateUser(User user) { // 業務校驗:ID不能為空 if (user.getId() == null || user.getId() <= 0) { throw new IllegalArgumentException("用户ID不能為空!"); } // 校驗用户是否存在(避免修改不存在的用户) User existUser = userMapper.selectUserById(user.getId()); if (existUser == null) { throw new RuntimeException("用户不存在,無法修改!"); } // 調用Mapper修改數據 int rows = userMapper.updateUserById(user); return rows > 0; } /** * 刪除用户:事務管理,校驗ID存在 */ @Override @Transactional public boolean deleteUser(Integer id) { if (id == null || id <= 0) { throw new IllegalArgumentException("用户ID無效!"); } // 校驗用户是否存在 User existUser = userMapper.selectUserById(id); if (existUser == null) { throw new RuntimeException("用户不存在,無法刪除!"); } // 調用Mapper刪除數據 int rows = userMapper.deleteUserById(id); return rows > 0; }}
五、第四步:控制層(SpringMVC)實現
Controller 層接收前端請求,調用 Service 層處理業務,返回結果(頁面跳轉或 JSON 數據)。此處以 “返回 JSON 接口” 為例(適配前後端分離或 AJAX 請求)。
5.1 Controller 類(UserController.java)
package com.controller;import com.pojo.User;import com.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import java.util.HashMap;import java.util.List;import java.util.Map;// @Controller標記為SpringMVC的控制器;@ResponseBody表示所有方法返回JSON(無需視圖渲染)@Controller@RequestMapping("/user") // 類級別的URL前綴:所有接口路徑以/user開頭@ResponseBodypublic class UserController { // 注入Service組件 @Autowired private UserService userService; /** * 1. 新增用户:POST請求,接收JSON格式參數 * URL:/user/add * 請求體:{"username":"張三","age":20,"email":"zhangsan@xxx.com"} */ @PostMapping("/add") // 對應HTTP POST請求,路徑為/user/add public Map<String, Object> addUser(@RequestBody User user) { // @RequestBody接收JSON參數 Map<String, Object> result = new HashMap<>(); try { boolean success = userService.addUser(user); if (success) { result.put("code", 200); // 成功狀態碼 result.put("msg", "新增用户成功!"); result.put("data", user.getId()); // 返回新增用户的ID } else { result.put("code", 500); result.put("msg", "新增用户失敗!"); } } catch (IllegalArgumentException e) { // 捕獲業務校驗異常(如用户名空) result.put("code", 400); result.put("msg", e.getMessage()); } catch (Exception e) { // 捕獲其他異常 result.put("code", 500); result.put("msg", "服務器異常:" + e.getMessage()); } return result; } /** * 2. 根據ID查詢用户:GET請求,URL參數傳遞ID * URL:/user/get?id=1 */ @GetMapping("/get") // 對應HTTP GET請求,路徑為/user/get public Map<String, Object> getUserById(@RequestParam("id") Integer id) { // @RequestParam接收URL參數 Map<String, Object> result = new HashMap<>(); try { User user = userService.getUserById(id); if (user != null) { result.put("code", 200); result.put("msg", "查詢成功!"); result.put("data", user); // 返回用户詳情 } else { result.put("code", 404); result.put("msg", "用户不存在!"); } } catch (IllegalArgumentException e</doubaocanvas>