1. 项目概述
作为一名常年使用IDEA进行Java开发的工程师,我经常需要快速搭建SpringBoot+MyBatis+Mysql的技术栈项目。这种组合在企业级开发中非常普遍,但新手在搭建过程中往往会遇到各种配置问题。今天我就来分享一套经过实战检验的标准搭建流程,包含从环境准备到接口测试的完整步骤。
这个技术栈的优势在于:SpringBoot提供了开箱即用的项目骨架和自动配置,MyBatis作为轻量级ORM框架简化了数据库操作,而Mysql则是互联网公司最常用的关系型数据库。三者结合既能快速开发,又能保证系统性能。下面我会详细演示如何在IDEA中从零开始搭建这个工程。
2. 环境准备与工具配置
2.1 开发环境要求
在开始之前,请确保你的开发环境满足以下要求:
- JDK 1.8或以上版本(推荐使用JDK 11)
- IntelliJ IDEA 2021.3或更高版本(社区版或旗舰版均可)
- Maven 3.6.3或以上版本
- MySQL 5.7或8.0版本
提示:虽然SpringBoot 2.7.x支持JDK 17,但考虑到企业生产环境普遍仍在使用JDK 8,建议初学者先用JDK 8进行开发。
2.2 IDEA基础配置
-
安装必要的插件:
- Lombok Plugin(必装,简化实体类编写)
- MyBatisX(可选,提供MyBatis映射文件与接口的跳转)
- Database Tools and SQL(IDEA自带,用于连接数据库)
-
配置Maven:
bash复制# 检查Maven版本 mvn -v建议修改Maven的settings.xml文件,配置阿里云镜像加速依赖下载:
xml复制<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>
3. 项目初始化
3.1 创建SpringBoot项目
- 在IDEA中选择File -> New -> Project
- 选择Spring Initializr,配置以下参数:
- Project SDK: 你的JDK版本
- Initializr Service URL: 默认(https://start.spring.io)
- 填写Group(如com.example)和Artifact(如demo)
- Type: Maven
- Language: Java
- Packaging: Jar
- Java Version: 8
- 在Dependencies中选择:
- Spring Web(构建web应用)
- MyBatis Framework
- MySQL Driver
- Lombok(简化代码)
3.2 项目结构解析
创建完成后,标准项目结构如下:
code复制demo
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── DemoApplication.java
│ │ │ ├── controller
│ │ │ ├── service
│ │ │ ├── mapper
│ │ │ └── entity
│ │ └── resources
│ │ ├── application.properties
│ │ └── mapper
│ └── test
└── pom.xml
3.3 关键配置文件
- application.properties配置:
properties复制# 应用端口
server.port=8080
# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/demo_db?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis配置
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.demo.entity
4. MyBatis集成与数据库操作
4.1 数据库准备
- 创建数据库和表:
sql复制CREATE DATABASE demo_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE demo_db;
CREATE TABLE user (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(100) NOT NULL,
email VARCHAR(100),
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
4.2 实体类与Mapper
- 创建User实体类:
java复制@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String username;
private String password;
private String email;
private Date createTime;
}
- 创建UserMapper接口:
java复制@Mapper
public interface UserMapper {
@Insert("INSERT INTO user(username, password, email) VALUES(#{username}, #{password}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Select("SELECT * FROM user WHERE id = #{id}")
User selectById(Long id);
@Update("UPDATE user SET username=#{username}, email=#{email} WHERE id=#{id}")
int update(User user);
@Delete("DELETE FROM user WHERE id=#{id}")
int delete(Long id);
}
4.3 XML映射文件配置
在resources/mapper目录下创建UserMapper.xml:
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="com.example.demo.mapper.UserMapper">
<resultMap id="userResultMap" type="User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
<result property="createTime" column="create_time"/>
</resultMap>
<select id="selectAll" resultMap="userResultMap">
SELECT * FROM user
</select>
</mapper>
5. 业务层与控制器实现
5.1 Service层实现
创建UserService接口和实现类:
java复制public interface UserService {
User getUserById(Long id);
List<User> getAllUsers();
int addUser(User user);
int updateUser(User user);
int deleteUser(Long id);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User getUserById(Long id) {
return userMapper.selectById(id);
}
@Override
public List<User> getAllUsers() {
return userMapper.selectAll();
}
@Override
public int addUser(User user) {
return userMapper.insert(user);
}
@Override
public int updateUser(User user) {
return userMapper.update(user);
}
@Override
public int deleteUser(Long id) {
return userMapper.delete(id);
}
}
5.2 Controller层实现
创建UserController:
java复制@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.getAllUsers();
return ResponseEntity.ok(users);
}
@PostMapping
public ResponseEntity<Void> addUser(@RequestBody User user) {
userService.addUser(user);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
@PutMapping
public ResponseEntity<Void> updateUser(@RequestBody User user) {
userService.updateUser(user);
return ResponseEntity.ok().build();
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}
6. 测试与调试
6.1 单元测试
创建UserServiceTest测试类:
java复制@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testCRUD() {
User user = new User();
user.setUsername("testUser");
user.setPassword("123456");
user.setEmail("test@example.com");
// 测试插入
int result = userService.addUser(user);
assertEquals(1, result);
assertNotNull(user.getId());
// 测试查询
User dbUser = userService.getUserById(user.getId());
assertEquals(user.getUsername(), dbUser.getUsername());
// 测试更新
user.setEmail("updated@example.com");
int updateResult = userService.updateUser(user);
assertEquals(1, updateResult);
// 测试删除
int deleteResult = userService.deleteUser(user.getId());
assertEquals(1, deleteResult);
}
}
6.2 API测试
使用Postman或curl测试API:
bash复制# 创建用户
curl -X POST -H "Content-Type: application/json" -d '{
"username": "test",
"password": "123456",
"email": "test@example.com"
}' http://localhost:8080/api/users
# 查询用户
curl http://localhost:8080/api/users/1
# 查询所有用户
curl http://localhost:8080/api/users
# 更新用户
curl -X PUT -H "Content-Type: application/json" -d '{
"id": 1,
"username": "updated",
"email": "updated@example.com"
}' http://localhost:8080/api/users
# 删除用户
curl -X DELETE http://localhost:8080/api/users/1
7. 常见问题与解决方案
7.1 数据库连接问题
问题现象:启动时报错"Access denied for user 'root'@'localhost'"
解决方案:
- 检查application.properties中的用户名密码是否正确
- 确认MySQL服务已启动
- 检查MySQL用户权限:
sql复制GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY 'yourpassword';
FLUSH PRIVILEGES;
7.2 MyBatis映射问题
问题现象:查询返回null或报错"Invalid bound statement (not found)"
解决方案:
- 检查mapper.xml文件是否放在resources/mapper目录下
- 确认mapper.xml中的namespace与Mapper接口全限定名一致
- 在启动类添加@MapperScan注解:
java复制@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
7.3 时区问题
问题现象:数据库时间与Java时间不一致
解决方案:
- 在JDBC URL中添加时区参数:
properties复制spring.datasource.url=jdbc:mysql://localhost:3306/demo_db?useSSL=false&serverTimezone=Asia/Shanghai
- 在MySQL中设置时区:
sql复制SET GLOBAL time_zone = '+8:00';
8. 高级配置与优化
8.1 分页插件集成
添加MyBatis分页插件PageHelper:
- 在pom.xml中添加依赖:
xml复制<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
- 在application.properties中配置:
properties复制# PageHelper配置
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
- 使用示例:
java复制@GetMapping("/page")
public ResponseEntity<PageInfo<User>> getUsersByPage(
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<User> users = userService.getAllUsers();
PageInfo<User> pageInfo = new PageInfo<>(users);
return ResponseEntity.ok(pageInfo);
}
8.2 多数据源配置
当需要连接多个数据库时:
- 配置多个数据源:
properties复制# 主数据源
spring.datasource.primary.url=jdbc:mysql://localhost:3306/db1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
# 次数据源
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/db2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
- 创建数据源配置类:
java复制@Configuration
public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
- 为每个数据源配置独立的SqlSessionFactory:
java复制@Configuration
@MapperScan(basePackages = "com.example.demo.mapper.primary", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryMyBatisConfig {
@Autowired
@Qualifier("primaryDataSource")
private DataSource dataSource;
@Bean
public SqlSessionFactory primarySqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath:mapper/primary/*.xml"));
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate primarySqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(primarySqlSessionFactory());
}
}
8.3 事务管理
Spring Boot默认已经配置了事务管理,只需在Service方法上添加@Transactional注解:
java复制@Service
public class UserServiceImpl implements UserService {
@Transactional
@Override
public int updateUser(User user) {
// 业务逻辑
return userMapper.update(user);
}
}
对于需要更精细控制的事务:
java复制@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,
timeout = 30,
rollbackFor = Exception.class
)
public void complexBusiness() {
// 复杂业务逻辑
}
9. 项目打包与部署
9.1 Maven打包
- 添加打包插件:
xml复制<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
- 执行打包命令:
bash复制mvn clean package
打包完成后会在target目录生成demo-0.0.1-SNAPSHOT.jar文件。
9.2 运行项目
- 直接运行:
bash复制java -jar demo-0.0.1-SNAPSHOT.jar
- 指定配置文件运行:
bash复制java -jar demo-0.0.1-SNAPSHOT.jar --spring.config.location=file:/path/to/application.properties
- 生产环境推荐使用nohup后台运行:
bash复制nohup java -jar demo-0.0.1-SNAPSHOT.jar > app.log 2>&1 &
10. 性能优化建议
10.1 连接池配置
默认使用HikariCP连接池,建议调整以下参数:
properties复制# 连接池配置
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
10.2 MyBatis二级缓存
启用MyBatis二级缓存:
- 在mapper.xml中添加:
xml复制<mapper namespace="com.example.demo.mapper.UserMapper">
<cache/>
...
</mapper>
- 实体类实现Serializable接口:
java复制public class User implements Serializable {
// ...
}
- 在application.properties中配置:
properties复制mybatis.configuration.cache-enabled=true
10.3 SQL优化
- 使用@SelectProvider动态SQL:
java复制@SelectProvider(type = UserSqlProvider.class, method = "selectByCondition")
List<User> selectByCondition(UserCondition condition);
- 创建SqlProvider类:
java复制public class UserSqlProvider {
public String selectByCondition(UserCondition condition) {
return new SQL() {{
SELECT("*");
FROM("user");
if (condition.getUsername() != null) {
WHERE("username like #{username} || '%'");
}
if (condition.getEmail() != null) {
WHERE("email = #{email}");
}
ORDER_BY("create_time desc");
}}.toString();
}
}
在实际项目中,我发现合理使用MyBatis的动态SQL可以显著减少数据库查询次数。特别是在处理复杂查询条件时,相比在Java代码中拼接SQL字符串,这种方式更加安全和高效。
