项目结构
Mybatis-demo
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com.example.demo
│ │ │ ├── common // 公共模块:存放统一返回结果 Result 类
│ │ │ ├── config // 配置类:MyBatis 映射配置、全局异常处理
│ │ │ ├── controller // 控制层:接受请求,调用 Service
│ │ │ ├── entity // 实体层:与数据库表一一对应的 Java 对象
│ │ │ ├── mapper // 持久层:MyBatis 接口文件
│ │ │ └── service // 业务层:接口与实现类 (impl)
│ │ │ └── impl
│ │ └── resources
│ │ ├── mapper // 存放 MyBatis 的 XML 映射文件
│ │ ├── application.yml // 核心配置文件
│ │ └── static/templates // 静态资源/模板(前后端分离项目通常为空)
│ └── test // 单元测试
├── pom.xml // Maven 依赖管理
└── .gitignore // 忽略提交的文件
1 数据库准备 SQL
-- 创建用户表
CREATE TABLE user (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100),
age INT
);
-- 创建订单表
CREATE TABLE `order` (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
order_no VARCHAR(50) NOT NULL,
amount DECIMAL(10,2),
user_id BIGINT,
FOREIGN KEY (user_id) REFERENCES user(id)
);
-- 插入示例数据
INSERT INTO user (username, email, age) VALUES
('张三', 'zhangsan@example.com', 25),
('李四', 'lisi@example.com', 30),
('王五', 'wangwu@example.com', 28);
INSERT INTO `order` (order_no, amount, user_id) VALUES
('ORD001', 99.99, 1),
('ORD002', 199.99, 2),
('ORD003', 299.99, 1);
2 项目构建
创建选择maven ,JDK 17
3 项目依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version> <relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-mybatis-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-mybatis-demo</name>
<description>Spring Boot 3 + MyBatis Quick Start</description>
<properties>
<java.version>17</java.version> <mybatis.version>3.0.3</mybatis.version> </properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
4 yml文件关键配置
application.yml
spring:
application:
name: Mybatis-demo
datasource:
url: jdbc:mysql://localhost:3306/mybatisdemo?useSSL=false&serverTimezone=UTC
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: org.example.mybatisdemo.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
5 创建实体类
User.java
package org.example.mybatisdemo.entity;
import lombok.Data;
@Data
public class User {
private Long id;
private String orderNo;
private Double amount;
private Long userId;
// 关键:为了显示多表联查的结果,添加这个字段
private String username;
}
Order.java
package org.example.mybatisdemo.entity;
import lombok.Data;
@Data
public class Order {
private Long id;
private String orderNo;
private Double amount;
private Long userId;
// 关键:为了显示多表联查的结果,添加这个字段
private String username;
}
6 Mapper 接口与 XML (mapper 包)
实现mapper层 数据访问接口
UserMapper .java
package org.example.mybatisdemo.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.example.mybatisdemo.entity.User;
import java.util.List;
@Mapper
public interface UserMapper {
// 查询所有用户
List<User> findAll();
// 根据ID查询用户
User findById(Long id);
// 添加用户
int insert(User user);
// 更新用户
int update(User user);
// 删除用户
int delete(Long id);
}
OrderMapper.java
package org.example.mybatisdemo.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.example.mybatisdemo.entity.Order;
import java.util.List;
@Mapper
public interface OrderMapper {
// 查询所有订单
List<Order> findAll();
// 根据ID查询订单
Order findById(Long id);
// 添加订单
int insert(Order order);
// 更新订单
int update(Order order);
// 删除订单
int delete(Long id);
}
在src/main/resources/mapper/UserMapper.xml和 OrderMapper.xml
<?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">
<mapper namespace="org.example.mybatisdemo.mapper.UserMapper">
<resultMap id="BaseResultMap" type="org.example.mybatisdemo.entity.User">
<id column="id" property="id" />
<result column="username" property="username" />
<result column="email" property="email" />
<result column="age" property="age" />
</resultMap>
<sql id="Base_Column_List">
id, username, email, age
</sql>
<select id="findAll" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM user
</select>
<select id="findById" parameterType="java.lang.Long" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM user
WHERE id = #{id}
</select>
<insert id="insert" parameterType="org.example.mybatisdemo.entity.User">
INSERT INTO user (username, email, age)
VALUES (#{username}, #{email}, #{age})
</insert>
<update id="update" parameterType="org.example.mybatisdemo.entity.User">
UPDATE user
SET
<if test="username != null">username = #{username},</if>
<if test="email != null">email = #{email},</if>
<if test="age != null">age = #{age}</if>
WHERE id = #{id}
</update>
<delete id="delete" parameterType="java.lang.Long">
DELETE FROM user WHERE id = #{id}
</delete>
</mapper>
OrderMapper.xml
<?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">
<mapper namespace="org.example.mybatisdemo.mapper.OrderMapper">
<resultMap id="BaseResultMap" type="org.example.mybatisdemo.entity.Order">
<id column="id" property="id" />
<result column="order_no" property="orderNo" />
<result column="amount" property="amount" />
<result column="user_id" property="userId" />
<result column="username" property="username" />
</resultMap>
<sql id="Base_Column_List">
id, order_no, amount, user_id
</sql>
<select id="findAll" resultMap="BaseResultMap">
SELECT o.id, o.order_no, o.amount, o.user_id, u.username
FROM `order` o
LEFT JOIN user u ON o.user_id = u.id
</select>
<select id="findById" parameterType="java.lang.Long" resultMap="BaseResultMap">
SELECT o.id, o.order_no, o.amount, o.user_id, u.username
FROM `order` o
LEFT JOIN user u ON o.user_id = u.id
WHERE o.id = #{id}
</select>
<insert id="insert" parameterType="org.example.mybatisdemo.entity.Order">
INSERT INTO `order` (order_no, amount, user_id)
VALUES (#{orderNo}, #{amount}, #{userId})
</insert>
<update id="update" parameterType="org.example.mybatisdemo.entity.Order">
UPDATE `order`
SET
<if test="orderNo != null">order_no = #{orderNo},</if>
<if test="amount != null">amount = #{amount},</if>
<if test="userId != null">user_id = #{userId}</if>
WHERE id = #{id}
</update>
<delete id="delete" parameterType="java.lang.Long">
DELETE FROM `order` WHERE id = #{id}
</delete>
</mapper>
7 Service层
UserService.java
package org.example.mybatisdemo.service;
import org.example.mybatisdemo.entity.User;
import java.util.List;
/*
* 接口不添加@Service注解,只定义方法契约
* */
public interface UserService {
List<User> findAll();
User findById(Long id);
int insert(User user);
int update(User user);
int delete(Long id);
}
OrderService.java
package org.example.mybatisdemo.service;
import org.example.mybatisdemo.entity.Order;
import java.util.List;
public interface OrderService {
List<Order> findAll();
Order findById(Long id);
int insert(Order order);
int update(Order order);
int delete(Long id);
}
创建service.impl包
- 接口-实现分离的模式。让我总结一下Service层接口-实现分离的好处:
- 符合面向接口编程原则:Controller依赖于Service接口而不是具体实现,符合依赖倒置原则。
- 便于单元测试:可以通过Mock接口来测试Controller层,而不需要依赖具体的实现。
- 便于扩展:如果需要提供不同的实现,只需要创建新的实现类即可。
- 便于AOP代理:Spring的事务管理等AOP功能通常需要基于接口进行代理。
- 解耦合:接口定义契约,实现类提供具体实现,降低了系统各部分之间的耦合度
UserServiceImpl.java
package org.example.mybatisdemo.service.impl;
import org.example.mybatisdemo.entity.User;
import org.example.mybatisdemo.mapper.UserMapper;
import org.example.mybatisdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.findAll();
}
@Override
public User findById(Long id) {
return userMapper.findById(id);
}
@Override
public int insert(User user) {
return userMapper.insert(user);
}
@Override
public int update(User user) {
return userMapper.update(user);
}
@Override
public int delete(Long id) {
return userMapper.delete(id);
}
}
OrderServiceImpl.java
package org.example.mybatisdemo.service.impl;
import org.example.mybatisdemo.entity.Order;
import org.example.mybatisdemo.mapper.OrderMapper;
import org.example.mybatisdemo.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Override
public List<Order> findAll() {
return orderMapper.findAll();
}
@Override
public Order findById(Long id) {
return orderMapper.findById(id);
}
@Override
public int insert(Order order) {
return orderMapper.insert(order);
}
@Override
public int update(Order order) {
return orderMapper.update(order);
}
@Override
public int delete(Long id) {
return orderMapper.delete(id);
}
}
8 Controller层
控制层 遵循 RESTful API 设计规范:
@PathVariable 用于获取 URL 路径上的参数(如 /user/1)
@RequestBody 用于接收 JSON 格式的请求体(常用于新增、修改)
AjaxResult.java: 用于统一返回格式
package org.example.mybatisdemo.common;
import java.util.HashMap;
/**
* AjaxResult
* 用于统一返回格式 / Unified response format
*/
public class AjaxResult extends HashMap<String, Object> {
public AjaxResult() {}
// 成功(无数据)/ success without data
public static AjaxResult success() {
AjaxResult r = new AjaxResult();
r.put("code", 200);
r.put("msg", "success");
return r;
}
// 成功(带数据)/ success with data
public static AjaxResult success(Object data) {
AjaxResult r = new AjaxResult();
r.put("code", 200);
r.put("msg", "success");
r.put("data", data);
return r;
}
// 错误 / error
public static AjaxResult error(String msg) {
AjaxResult r = new AjaxResult();
r.put("code", 500);
r.put("msg", msg);
return r;
}
}
UserController.java
package org.example.mybatisdemo.controller;
import org.example.mybatisdemo.entity.User;
import org.example.mybatisdemo.service.UserService;
import org.example.mybatisdemo.common.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/list")
public AjaxResult list() {
List<User> users = userService.findAll();
return AjaxResult.success(users);
}
@GetMapping("/{id}")
public AjaxResult getById(@PathVariable Long id) {
User user = userService.findById(id);
return AjaxResult.success(user);
}
@PostMapping
public AjaxResult add(@RequestBody User user) {
int result = userService.insert(user);
if (result > 0) {
return AjaxResult.success("添加成功");
} else {
return AjaxResult.error("添加失败");
}
}
@PutMapping
public AjaxResult edit(@RequestBody User user) {
int result = userService.update(user);
if (result > 0) {
return AjaxResult.success("更新成功");
} else {
return AjaxResult.error("更新失败");
}
}
@DeleteMapping("/{id}")
public AjaxResult delete(@PathVariable Long id) {
int result = userService.delete(id);
if (result > 0) {
return AjaxResult.success("删除成功");
} else {
return AjaxResult.error("删除失败");
}
}
}
OrderController.java
package org.example.mybatisdemo.controller;
import org.example.mybatisdemo.entity.Order;
import org.example.mybatisdemo.service.OrderService;
import org.example.mybatisdemo.common.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/list")
public AjaxResult list() {
List<Order> orders = orderService.findAll();
return AjaxResult.success(orders);
}
@GetMapping("/{id}")
public AjaxResult getById(@PathVariable Long id) {
Order order = orderService.findById(id);
return AjaxResult.success(order);
}
@PostMapping
public AjaxResult add(@RequestBody Order order) {
int result = orderService.insert(order);
if (result > 0) {
return AjaxResult.success("添加成功");
} else {
return AjaxResult.error("添加失败");
}
}
@PutMapping
public AjaxResult edit(@RequestBody Order order) {
int result = orderService.update(order);
if (result > 0) {
return AjaxResult.success("更新成功");
} else {
return AjaxResult.error("更新失败");
}
}
@DeleteMapping("/{id}")
public AjaxResult delete(@PathVariable Long id) {
int result = orderService.delete(id);
if (result > 0) {
return AjaxResult.success("删除成功");
} else {
return AjaxResult.error("删除失败");
}
}
}
10 启动项目
端口号8080
接下来可以去postman测试接口了