Week 1-8: Spring Boot 学习计划完整项目
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
101
week3/src/main/java/com/learn/service/jpa/StudentJpaService.java
Normal file
101
week3/src/main/java/com/learn/service/jpa/StudentJpaService.java
Normal file
@@ -0,0 +1,101 @@
|
||||
package com.learn.service.jpa;
|
||||
|
||||
import com.learn.entity.Student;
|
||||
import com.learn.repository.jpa.StudentJpaRepository;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* JPA 版本的学生服务
|
||||
*
|
||||
* @Transactional:声明式事务。方法执行过程中如果抛出 RuntimeException,
|
||||
* 所有数据库操作会自动回滚。保证数据一致性。
|
||||
* readOnly=true 表示只读,性能更好(跳过脏检查)。
|
||||
*/
|
||||
@Service
|
||||
public class StudentJpaService {
|
||||
|
||||
private final StudentJpaRepository repository;
|
||||
|
||||
public StudentJpaService(StudentJpaRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
// ==================== 增删改查 ====================
|
||||
|
||||
@Transactional
|
||||
public Student add(Student student) {
|
||||
return repository.save(student); // JPA: save() 同时用于新增和更新
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Student> list() {
|
||||
return repository.findAll(Sort.by(Sort.Direction.DESC, "score"));
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Optional<Student> getById(Long id) {
|
||||
return repository.findById(id);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Optional<Student> update(Long id, Student updated) {
|
||||
return repository.findById(id).map(existing -> {
|
||||
if (updated.getName() != null) existing.setName(updated.getName());
|
||||
if (updated.getAge() > 0) existing.setAge(updated.getAge());
|
||||
if (updated.getEmail() != null) existing.setEmail(updated.getEmail());
|
||||
if (updated.getScore() >= 0) existing.setScore(updated.getScore());
|
||||
// JPA 的 save: 有 ID 且存在则更新,无 ID 则新增
|
||||
return repository.save(existing);
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public boolean delete(Long id) {
|
||||
if (repository.existsById(id)) {
|
||||
repository.deleteById(id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ==================== 搜索 ====================
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Student> searchByKeyword(String keyword) {
|
||||
return repository.searchByKeyword(keyword);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Student> findByName(String name) {
|
||||
return repository.findByNameContaining(name);
|
||||
}
|
||||
|
||||
// ==================== 分页(第 5 天) ====================
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Page<Student> page(int pageNum, int pageSize) {
|
||||
// JPA 分页:PageRequest.of(页码从0开始, 每页条数, 排序)
|
||||
PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize,
|
||||
Sort.by(Sort.Direction.DESC, "score"));
|
||||
return repository.findAll(pageRequest);
|
||||
}
|
||||
|
||||
// ==================== 统计 ====================
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public long count() {
|
||||
return repository.count();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public long countByScoreRange(int min, int max) {
|
||||
return repository.countByScoreRange(min, max);
|
||||
}
|
||||
}
|
||||
131
week3/src/main/java/com/learn/service/mp/StudentMpService.java
Normal file
131
week3/src/main/java/com/learn/service/mp/StudentMpService.java
Normal file
@@ -0,0 +1,131 @@
|
||||
package com.learn.service.mp;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.learn.entity.Student;
|
||||
import com.learn.repository.mp.StudentMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* MyBatis-Plus 版本的学生服务
|
||||
*
|
||||
* 重点对比与 JPA 版本的差异:
|
||||
* 1. 新增:MP 用 insert(),JPA 用 save()
|
||||
* 2. 查询:MP 用 LambdaQueryWrapper 构建条件,JPA 用方法命名或 JPQL
|
||||
* 3. 分页:MP 用 Page + IPage,JPA 用 PageRequest + Page
|
||||
* 4. 更新:MP 用 updateById(),JPA 用 save()
|
||||
*
|
||||
* 关键武器:LambdaQueryWrapper
|
||||
* 用它构建条件,不用担心列名写错(基于 Lambda 表达式,编译期安全)
|
||||
* 例如:wrapper.eq(Student::getName, "张三") → WHERE name = '张三'
|
||||
*/
|
||||
@Service
|
||||
public class StudentMpService {
|
||||
|
||||
private final StudentMapper mapper;
|
||||
|
||||
public StudentMpService(StudentMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
// ==================== 增删改查 ====================
|
||||
|
||||
@Transactional
|
||||
public Student add(Student student) {
|
||||
mapper.insert(student); // MP: insert() 只用于新增
|
||||
return student; // insert 后 student.id 已被自动回填
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Student> list() {
|
||||
// MP 条件构造器:空的 wrapper → 查全部
|
||||
// orderByDesc 让结果按成绩降序
|
||||
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.orderByDesc(Student::getScore);
|
||||
return mapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Optional<Student> getById(Long id) {
|
||||
return Optional.ofNullable(mapper.selectById(id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Optional<Student> update(Long id, Student updated) {
|
||||
Student existing = mapper.selectById(id);
|
||||
if (existing == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (updated.getName() != null) existing.setName(updated.getName());
|
||||
if (updated.getAge() > 0) existing.setAge(updated.getAge());
|
||||
if (updated.getEmail() != null) existing.setEmail(updated.getEmail());
|
||||
if (updated.getScore() >= 0) existing.setScore(updated.getScore());
|
||||
|
||||
mapper.updateById(existing); // MP 用 updateById
|
||||
return Optional.of(existing);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public boolean delete(Long id) {
|
||||
return mapper.deleteById(id) > 0;
|
||||
}
|
||||
|
||||
// ==================== 搜索 ====================
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Student> searchByKeyword(String keyword) {
|
||||
return mapper.searchByKeyword(keyword);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Student> findByName(String name) {
|
||||
// MP 的 Lambda 方式构建条件
|
||||
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(Student::getName, name); // WHERE name LIKE '%name%'
|
||||
return mapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
// ==================== 分页(第 5 天) ====================
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public IPage<Student> page(int pageNum, int pageSize) {
|
||||
// MP 分页:Page<Student>(页码, 每页条数)
|
||||
Page<Student> page = new Page<>(pageNum, pageSize);
|
||||
|
||||
// 按成绩降序
|
||||
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.orderByDesc(Student::getScore);
|
||||
|
||||
return mapper.selectPage(page, wrapper);
|
||||
}
|
||||
|
||||
// ==================== 统计 ====================
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public long count() {
|
||||
return mapper.selectCount(null); // null = 无筛选条件
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public long countByScoreRange(int min, int max) {
|
||||
// MP 的 Lambda 方式构建范围条件
|
||||
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.between(Student::getScore, min, max); // WHERE score BETWEEN min AND max
|
||||
return mapper.selectCount(wrapper);
|
||||
}
|
||||
|
||||
// ==================== 高级查询(演示 LambdaQueryWrapper 的威力) ====================
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Student> findExcellentStudents(int threshold) {
|
||||
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.ge(Student::getScore, threshold) // WHERE score >= ?
|
||||
.orderByDesc(Student::getScore);
|
||||
return mapper.selectList(wrapper);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user