CREATE TABLE user (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT
);
spring和mybatis交互的时间线如下:
1.entity
java复制代码
public class user{
private Long id;
private Integer age;
private String name;
//构造函数
public user(String name,Integer age){//全参构造函数
this.name=name;
this.age=age;
}
public user(){}//无参构造函数
//getter和setter
public Long GetId(){return id;}
public void SetId(Long id){this.id=id;}
public Integer GetAge(){return age;}
public void SetAge(Integer age){this.age=age;}
public String GetName(){return name;}
public void SetName(String name){this.name=name;}
}
import lombok.data;
@Data
public class User{
private Long id;
private String name;
private Integer age;
}
这个等价于
java复制代码
public class User {
private Long id;
private String name;
private Integer age;
// 1. 无参构造函数(因为没有任何 final 或 @NonNull 字段)
public User() {
}
// 2. 所有字段的 getter 方法
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Integer getAge() {
return this.age;
}
// 3. 所有非 final 字段的 setter 方法
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
// 4. equals 方法
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof User)) return false;
User other = (User) o;
if (!other.canEqual(this)) return false;
// 比较 id、name、age 字段
// ... 完整实现
}
protected boolean canEqual(Object other) {
return other instanceof User;
}
// 5. hashCode 方法
@Override
public int hashCode() {
// 基于 id、name、age 计算 hashCode
// ... 完整实现
}
// 6. toString 方法
@Override
public String toString() {
return "User(id=" + this.id + ", name=" + this.name + ", age=" + this.age + ")";
}
}
如果要加上全参构造函数,可以加上@AllArgsConstructor注解。
2.mapper
java复制代码
package com.你的包名.mapper;
import com.你的包名.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user")
List<User> findAll();
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Update("UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}")
int update(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
int delete(Long id);
}
这里的@Select这些CRUD注解是告诉mybatis去执行sql。这个 @Select("SELECT * FROM user")里面的sql语句和数据库查询语法基本一致,select这些都是不区分大小写。
要注意,这里的@Insert/@Update/@Delete 返回 int 是 JDBC 规范,代表数据库受影响的行数
java复制代码
@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
// 2. 业务代码调用
public void updateUser() {
User user = new User();
user.setId(1L); // 必须设置主键 ID
user.setName("李四"); // 只修改名字
// age 字段不设置,保持为 null
// 生成的 SQL: UPDATE user SET name = '李四' WHERE id = 1;
// age 不会被更新,保留数据库原值
userMapper.updateById(user);
}
4)mapper里面的为什么是接口,而不是类,具体的实现类去哪里了?
因为mybatis帮你生成了一个实现这个类的接口,你不需要自己写实现类了。
java复制代码
@Mapper
public interface UserMapper{
@Select("select * from user")
List<User> findAll();
}
mybatis在背后帮你生成了下面的实现类,你看不见
java复制代码
public class UserMapperImpl implements UserMapper{
@override
public List<User> findAll(){
//执行SQL,把结果封装成List<user>返回
}
}
3. Service(业务逻辑层)
java复制代码
package com.你的包名.service;
import com.你的包名.entity.User;
import com.你的包名.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;//自动注解(让spring自动创建对象加进来)
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> findAll() {
return userMapper.findAll();
}
public User findById(Long id) {
return userMapper.findById(id);
}
public int add(User user) {
return userMapper.insert(user);
}
public int update(User user) {
return userMapper.update(user);
}
public int delete(Long id) {
return userMapper.delete(id);
}
}
package com.你的包名.controller;
import com.你的包名.entity.User;
import com.你的包名.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> findAll() {
return userService.findAll();
}
@GetMapping("/{id}")
public User findById(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public String add(@RequestBody User user) {
int result = userService.add(user);
return result > 0 ? "添加成功" : "添加失败";
}
@PutMapping
public String update(@RequestBody User user) {
int result = userService.update(user);
return result > 0 ? "修改成功" : "修改失败";
}
@DeleteMapping("/{id}")
public String delete(@PathVariable Long id) {
int result = userService.delete(id);
return result > 0 ? "删除成功" : "删除失败";
}
}
控制层是前后端交互的"接口",
这里的重点说一下@RestController。``@RestController 是 Spring Boot 中用于构建 RESTful API 的核心注解,它的作用是让一个 Java 类成为处理 HTTP 请求的控制器,并自动将返回结果转为 JSON 格式。
1)@RestController的核心作用:
2)与普通 Controller 的区别
传统 @Controller(返回页面)
java复制代码
@Controller
public class UserController {
@GetMapping("/user")
public String getUser(Model model) {
model.addAttribute("name", "张三");
return "userPage"; // 返回视图名称,跳转到 userPage.html
}
}
@RestController(返回数据)
java复制代码
@RestController
public class UserController {
@GetMapping("/user")
public User getUser() {
User user = new User();
user.setName("张三");
user.setAge(25);
return user; // 自动转为 JSON:{"name":"张三","age":25}
}
}
3)@ResponseBody
它的主要作用是将返回的对象,自动转换成客户端能直接接收的数据格式(通常是 JSON 或 XML),并作为 HTTP 响应的 body 内容。