1. 环境准备与工具选型
在开始构建SpringBoot+MyBatis+MySQL项目前,需要确保开发环境配置正确。我推荐使用IntelliJ IDEA 2023.3+版本作为开发工具,这是目前Java开发者中使用率最高的IDE。社区版虽然免费,但旗舰版提供了更完善的数据库工具和框架支持,对MyBatis的XML映射文件有更好的智能提示。
注意:安装IDEA时建议选择默认的JetBrains Runtime而非系统JDK,这能避免一些奇怪的兼容性问题。我遇到过在macOS上使用系统JDK导致界面卡顿的情况。
开发环境需要:
- JDK 17(LTS版本,SpringBoot 3.x的最低要求)
- MySQL 8.0+(建议使用8.0.28以上版本)
- Maven 3.8.6+(配置阿里云镜像加速依赖下载)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 项目初始化与基础配置
2.1 创建SpringBoot项目
在IDEA中使用Spring Initializr创建项目时,关键依赖选择:
- Spring Web(构建Web应用基础)
- MyBatis Framework(核心ORM支持)
- MySQL Driver(数据库连接)
我习惯在pom.xml中额外添加这些依赖:
xml复制<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
2.2 数据库连接配置
application.yml的配置示例:
yaml复制spring:
datasource:
url: jdbc:mysql://localhost:3306/demo_db?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 20
minimum-idle: 5
idle-timeout: 30000
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
踩坑提醒:MySQL 8.0+必须指定serverTimezone参数,否则会报时区错误。生产环境记得把useSSL设为true并配置证书。
3. MyBatis集成与开发实践
3.1 实体类与Mapper接口
实体类示例(使用Lombok简化代码):
java复制@Data
@TableName("t_user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String password;
@TableField("create_time")
private LocalDateTime createTime;
}
Mapper接口开发技巧:
java复制@Mapper
public interface UserMapper {
// 注解方式简单查询
@Select("SELECT * FROM t_user WHERE id = #{id}")
User selectById(Long id);
// XML方式复杂查询
List<User> selectByCondition(@Param("cond") Map<String, Object> condition);
}
3.2 XML映射文件编写
在resources/mapper目录下创建UserMapper.xml:
xml复制<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.example.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="create_time" property="createTime"/>
</resultMap>
<select id="selectByCondition" resultMap="BaseResultMap">
SELECT * FROM t_user
<where>
<if test="cond.username != null">
AND username LIKE CONCAT('%', #{cond.username}, '%')
</if>
<if test="cond.startTime != null">
AND create_time >= #{cond.startTime}
</if>
</where>
ORDER BY id DESC
</select>
</mapper>
实用技巧:在IDEA中安装MyBatisX插件,可以实现Mapper接口与XML的智能跳转,还能自动生成基础CRUD代码。
4. 业务层与服务开发
4.1 Service层实现
典型服务类结构:
java复制@Service
@RequiredArgsConstructor
public class UserService {
private final UserMapper userMapper;
@Transactional(rollbackFor = Exception.class)
public void createUser(UserCreateDTO dto) {
if (userMapper.existsByUsername(dto.getUsername())) {
throw new BusinessException("用户名已存在");
}
User user = new User();
BeanUtils.copyProperties(dto, user);
user.setPassword(PasswordUtil.encrypt(dto.getPassword()));
userMapper.insert(user);
}
public PageInfo<User> queryPage(UserQuery query, Pageable pageable) {
PageHelper.startPage(pageable.getPageNumber(), pageable.getPageSize());
return PageInfo.of(userMapper.selectByCondition(query.toMap()));
}
}
4.2 事务管理要点
Spring事务的常见问题解决方案:
-
事务不生效检查点:
- 确保方法被Spring代理(调用方必须是Spring注入的Bean)
- 检查异常类型是否匹配rollbackFor
- 确认数据库引擎支持事务(InnoDB支持)
-
事务传播行为选择:
- REQUIRED(默认):当前有事务则加入,没有则新建
- REQUIRES_NEW:总是新建事务
- NESTED:嵌套事务
5. 接口开发与测试
5.1 RESTful接口设计
控制器示例:
java复制@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping
public Result<Void> create(@Valid @RequestBody UserCreateDTO dto) {
userService.createUser(dto);
return Result.success();
}
@GetMapping
public Result<PageInfo<User>> pageQuery(UserQuery query,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
return Result.success(userService.queryPage(query, PageRequest.of(page-1, size)));
}
}
5.2 接口测试技巧
使用IDEA的HTTP Client进行测试(在.http文件中):
code复制### 创建用户
POST http://localhost:8080/api/users
Content-Type: application/json
{
"username": "testuser",
"password": "Test@1234"
}
### 分页查询
GET http://localhost:8080/api/users?page=1&size=10
6. 生产环境注意事项
6.1 性能优化建议
-
MyBatis二级缓存慎用:
- 适合读多写少的场景
- 需要处理缓存一致性
- 建议使用Redis实现分布式缓存
-
SQL优化要点:
java复制@Select({ "SELECT u.*, d.name AS deptName", "FROM t_user u LEFT JOIN t_department d ON u.dept_id = d.id", "WHERE u.status = 1" })- 避免SELECT *
- 复杂查询考虑使用@Results注解定义结果映射
6.2 监控与日志配置
推荐添加的依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.9.1</version>
</dependency>
application.yml增加:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,metrics
metrics:
tags:
application: ${spring.application.name}
logging:
level:
org.springframework.web: INFO
com.example.mapper: DEBUG
7. 常见问题解决方案
7.1 MyBatis典型问题
-
字段值为null不更新问题:
java复制// 在实体类字段上添加注解 @TableField(updateStrategy = FieldStrategy.IGNORED) private String remark; -
分页查询全量返回:
java复制// PageHelper.startPage()后立即执行查询 PageHelper.startPage(1, 10, false); // 第三个参数设为false禁用count查询
7.2 启动时常见异常
-
数据库连接失败:
- 检查MySQL服务是否启动
- 验证用户名密码
- 确认连接URL格式正确
-
MyBatis映射文件找不到:
- 检查mapper-locations配置路径
- 确认XML文件在target/classes对应目录
- 清理并重新编译项目
-
时区问题:
yaml复制url: jdbc:mysql://localhost:3306/db?serverTimezone=Asia/Shanghai
8. 项目结构优化建议
标准项目结构示例:
code复制src/
├── main/
│ ├── java/
│ │ └── com.example/
│ │ ├── config/ # 配置类
│ │ ├── controller/ # 控制器
│ │ ├── entity/ # 实体类
│ │ ├── mapper/ # MyBatis接口
│ │ ├── service/ # 业务逻辑
│ │ ├── util/ # 工具类
│ │ └── Application.java
│ └── resources/
│ ├── mapper/ # XML映射文件
│ ├── static/ # 静态资源
│ ├── templates/ # 模板文件
│ ├── application.yml # 主配置文件
│ └── application-dev.yml # 开发环境配置
└── test/ # 测试代码
在IDEA中设置Mark目录为:
- java目录 -> Sources Root
- resources目录 -> Resources Root
- mapper目录 -> Resources Root(重要!)
9. 进阶开发技巧
9.1 MyBatis-Plus集成
添加依赖:
xml复制<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
</dependency>
Mapper接口改造:
java复制public interface UserMapper extends BaseMapper<User> {
// 继承后自动获得CRUD方法
@Select("SELECT * FROM t_user WHERE dept_id = #{deptId}")
List<User> selectByDept(Long deptId);
}
9.2 多数据源配置
- 添加配置:
yaml复制spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/db1
username: root
password: 123456
secondary:
url: jdbc:mysql://localhost:3306/db2
username: root
password: 123456
- 配置类示例:
java复制@Configuration
@MapperScan(basePackages = "com.example.mapper.primary",
sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory primarySqlSessionFactory(
@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/primary/*.xml"));
return bean.getObject();
}
}
10. 部署与运维
10.1 打包与运行
Maven打包命令:
bash复制mvn clean package -DskipTests
运行JAR包:
bash复制java -jar target/demo-0.0.1-SNAPSHOT.jar \
--spring.profiles.active=prod \
--server.port=8081
10.2 数据库迁移方案
- Flyway集成:
xml复制<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
- 创建迁移脚本:
code复制resources/
└── db/
└── migration/
├── V1__Create_user_table.sql
└── V2__Add_user_indexes.sql
在实际项目中,我发现合理使用MyBatis的动态SQL能大幅减少重复代码量,但也要注意避免过度复杂的SQL片段影响可维护性。对于新项目,建议直接从MyBatis-Plus起步,它能显著提升开发效率。
