Java后端开发从0到1学习教程
学习目标
让前端开发者(0Java基础)能够:
- 理解Java后端开发基础概念
- 掌握Spring Boot框架使用
- 能够独立开发REST API接口
- 理解数据库操作和ORM框架
- 能够维护和扩展现有项目
ps:本人前端菜鸡一枚,最近在学习java,本文乃学习过程中记录的笔记,可能有所错误,欢迎大佬们指正!
第一阶段:Java基础入门
1:Java环境搭建
1.1 安装JDK
bash
# 下载JDK 8或11
# 官网:https://www.oracle.com/java/technologies/downloads/
# 安装后验证
java -version
javac -version
1.2 配置环境变量
bash
# Windows系统
JAVA_HOME=C:\Program Files\Java\jdk-11.0.16
PATH=%JAVA_HOME%\bin;%PATH%
# 验证配置
echo %JAVA_HOME%
1.3 第一个Java程序
java
// HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, Java!");
System.out.println("欢迎来到Java世界!");
}
}
// 编译和运行
// javac HelloWorld.java
// java -cp . HelloWorld
前端对比理解:
javascript
// JavaScript
console.log("Hello, JavaScript!");
// Java
System.out.println("Hello, Java!");
2:Java基本语法
2.1 变量和数据类型
基本类型
1.整数类型:
byte、short、int、long
java
byte b = 127; // 8位,-128到127
short s = 32767; // 16位,-32768到32767
int i = 2147483647; // 32位,-2^31到2^31-1
long l = 9223372036854775807L; // 64位,需要L后缀
/**
Java:4种整数类型,需要明确指定类型
JavaScript:只有Number类型,自动处理整数和浮点数
**/
2.浮点数类型
float、double
java
float f = 3.14f; // 32位,需要f后缀
double d = 3.141592653589793; // 64位,默认类型
/**
Java:float和double两种精度
JavaScript:只有Number类型,但精度问题相同
**/
3.字符类型
char
java
char c = 'A'; // 16位Unicode字符
char chinese = '中'; // 支持中文字符
/**
varchar是数据库的类型,不是java的类型
Java:有专门的char类型
JavaScript:字符就是单字符字符串
**/
4.布尔类型
boolean
java
boolean b1 = true;
boolean b2 = false;
/**
Java:只有true和false
JavaScript:有"假值"概念(0、""、null、undefined、NaN)
**/
5.字符串类型
string
java
String str1 = "Hello"; // 字符串字面量
String str2 = new String("World"); // 对象创建
String str3 = str1 + " " + str2; // 字符串拼接
/**
Java:String是不可变对象,对象创建后,其内部状态不能被修改。
可以理解为:声明一个string之后,如果对这个string进行重新赋值了,那就相当于重新创建了一个string,而不是对原始的string进行修改。
示例:
String str = "Hello";
System.out.println("第一次赋值 - 内存地址: " + System.identityHashCode(str));
// 重新赋值 = 创建新String对象
str = "World";
System.out.println("重新赋值后 - 内存地址: " + System.identityHashCode(str));
// 再次重新赋值 = 又创建新String对象
str = "Java";
System.out.println("再次赋值后 - 内存地址: " + System.identityHashCode(str));
运行结果:
第一次赋值 - 内存地址: 1234567890
重新赋值后 - 内存地址: 9876543210 // 地址变了!
再次赋值后 - 内存地址: 5555555555 // 地址又变了!
可以看到每次赋值后,内存地址发生了变化
JavaScript:字符串也是不可变的,但可以重新赋值
**/
String不可变设计的好处:
- 线程安全:多线程环境下安全使用
- 性能优化:字符串常量池共享内存
- 安全性:作为HashMap key安全,密码传递安全
- 简化设计:无需同步,避免副作用
- 函数式支持:支持链式调用
- 内存效率:相同字符串共享内存
- 易于维护:代码更可预测,bug更少
字符串类型常用函数
功能 | Java | JavaScript |
---|---|---|
长度 | length() | length |
去空格 | trim() | trim() |
转大写 | toUpperCase() | toUpperCase() |
转小写 | toLowerCase() | toLowerCase() |
子字符串 | substring(start, end) | substring(start, end) |
替换 | replace(old, new) | replace(old, new) |
分割 | split(delimiter) | split(delimiter) |
包含检查 | contains(str) | includes(str) |
开始检查 | startsWith(str) | startsWith(str) |
结束检查 | endsWith(str) | endsWith(str) |
比较 | equals(str) | === |
引用类型
1.数组类型
java
//java
int[] numbers = {1, 2, 3, 4, 5}; // 一维数组
String[] names = new String[3]; // 声明数组
names[0] = "张三";
names[1] = "李四";
names[2] = "王五";
// 二维数组
int[][] matrix = {{1, 2}, {3, 4}};
//javascript
let numbers = [1, 2, 3, 4, 5]; // 数组字面量
let names = new Array(3); // 声明数组
names[0] = "张三";
names[1] = "李四";
names[2] = "王五";
// 二维数组
let matrix = [[1, 2], [3, 4]];
/**
Java:数组长度固定,类型固定
JavaScript:数组长度可变,类型可变
**/
2.对象类型
java
//定义类
class Person {
private String name;
private int age;
// 构造函数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class ObjectTypes {
public static void main(String[] args) {
// 创建对象
Person person = new Person("张三", 25);
}
}
/**
Java:需要先定义类,再创建对象
JavaScript:可以直接创建对象,动态添加属性
**/
3.类型转换
java
public class TypeConversion {
public static void main(String[] args) {
// 自动类型转换(隐式转换)
int i = 100;
long l = i; // int自动转换为long
double d = i; // int自动转换为double
// 强制类型转换(显式转换)
double d2 = 3.14;
int i2 = (int) d2; // double强制转换为int,结果为3
// 字符串转换
String str = "123";
int num = Integer.parseInt(str); // 字符串转整数
String str2 = String.valueOf(num); // 整数转字符串
System.out.println("i2: " + i2);
System.out.println("num: " + num);
System.out.println("str2: " + str2);
}
}
/**
Java:类型转换更严格,需要显式转换
JavaScript:类型转换更灵活,有隐式转换
**/
4. List集合类型
4.1 ArrayList(最常用)
java
import java.util.ArrayList;
import java.util.List;
public class ArrayListExample {
public static void main(String[] args) {
// 创建ArrayList
List<String> list = new ArrayList<>();
// 添加元素
list.add("张三");
list.add("李四");
list.add("王五");
// 访问元素
System.out.println("列表: " + list);
System.out.println("第一个元素: " + list.get(0));
System.out.println("列表大小: " + list.size());
// 遍历
for (String name : list) {
System.out.println("姓名: " + name);
}
}
}
/**
运行结果:
列表: [张三, 李四, 王五]
第一个元素: 张三
列表大小: 3
姓名: 张三
姓名: 李四
姓名: 王五
**/
特点:基于数组,随机访问快,插入删除慢
list常用方法
功能 | Java List | JavaScript Array |
---|---|---|
添加元素 | add(item) | push(item) |
插入元素 | add(index, item) | splice(index, 0, item) |
获取元素 | get(index) | array[index] |
获取大小 | size() | length |
包含检查 | contains(item) | includes(item) |
查找索引 | indexOf(item) | indexOf(item) |
删除元素 | remove(item) | splice(index, 1) |
清空 | clear() | length = 0 |
是否为空 | isEmpty() | length === 0 |
遍历 | for-each | forEach() |
4.2 LinkedList
java
import java.util.LinkedList;
import java.util.List;
public class LinkedListExample {
public static void main(String[] args) {
// 创建LinkedList
List<String> list = new LinkedList<>();
// 添加元素
list.add("张三");
list.add("李四");
list.add("王五");
// 在指定位置插入
list.add(1, "赵六");
// 删除元素
list.remove("李四");
System.out.println("列表内容: " + list);
}
}
/**
运行结果:
列表内容: [张三, 赵六, 王五]
**/
特点:基于链表,插入删除快,随机访问慢
4.3 Vector
java
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
// 创建Vector
Vector<String> vector = new Vector<>();
// 添加元素
vector.add("张三");
vector.add("李四");
// 特点:线程安全,但性能较低
System.out.println("Vector内容: " + vector);
}
}
/**
运行结果:
Vector内容: [张三, 李四]
**/
类型 | 特点 | 适用场景 | 性能 |
---|---|---|---|
ArrayList | 基于数组,随机访问快 | 频繁查询,少量插入删除 | 查询O(1),插入O(n) |
LinkedList | 基于链表,插入删除快 | 频繁插入删除,少量查询 | 查询O(n),插入O(1) |
Vector | 线程安全 | 多线程环境 | 性能较低 |
5.Map集合类型
5.1HashMap(最常用)
java
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
// 创建HashMap
Map<String, Integer> map = new HashMap<>();
// 添加键值对
map.put("张三", 25);
map.put("李四", 30);
map.put("王五", 28);
// 获取值
Integer age = map.get("张三");
System.out.println("张三的年龄: " + age);
// 检查键是否存在
boolean hasKey = map.containsKey("李四");
System.out.println("是否有李四: " + hasKey);
// 遍历
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
/**
张三的年龄: 25
是否有李四: true
李四: 30
张三: 25
王五: 28
**/
//前端JavaScript对比
// JavaScript对象
let map = {};
map["张三"] = 25;
map["李四"] = 30;
map["王五"] = 28;
console.log("张三的年龄:", map["张三"]);
console.log("是否有李四:", "李四" in map);
Object.keys(map).forEach(key => {
console.log(key + ": " + map[key]);
});
特点:无序,允许null键值,性能好
map常用函数方法
功能 | Java Map | JavaScript Object |
---|---|---|
添加键值对 | put(key, value) | obj[key] = value |
获取值 | get(key) | obj[key] |
获取大小 | size() | Object.keys(obj).length |
检查键 | containsKey(key) | key in obj |
检查值 | containsValue(value) | Object.values(obj).includes(value) |
删除键值对 | remove(key) | delete obj[key] |
清空 | clear() | obj = {} |
是否为空 | isEmpty() | Object.keys(obj).length === 0 |
遍历键 | keySet() | Object.keys(obj) |
遍历值 | values() | Object.values(obj) |
遍历键值对 | entrySet() | Object.entries(obj) |
5.2 LinkedHashMap(保持插入顺序)
java
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapExample {
public static void main(String[] args) {
// 创建LinkedHashMap
Map<String, Integer> map = new LinkedHashMap<>();
// 添加元素
map.put("张三", 25);
map.put("李四", 30);
map.put("王五", 28);
// 遍历(保持插入顺序)
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
/**
运行结果:
张三: 25
李四: 30
王五: 28
**/
特点:保持插入顺序,性能略低于HashMap
5.3 TreeMap(有序)
java
import java.util.TreeMap;
import java.util.Map;
public class TreeMapExample {
public static void main(String[] args) {
// 创建TreeMap
Map<String, Integer> map = new TreeMap<>();
// 添加元素
map.put("张三", 25);
map.put("李四", 30);
map.put("王五", 28);
// 遍历(按键排序)
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
/**
运行结果:
张三: 25
李四: 30
王五: 28
**/
特点:按键排序,性能低于HashMap
类型 | 特点 | 适用场景 | 性能 |
---|---|---|---|
HashMap | 无序,性能好 | 一般用途 | O(1) |
LinkedHashMap | 保持插入顺序 | 需要保持顺序 | O(1) |
TreeMap | 有序 | 需要排序 | O(log n) |
6.Set集合类型
6.1 HashSet(去重) (常用)
java
import java.util.HashSet;
import java.util.Set;
public class HashSetExample {
public static void main(String[] args) {
// 创建HashSet
Set<String> set = new HashSet<>();
// 添加元素
set.add("张三");
set.add("李四");
set.add("张三"); // 重复元素,不会添加
System.out.println("set: " +set);
// 检查元素是否存在
boolean hasName = set.contains("张三");
System.out.println("是否有张三: " + hasName);
// 遍历
for (String name : set) {
System.out.println("姓名: " + name);
}
}
}
/**
运行结果:
set: [李四, 张三]
是否有张三: true
姓名: 李四
姓名: 张三
**/
特点:去重,无序,性能好
set常用函数方法
功能 | Java Set | JavaScript Set |
---|---|---|
添加元素 | add(item) | add(item) |
获取大小 | size() | size |
包含检查 | contains(item) | has(item) |
删除元素 | remove(item) | delete(item) |
清空 | clear() | clear() |
是否为空 | isEmpty() | size === 0 |
遍历 | for-each | forEach() |
转数组 | toArray() | Array.from() |
6.2 LinkedHashSet(去重+保持顺序)
java
import java.util.LinkedHashSet;
import java.util.Set;
public class LinkedHashSetExample {
public static void main(String[] args) {
// 创建LinkedHashSet
Set<String> set = new LinkedHashSet<>();
// 添加元素
set.add("张三");
set.add("李四");
set.add("王五");
set.add("张三"); // 重复元素,不会添加
System.out.println("set: " +set);
// 遍历(保持插入顺序)
for (String name : set) {
System.out.println("姓名: " + name);
}
}
}
/**
运行结果:
set: [张三, 李四, 王五]
姓名: 张三
姓名: 李四
姓名: 王五
**/
特点:去重,保持插入顺序
6.3 TreeSet(去重+排序)
java
import java.util.TreeSet;
import java.util.Set;
public class TreeSetExample {
public static void main(String[] args) {
// 创建TreeSet
Set<String> set = new TreeSet<>();
// 添加元素
set.add("张三");
set.add("李四");
set.add("王五");
set.add("张三"); // 重复元素,不会添加
System.out.println("set: " +set);
// 遍历(按字母排序)
for (String name : set) {
System.out.println("姓名: " + name);
}
}
}
/**
运行结果:
set: [张三, 李四, 王五]
姓名: 张三
姓名: 李四
姓名: 王五
**/
特点:去重,排序
类型 | 特点 | 适用场景 | 性能 |
---|---|---|---|
HashSet | 去重,无序 | 去重操作 | O(1) |
LinkedHashSet | 去重,保持顺序 | 去重+保持顺序 | O(1) |
TreeSet | 去重,排序 | 去重+排序 | O(log n) |
2.2 控制结构
java
public class ControlStructures {
public static void main(String[] args) {
int score = 85;
// if-else语句
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 70) {
System.out.println("中等");
} else {
System.out.println("需要努力");
}
// for循环
for (int i = 1; i <= 5; i++) {
System.out.println("第" + i + "次循环");
}
// while循环
int count = 0;
while (count < 3) {
System.out.println("计数: " + count);
count++;
}
}
}
前端对比理解:
javascript
// JavaScript
let score = 85;
if (score >= 90) {
console.log("优秀");
} else if (score >= 80) {
console.log("良好");
} else {
console.log("需要努力");
}
for (let i = 1; i <= 5; i++) {
console.log(`第${i}次循环`);
}
3:面向对象编程
3.1 类和对象
前端在数据类型里已经讲过java的对象需先定义类,再创建对象
java
// 用户类
public class User {
// 属性(类似Vue3的data)
private String name;
private Integer age;
private String email;
// 构造函数
public User(String name, Integer age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
// Getter方法(类似Vue3的computed)
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public String getEmail() {
return email;
}
// Setter方法
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setEmail(String email) {
this.email = email;
}
// 方法(类似Vue3的methods)
public void displayInfo() {
System.out.println("姓名: " + name + ", 年龄: " + age + ", 邮箱: " + email);
}
public boolean isAdult() {
return age >= 18;
}
}
// 测试类
public class UserTest {
public static void main(String[] args) {
// 创建用户对象
User user1 = new User("张三", 25, "zhangsan@example.com");
User user2 = new User("李四", 17, "lisi@example.com");
// 调用方法
user1.displayInfo();
user2.displayInfo();
// 判断是否成年
System.out.println("张三是否成年: " + user1.isAdult());
System.out.println("李四是否成年: " + user2.isAdult());
}
}
前端对比理解:
javascript
// Vue3
export default {
data() {
return {
name: '',
age: 0,
email: ''
}
},
computed: {
isAdult() {
return this.age >= 18
}
},
methods: {
displayInfo() {
console.log(`姓名: ${this.name}, 年龄: ${this.age}, 邮箱: ${this.email}`)
}
}
}
3.2 抽象类和接口
在了解抽象类时,我们先了解一下抽象类、抽象方法、具体实现类、具体方法的含义与区别。
抽象类:
就像是一个"半成品模板",它定义了基本的结构,但有些部分还没有完成。
想象你要开一家餐厅:
-
抽象类 = 餐厅的基本框架(有厨房、有桌椅、有收银台)
-
具体实现类 = 具体的餐厅(中餐厅、西餐厅、快餐店)
特点:
- 可以有具体方法:已经实现的功能
- 可以有抽象方法:待实现的功能
- 可以有属性:餐厅的基本设施
- 不能直接创建对象:不能直接生产菜品
- 单继承:一个餐厅只能继承一个母公司
java
// 抽象类:餐厅的基本框架
public abstract class Restaurant {
protected String name;
protected String address;
// 构造函数
public Restaurant(String name, String address) {
this.name = name;
this.address = address;
}
// 具体方法:所有餐厅都有的功能
public void welcome() {
System.out.println("欢迎光临" + name + "!");
}
public void showMenu() {
System.out.println("这是" + name + "的菜单");
}
public void takeOrder() {
System.out.println("正在为您点餐...");
}
// 抽象方法:每个餐厅都不同,需要子类自己实现
public abstract void cook(); // 做菜方式不同
public abstract void serve(); // 服务方式不同
public abstract String getCuisine(); // 菜系不同
}
抽象方法:
抽象方法就像是一个"待办事项",告诉子类"你必须做这件事,但具体怎么做你自己决定"
特点
-
只有方法声明,没有方法体
-
用abstract关键字修饰
-
必须在抽象类中
-
子类必须实现(重写)这些方法
java
// 抽象方法示例
public abstract class Vehicle {
protected String brand;
// 具体方法:所有车辆都有的功能
public void start() {
System.out.println("车辆启动");
}
// 抽象方法:每个车辆都不同,需要子类自己实现
public abstract void drive(); // 驾驶方式不同
public abstract void stop(); // 停车方式不同
public abstract String getType(); // 车辆类型不同
}
具体实现类:
具体实现类就像是一个"完整的成品",它继承了抽象类的框架,并实现了所有抽象方法。
java
// 具体实现类1:中餐厅
public class ChineseRestaurant extends Restaurant {
public ChineseRestaurant(String name, String address) {
super(name, address);
}
// 实现抽象方法
@Override
public void cook() {
System.out.println("用中式方法烹饪:炒、煮、蒸、炸");
}
@Override
public void serve() {
System.out.println("用筷子和碗为您服务");
}
@Override
public String getCuisine() {
return "中式菜系";
}
// 具体实现类特有的方法
public void serveTea() {
System.out.println("为您奉上热茶");
}
}
// 具体实现类2:西餐厅
public class WesternRestaurant extends Restaurant {
public WesternRestaurant(String name, String address) {
super(name, address);
}
// 实现抽象方法
@Override
public void cook() {
System.out.println("用西式方法烹饪:烤、煎、焗、煮");
}
@Override
public void serve() {
System.out.println("用刀叉和盘子为您服务");
}
@Override
public String getCuisine() {
return "西式菜系";
}
// 具体实现类特有的方法
public void serveWine() {
System.out.println("为您推荐红酒");
}
}
具体方法:
具体方法就像是一个"已经完成的功能",有具体的实现代码,可以直接使用。
java
// 具体方法示例
public abstract class Animal {
protected String name;
protected int age;
// 具体方法:所有动物都有的功能,已经实现好了
public void sleep() {
System.out.println(name + "正在睡觉");
}
public void eat() {
System.out.println(name + "正在吃东西");
}
public void displayInfo() {
System.out.println("名字:" + name + ",年龄:" + age);
}
// 抽象方法:每个动物都不同,需要子类自己实现
public abstract void makeSound();
public abstract void move();
}
// 具体实现类
public class Dog extends Animal {
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
// 实现抽象方法
@Override
public void makeSound() {
System.out.println(name + "汪汪叫");
}
@Override
public void move() {
System.out.println(name + "在跑步");
}
// 具体方法:子类特有的功能
public void fetch() {
System.out.println(name + "在捡球");
}
}
接口:
接口就像是一个"标准规范",它定义了"必须做什么",但不关心"怎么做"。
想象你要开一家餐厅:
-
接口 = 餐厅的标准规范(必须有点餐、上菜、结账功能)
-
具体实现类 = 具体的餐厅(中餐厅、西餐厅、快餐店
特点:
-
只能有抽象方法:只有规范,没有实现
-
不能有属性:只有方法声明
-
不能直接创建对象:不能直接开餐厅
-
多实现:一个餐厅可以实现多个规范
-
所有方法都是public:规范是公开的
java
// 接口:餐厅标准规范
public interface Restaurant {
// 抽象方法:每个餐厅都必须实现
void takeOrder(); // 点餐
void serveFood(); // 上菜
void collectPayment(); // 结账
String getCuisine(); // 获取菜系
}
// 接口:外卖服务规范
public interface DeliveryService {
void prepareDelivery(); // 准备外卖
void deliverFood(); // 送餐
double calculateDeliveryFee(); // 计算配送费
}
// 接口:会员服务规范
public interface MembershipService {
void registerMember(); // 注册会员
void giveDiscount(); // 给折扣
void sendPromotion(); // 发送促销信息
}
特性 | 抽象类 | 接口 |
---|---|---|
关键字 | abstract class | interface |
继承/实现 | extends | implements |
数量限制 | 单继承 | 多实现 |
方法类型 | 可以有具体方法和抽象方法 | 只能有抽象方法 |
属性 | 可以有属性 | 不能有属性 |
构造函数 | 可以有构造函数 | 不能有构造函数 |
访问修饰符 | 可以是任意修饰符 | 默认public |
使用场景 | 有共同属性和行为的类 | 定义规范和行为契约 |
选择原则:
- 有共同属性 → 使用抽象类
- 需要多继承 → 使用接口
- 定义行为规范 → 使用接口
- 有共同实现 → 使用抽象类
通过抽象类和接口,我们可以:
-
统一接口:所有实现类都有相同的方法
-
灵活实现:每个实现类可以有不同的实现
-
代码复用:共同的功能在抽象类中实现
-
易于扩展:添加新类型只需要继承或实现
3.3 封装、继承和多态
封装
java
public class BankAccount {
// 私有属性,外部不能直接访问
private String accountNumber;
private double balance;
private String ownerName;
// 构造函数
public BankAccount(String accountNumber, String ownerName, double initialBalance) {
this.accountNumber = accountNumber;
this.ownerName = ownerName;
this.balance = initialBalance;
}
// 公共方法,提供受控的访问
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("存款成功,当前余额:" + balance);
} else {
System.out.println("存款金额必须大于0");
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("取款成功,当前余额:" + balance);
} else {
System.out.println("取款失败:金额无效或余额不足");
}
}
public double getBalance() {
return balance;
}
public String getAccountNumber() {
return accountNumber;
}
public String getOwnerName() {
return ownerName;
}
// 私有方法,只能在类内部使用
private void logTransaction(String type, double amount) {
System.out.println("交易记录:" + type + " " + amount + "元");
}
}
// 使用封装的类
public class BankTest {
public static void main(String[] args) {
BankAccount account = new BankAccount("123456789", "张三", 1000.0);
// 只能通过公共方法访问
account.deposit(500.0);
account.withdraw(200.0);
// 不能直接访问私有属性
// account.balance = 10000; // 编译错误!
// 只能通过getter获取余额
System.out.println("当前余额:" + account.getBalance());
}
}
/**
private 定义私有属性、方法,类似于JavaScript里的闭包
public 定义公共属性、方法
**/
上述如果用JavaScript实现
JavaScript
// JavaScript中的封装(使用闭包)
function BankAccount(accountNumber, ownerName, initialBalance) {
// 私有变量
let balance = initialBalance;
let accountNum = accountNumber;
let owner = ownerName;
// 公共方法
this.deposit = function(amount) {
if (amount > 0) {
balance += amount;
console.log(`存款成功,当前余额:${balance}`);
} else {
console.log("存款金额必须大于0");
}
};
this.withdraw = function(amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
console.log(`取款成功,当前余额:${balance}`);
} else {
console.log("取款失败:金额无效或余额不足");
}
};
this.getBalance = function() {
return balance;
};
this.getAccountNumber = function() {
return accountNum;
};
this.getOwnerName = function() {
return owner;
};
// 私有方法
function logTransaction(type, amount) {
console.log(`交易记录:${type} ${amount}元`);
}
}
// 使用封装的类
let account = new BankAccount("123456789", "张三", 1000.0);
account.deposit(500.0);
account.withdraw(200.0);
// 不能直接访问私有变量
// console.log(account.balance); // undefined
console.log("当前余额:" + account.getBalance());
继承
java
// 父类
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + "正在吃东西");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
}
// 子类
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void eat() {
System.out.println(name + "正在吃狗粮");
}
public void bark() {
System.out.println(name + "正在汪汪叫");
}
}
// 测试
public class AnimalTest {
public static void main(String[] args) {
Animal animal = new Animal("动物");
Dog dog = new Dog("旺财");
animal.eat();
dog.eat();
dog.bark();
}
}
/**
使用extends关键字,super调用父类,同JavaScript里ES6的extends、super
extends关键字用于建立继承关系,表示"扩展"或"继承"。
super关键字用于访问父类的成员,包括:
调用父类构造函数
访问父类属性
调用父类方法
**/
多态
多态是指同一个接口可以有不同的实现,即一个对象可以表现出多种形态。
-
一个接口,多种实现
-
同一个方法调用,不同的行为
-
运行时决定调用哪个方法
java
// 抽象类
public abstract class Shape {
protected String name;
public Shape(String name) {
this.name = name;
}
// 抽象方法
public abstract double getArea();
public abstract double getPerimeter();
// 具体方法
public void displayInfo() {
System.out.println("形状:" + name);
System.out.println("面积:" + getArea());
System.out.println("周长:" + getPerimeter());
}
}
// 具体实现类
public class Circle extends Shape {
private double radius;
public Circle(String name, double radius) {
super(name);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public double getPerimeter() {
return 2 * Math.PI * radius;
}
}
public class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(String name, double width, double height) {
super(name);
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width * height;
}
@Override
public double getPerimeter() {
return 2 * (width + height);
}
}
// 使用多态
public class ShapeTest {
public static void main(String[] args) {
// 多态:同一个接口,不同的实现
Shape[] shapes = {
new Circle("圆形", 5.0),
new Rectangle("矩形", 4.0, 6.0),
new Circle("大圆", 10.0)
};
// 多态调用
for (Shape shape : shapes) {
shape.displayInfo(); // 每个形状都有不同的实现
System.out.println("---");
}
// 计算总面积
double totalArea = 0;
for (Shape shape : shapes) {
totalArea += shape.getArea();
}
System.out.println("总面积:" + totalArea);
}
}
上述用JavaScript实现
javascript
// JavaScript中的多态
class Shape {
constructor(name) {
this.name = name;
}
getArea() {
throw new Error("子类必须实现getArea方法");
}
getPerimeter() {
throw new Error("子类必须实现getPerimeter方法");
}
displayInfo() {
console.log(`形状:${this.name}`);
console.log(`面积:${this.getArea()}`);
console.log(`周长:${this.getPerimeter()}`);
}
}
class Circle extends Shape {
constructor(name, radius) {
super(name);
this.radius = radius;
}
getArea() {
return Math.PI * this.radius * this.radius;
}
getPerimeter() {
return 2 * Math.PI * this.radius;
}
}
class Rectangle extends Shape {
constructor(name, width, height) {
super(name);
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
getPerimeter() {
return 2 * (this.width + this.height);
}
}
// 使用多态
let shapes = [
new Circle("圆形", 5.0),
new Rectangle("矩形", 4.0, 6.0),
new Circle("大圆", 10.0)
];
// 多态调用
shapes.forEach(shape => {
shape.displayInfo(); // 每个形状都有不同的实现
console.log("---");
});
// 计算总面积
let totalArea = shapes.reduce((sum, shape) => sum + shape.getArea(), 0);
console.log("总面积:" + totalArea);
多态的优势:
- 代码复用:减少重复代码
- 易于扩展:添加新类型不影响现有代码
- 接口统一:统一的接口,不同的实现
- 灵活性:运行时决定行为
4:异常处理
4.1 异常处理基础
就是try catch
java
public class ExceptionExample {
public static void main(String[] args) {
try {
// 可能抛出异常的代码
int result = divide(10, 0);
System.out.println("结果: " + result);
} catch (ArithmeticException e) {
// 捕获异常
System.out.println("除零错误: " + e.getMessage());
} catch (Exception e) {
// 捕获其他异常
System.out.println("其他错误: " + e.getMessage());
} finally {
// 无论是否异常都会执行
System.out.println("程序执行完毕");
}
}
public static int divide(int a, int b) throws ArithmeticException {
if (b == 0) {
throw new ArithmeticException("除数不能为零");
}
return a / b;
}
}
前端对比理解:
javascript
// Vue3
export default {
methods: {
async divide(a, b) {
try {
if (b === 0) {
throw new Error("除数不能为零");
}
return a / b;
} catch (error) {
console.error("错误:", error.message);
} finally {
console.log("程序执行完毕");
}
}
}
}
第二阶段:Spring Boot框架入门
5:Spring Boot基础
可以将Spring Boot理解为一个同vue一样的框架,可以通过命令或者编译器直接创建项目。下面就以IDE编辑器创建一个简单的项目。
5.1 通过IDE创建第一个Spring Boot项目
创建一个简单的接口

创建后得到如下图所示的空项目

1. 添加Spring Boot依赖
xml
<!-- 文件 pom.xml -->
<?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 http://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>2.7.0</version>
<relativePath/>
</parent>
<groupId>org.example</groupId>
<artifactId>javademo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<java.version>8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Spring Boot Web Starter - 提供Web开发所需的核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Test Starter - 提供测试相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven插件 - 用于打包和运行应用 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
<!--
pom.xml文件解释:
作用:这是Maven项目的配置文件,类似于Vue项目中的package.json
为什么需要:定义了项目依赖、构建配置等,让Maven知道需要下载哪些库
Spring Boot Parent:提供了Spring Boot的版本管理和默认配置
spring-boot-starter-web:包含了Web开发所需的所有依赖(如Spring MVC、Tomcat等)
-->
2.创建实体类
我们可以在src\main\java\org\example文件夹下创建一个文件夹dto文件夹,用来存放实体类文件

然后在dto文件夹里,创建请求实体类HelloRequest.java,用于接收前端传来的参数:

java
//HelloRequest.java
package org.example.dto;
public class HelloRequest {
private String name;
/**
* 有参构造函数
* 方便创建对象时直接传入参数
*
* @param name 用户姓名
*/
public HelloRequest(String name) {
this.name = name;
}
/**
* 获取用户姓名
* Getter方法,用于获取name字段的值
*
* @return 用户姓名
*/
public String getName() {
return name;
}
/**
* 设置用户姓名
* Setter方法,用于设置name字段的值
* Spring Boot会自动调用此方法来设置从JSON转换来的值
*
* @param name 用户姓名
*/
public void setName(String name) {
this.name = name;
}
}
/**
为什么创建:用于定义API请求的数据结构,类似于Vue中的接口定义
类比Vue:就像Vue组件中的props定义,用于接收父组件传递的数据
主要功能:
定义请求参数的结构(name字段)
提供getter/setter方法供Spring Boot自动调用
包含构造函数用于创建对象实例
**/
然后在dto文件夹里,创建响应实体类 HelloResponse.java
java
package org.example.dto;
/**
* Hello接口返回实体类
* 用于封装返回给前端的数据
*
* 类比Vue中的响应数据对象
* 例如:{ message: "hello 张三" }
*/
public class HelloResponse {
/**
* 返回消息
* 包含问候语和用户姓名
*/
private String message;
/**
* 状态码
* 用于标识请求处理状态(可选字段)
*/
private int code;
/**
* 简化的有参构造函数
* 只传入消息,状态码默认为200(成功)
*
* @param message 返回消息
*/
public HelloResponse(String message) {
this.message = message;
this.code = 200; // 默认成功状态码
}
}
/**
* 完整的有参构造函数
* 传入消息和状态码
*
* @param message 返回消息
* @param code 状态码
*/
public HelloResponse(String message, int code) {
this.message = message;
this.code = code;
}
/**
* 获取返回消息
* @return 返回消息
*/
public String getMessage() {
return message;
}
/**
* 设置返回消息
* @param message 返回消息
*/
public void setMessage(String message) {
this.message = message;
}
/**
* 获取状态码
* @return 状态码
*/
public int getCode() {
return code;
}
/**
* 设置状态码
* @param code 状态码
*/
public void setCode(int code) {
this.code = code;
}
/**
为什么创建:用于定义API返回的数据结构,确保返回数据格式统一
类比Vue:就像Vue组件中定义的数据结构,用于规范组件间的数据传递
主要功能:
定义返回数据的结构(message和code字段)
提供多种构造函数方便不同场景使用
包含getter/setter方法供Spring Boot自动序列化为JSON
**/
3.创建业务逻辑服务类
为了规范美观,我们先创建文件夹service,专门用来存放逻辑服务类,然后在service里新建服务类文件HelloService.java

java
package org.example.service;
import org.example.dto.HelloRequest;
import org.example.dto.HelloResponse;
import org.springframework.stereotype.Service;
/**
* Hello业务逻辑服务类
* 处理Hello相关的业务逻辑
*
* 类比Vue中的methods或computed,包含具体的业务处理逻辑
* 类似于Vue组件中的方法,处理数据并返回结果
*/
@Service
public class HelloService {
/**
* 生成问候消息
* 根据传入的姓名生成问候语
*
* 类比Vue中的方法:
* methods: {
* generateHelloMessage(name) {
* return `hello ${name}`;
* }
* }
*
* @param request 包含用户姓名的请求对象
* @return 包含问候消息的响应对象
*/
public HelloResponse generateHelloMessage(HelloRequest request) {
// 获取用户姓名
String name = request.getName();
// 生成问候消息
String message = "hello " + name;
// 创建并返回响应对象
return new HelloResponse(message, 200);
}
}
/**
为什么创建:将业务逻辑从控制器中分离出来,遵循单一职责原则
类比Vue:就像Vue组件中的methods部分,包含具体的业务处理方法
@Service注解:告诉Spring这是一个服务类,需要被Spring容器管理
主要功能:
处理具体的业务逻辑(生成问候消息)
进行参数校验
提供多个重载方法增加灵活性
**/
4.创建控制器Controller
同逻辑服务类一样,先创建一个文件夹Controller专门存放控制器,然后创建控制器HelloController.java

java
package org.example.controller;
import org.example.dto.HelloRequest;
import org.example.dto.HelloResponse;
import org.example.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* Hello控制器类
* 处理HTTP请求,调用业务逻辑服务
*
* 类比Vue中的路由处理函数或API调用函数
* 类似于Vue Router中的路由处理,接收请求并返回响应
*/
@RestController
@RequestMapping("/hello")
public class HelloController {
/**
* 注入HelloService服务
* 通过依赖注入获取业务逻辑服务实例
*
* 类比Vue中的依赖注入或组件引用
* 类似于Vue中通过props或inject获取其他组件的方法
*/
@Autowired
private HelloService helloService;
/**
* Hello接口
* 处理GET请求,通过URL参数传递姓名
*
* 类比Vue中的API调用:
* async callHelloApi(name) {
* const response = await axios.get(`/hello/helloApi?name=${name}`);
* return response.data;
* }
*
* @param name 用户姓名(通过URL参数传递)
* @return 包含问候消息的响应对象
*/
@GetMapping("/helloApi")
public HelloResponse helloApi(@RequestParam String name) {
// 调用业务逻辑服务处理请求
return helloService.generateHelloMessage(name);
}
}
/**
为什么创建:作为Web层的入口,处理HTTP请求并调用业务逻辑
类比Vue:就像Vue Router中的路由处理函数,接收请求并返回响应
主要注解:
@RestController:标识这是一个REST控制器,自动将返回值转换为JSON
@RequestMapping("/hello"):定义基础路径为/hello
@PostMapping("/helloApi"):处理POST请求到/hello/helloApi
@GetMapping("/helloApi"):处理GET请求到/hello/helloApi
@RequestBody:将请求体JSON转换为Java对象
@RequestParam:获取URL参数
**/
5.更新主启动类
更新Main.java文件
java
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring Boot主启动类
* 应用程序的入口点
*
* 类比Vue中的main.js文件,是整个应用的启动入口
* 类似于Vue项目的入口文件,负责启动整个应用
*/
@SpringBootApplication
public class Main {
/**
* 主方法
* 启动Spring Boot应用程序
*
* 类比Vue中的:
* import { createApp } from 'vue'
* import App from './App.vue'
* createApp(App).mount('#app')
*
* @param args 命令行参数
*/
public static void main(String[] args) {
// 启动Spring Boot应用
SpringApplication.run(Main.class, args);
System.out.println("项目已启动成功");
}
}
/**
为什么创建:这是Spring Boot应用的入口点,类似于Vue项目的main.js
@SpringBootApplication注解:标识这是一个Spring Boot应用,包含自动配置功能
类比Vue:就像Vue项目中的main.js文件,负责启动整个应用
现在让我检查是否有任何编译错误:
**/
通过IDE启动项目:
1.找到启动类Main.java;
2.右键 运行;
3.在控制台看到启动成功信息;

4.在浏览器地址栏访问 http://localhost:8080/hello/helloApi?name=张三
即可得到访问成功信息

至此我们已经成功创建了一个完整的Spring Boot项目
项目结构如下
javaDemo/
├── pom.xml # Maven配置文件(类比package.json)
├── API测试说明.md # 测试说明文档
└── src/main/java/org/example/
├── Main.java # 主启动类(类比main.js)
├── controller/
│ └── HelloController.java # 控制器(类比Vue Router)
├── service/
│ └── HelloService.java # 业务逻辑服务(类比Vue methods)
└── dto/
├── HelloRequest.java # 请求实体类(类比Vue props)
└── HelloResponse.java # 返回实体类(类比Vue data)
第三阶段:数据库和ORM框架
6:数据库
数据库就像一个超级大的Excel表格仓库,专门用来存储和管理数据
6.1 数据库的作用
- 持久化存储:数据不会因为程序关闭而丢失
- 数据共享:多个程序可以同时访问同一份数据
- 数据安全:提供权限控制和备份机制
- 高效查询:快速查找和筛选数据
下面以MySql数据库为例,讲解常用的数据类型与语法
6.2 数据类型
1. 数值类型
整数类型
sql
-- MySQL整数类型
TINYINT -- 1字节,范围:-128到127
SMALLINT -- 2字节,范围:-32768到32767
MEDIUMINT -- 3字节,范围:-8388608到8388607
INT -- 4字节,范围:-2147483648到2147483647
BIGINT -- 8字节,范围:-9223372036854775808到9223372036854775807
浮点数类型
sql
-- MySQL浮点数类型
FLOAT -- 单精度浮点数,4字节
DOUBLE -- 双精度浮点数,8字节
DECIMAL -- 精确小数,用于货币等精确计算
2. 字符串类型
sql
-- MySQL字符串类型
CHAR(n) -- 固定长度字符串,最多255字符
VARCHAR(n) -- 可变长度字符串,最多65535字符
TEXT -- 长文本,最多65535字符
LONGTEXT -- 超长文本,最多4GB
3. 日期时间类型
sql
-- MySQL日期时间类型
DATE -- 日期,格式:YYYY-MM-DD
TIME -- 时间,格式:HH:MM:SS
DATETIME -- 日期时间,格式:YYYY-MM-DD HH:MM:SS
TIMESTAMP -- 时间戳,自动更新
YEAR -- 年份,格式:YYYY
4. 其他类型
sql
-- MySQL其他类型
BOOLEAN -- 布尔值,实际存储为TINYINT(1)
ENUM -- 枚举类型
SET -- 集合类型
JSON -- JSON数据类型(MySQL 5.7+)
6.3 常用语法
1. 数据库操作
创建数据库
sql
-- 创建数据库
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用数据库
USE mydb;
-- 删除数据库。。传说中的删库跑路的删库
DROP DATABASE mydb;
创建表
sql
-- 创建用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
age INT DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
2. 数据操作(CRUD)
插入数据(CREATE)
sql
-- 插入单条数据
INSERT INTO users (name, email, age) VALUES ('张三', 'zhangsan@example.com', 25);
-- 插入多条数据
INSERT INTO users (name, email, age) VALUES
('李四', 'lisi@example.com', 30),
('王五', 'wangwu@example.com', 28);
查询数据(READ)
sql
-- 查询所有数据
SELECT * FROM users;
-- 查询指定字段
SELECT id, name, email FROM users;
-- 条件查询
SELECT * FROM users WHERE age > 25;
-- 排序查询
SELECT * FROM users ORDER BY age DESC;
-- 分页查询
SELECT * FROM users LIMIT 10 OFFSET 0;
更新数据(UPDATE)
sql
-- 更新单条数据
UPDATE users SET age = 26 WHERE id = 1;
-- 更新多条数据
UPDATE users SET age = age + 1 WHERE age < 30;
-- 更新多个字段
UPDATE users SET name = '张三三', email = 'zhangsan3@example.com' WHERE id = 1;
删除数据(DELETE)
sql
-- 删除单条数据
DELETE FROM users WHERE id = 1;
-- 删除多条数据
DELETE FROM users WHERE age < 18;
-- 清空表
DELETE FROM users;
3. 高级查询
连接查询
sql
-- 内连接
SELECT u.name, p.title
FROM users u
INNER JOIN posts p ON u.id = p.user_id;
-- 左连接
SELECT u.name, p.title
FROM users u
LEFT JOIN posts p ON u.id = p.user_id;
-- 右连接
SELECT u.name, p.title
FROM users u
RIGHT JOIN posts p ON u.id = p.user_id;
聚合函数
sql
-- 统计数量
SELECT COUNT(*) FROM users;
-- 计算平均值
SELECT AVG(age) FROM users;
-- 计算总和
SELECT SUM(age) FROM users;
-- 查找最大值
SELECT MAX(age) FROM users;
-- 查找最小值
SELECT MIN(age) FROM users;
-- 分组统计
SELECT age, COUNT(*) FROM users GROUP BY age;
4. 索引和约束
创建索引
sql
-- 创建普通索引
CREATE INDEX idx_name ON users(name);
-- 创建唯一索引
CREATE UNIQUE INDEX idx_email ON users(email);
-- 创建复合索引
CREATE INDEX idx_name_age ON users(name, age);
添加约束
sql
-- 添加主键约束
ALTER TABLE users ADD PRIMARY KEY (id);
-- 添加外键约束
ALTER TABLE posts ADD FOREIGN KEY (user_id) REFERENCES users(id);
-- 添加检查约束
ALTER TABLE users ADD CONSTRAINT chk_age CHECK (age >= 0 AND age <= 150);
示例
sql
-- 创建用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
age INT DEFAULT 0,
status ENUM('active', 'inactive', 'banned') DEFAULT 'active',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 创建文章表
CREATE TABLE posts (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
title VARCHAR(200) NOT NULL,
content TEXT,
status ENUM('draft', 'published', 'archived') DEFAULT 'draft',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 插入测试数据
INSERT INTO users (username, email, password, age) VALUES
('zhangsan', 'zhangsan@example.com', 'password123', 25),
('lisi', 'lisi@example.com', 'password456', 30),
('wangwu', 'wangwu@example.com', 'password789', 28);
INSERT INTO posts (user_id, title, content, status) VALUES
(1, '我的第一篇文章', '这是文章内容...', 'published'),
(1, '草稿文章', '这是草稿内容...', 'draft'),
(2, '李四的文章', '这是李四的文章内容...', 'published');
7.ORM框架
什么是ORM?
ORM (Object-Relational Mapping) = 对象关系映射
简单理解:ORM就像一个翻译官,帮我们在Java对象和数据库表之间进行转换。
ORM的优势
- 简化开发:不需要手写复杂的SQL语句
- 类型安全:编译时就能发现错误
- 代码复用:通用的CRUD操作
- 维护性好:代码更清晰易懂
7.1 MyBatis-Plus
MyBatis-Plus是基于MyBatis的增强工具,提供了更多便利的功能。
类比Vue:
-
MyBatis = Vue的基础响应式系统
-
MyBatis-Plus = Vue + Vuex + 各种插件(功能更强大)
核心功能
1. 代码生成器
作用:自动生成实体类、Mapper、Service等代码
java
// MyBatis-Plus代码生成器类似
自动生成:
- User.java (实体类)
- UserMapper.java (数据访问层)
- UserService.java (业务逻辑层)
2. 通用CRUD操作
作用:提供基础的增删改查操作
java
// MyBatis-Plus中的通用操作
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 查询
public List<User> getUsers() {
return userMapper.selectList(null);
}
// 添加
public int addUser(User user) {
return userMapper.insert(user);
}
// 更新
public int updateUser(User user) {
return userMapper.updateById(user);
}
// 删除
public int deleteUser(Long id) {
return userMapper.deleteById(id);
}
}
条件构造器
作用:动态构建查询条件
java
// MyBatis-Plus中的条件查询
public List<User> searchUsers(String name, Integer minAge) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
if (name != null) {
wrapper.like("name", name);
}
if (minAge != null) {
wrapper.ge("age", minAge);
}
return userMapper.selectList(wrapper);
}
分页插件
作用:自动处理分页查询
java
// MyBatis-Plus中的分页
public IPage<User> getUsers(int current, int size) {
Page<User> page = new Page<>(current, size);
return userMapper.selectPage(page, null);
}
完结