mybatis-plus自定義業(yè)務(wù)實現(xiàn)方式
結(jié)構(gòu)
src/main/java/com/example/demo/ ├── DemoApplication.java // 啟動類 ├── entity/User.java // 實體類 ├── mapper/UserMapper.java // Mapper 接口(含自定義SQL) ├── service/IUserService.java // Service 接口(自定義方法聲明) └── service/impl/UserServiceImpl.java // Service 實現(xiàn)類(自定義方法實現(xiàn)) src/main/resources/ ├── application.yml // 配置文件 └── mapper/UserMapper.xml // 自定義SQL的XML文件(如需) src/test/java/com/example/demo/ └── UserServiceTest.java // 測試類
實體類 User
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("t_user") // 對應(yīng)數(shù)據(jù)庫表名
public class User {
@TableId(type = IdType.AUTO)
private Long id; // 主鍵自增
private String username; // 用戶名
private String email; // 郵箱
private Integer age; // 年齡
private Integer status; // 狀態(tài):1-正常 0-禁用
}
Mapper 接口(UserMapper.java)
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface UserMapper extends BaseMapper<User> {
" 自定義SQL:根據(jù)年齡范圍查詢(也可通過Wrapper實現(xiàn),這里演示XML方式) "
List<User> selectByAgeRange(@Param("minAge") Integer minAge, @Param("maxAge") Integer maxAge);
" 自定義SQL:統(tǒng)計不同年齡段的用戶數(shù)量 "
List<Map<String, Object>> countUserByAgeGroup();
}
Mapper XML 文件(UserMapper.xml)
在 resources/mapper 下創(chuàng)建,存放自定義SQL:
<?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">
<!-- 對應(yīng) selectByAgeRange 方法 -->
<select id="selectByAgeRange" resultType="com.example.demo.entity.User">
SELECT id, username, email, age, status
FROM t_user
WHERE age BETWEEN #{minAge} AND #{maxAge}
</select>
<!-- 對應(yīng) countUserByAgeGroup 方法 -->
<select id="countUserByAgeGroup" resultType="java.util.Map">
SELECT
CASE
WHEN age < 18 THEN '未成年'
WHEN age BETWEEN 18 AND 30 THEN '青年'
WHEN age BETWEEN 31 AND 50 THEN '中年'
ELSE '老年'
END AS age_group,
COUNT(*) AS user_count
FROM t_user
GROUP BY age_group
</select>
</mapper>
Service 接口(IUserService.java)
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.User;
import java.util.List;
import java.util.Map;
public interface IUserService extends IService<User> {
"示例1:根據(jù)年齡范圍查詢用戶(調(diào)用Mapper自定義SQL)"
List<User> getUserByAgeRange(Integer minAge, Integer maxAge);
"示例2:批量插入用戶(基于MP的saveBatch擴展)"
int batchInsertUsers(List<User> userList);
"示例3:根據(jù)用戶名模糊查詢并按年齡降序排序(純MP Wrapper實現(xiàn))"
List<User> listUsersByUsernameLike(String usernameKeyword);
"示例4:統(tǒng)計不同年齡段的用戶數(shù)量(調(diào)用Mapper自定義SQL)"
Map<String, Long> countUserByAgeGroup();
"示例5:邏輯刪除+狀態(tài)更新(業(yè)務(wù)組合操作)"
boolean disableUserById(Long userId);
}
Service 實現(xiàn)類(UserServiceImpl.java)
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
"示例1:調(diào)用Mapper自定義SQL實現(xiàn)年齡范圍查詢"
@Override
public List<User> getUserByAgeRange(Integer minAge, Integer maxAge) {
// 非空校驗(業(yè)務(wù)層必備)
if (minAge == null || maxAge == null || minAge > maxAge) {
throw new IllegalArgumentException("年齡范圍參數(shù)不合法");
}
return baseMapper.selectByAgeRange(minAge, maxAge);
}
"示例2:批量插入(擴展MP的saveBatch,增加批次控制和返回值)"
@Override
@Transactional(rollbackFor = Exception.class) // 事務(wù)保證
public int batchInsertUsers(List<User> userList) {
if (userList == null || userList.isEmpty()) {
return 0;
}
// MP的saveBatch默認批次是1000,這里自定義批次大小為500
boolean success = saveBatch(userList, 500);
return success ? userList.size() : 0;
}
"示例3:純Wrapper實現(xiàn)模糊查詢+排序"
@Override
public List<User> listUsersByUsernameLike(String usernameKeyword) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.like(usernameKeyword != null, User::getUsername, usernameKeyword) // 非空才拼接條件
.orderByDesc(User::getAge); // 按年齡降序
return list(wrapper); // 調(diào)用IService的默認方法
}
"示例4:統(tǒng)計年齡段數(shù)量(處理Mapper返回的Map)"
@Override
public Map<String, Long> countUserByAgeGroup() {
List<Map<String, Object>> resultList = baseMapper.countUserByAgeGroup();
Map<String, Long> ageGroupMap = new HashMap<>();
for (Map<String, Object> map : resultList) {
String ageGroup = (String) map.get("age_group");
Long userCount = (Long) map.get("user_count");
ageGroupMap.put(ageGroup, userCount);
}
return ageGroupMap;
}
"示例5:組合業(yè)務(wù)操作(邏輯刪除+狀態(tài)更新)"
@Override
@Transactional(rollbackFor = Exception.class)
public boolean disableUserById(Long userId) {
// 1. 查詢用戶是否存在
User user = getById(userId);
if (user == null) {
return false;
}
// 2. 更新狀態(tài)為禁用(0)
user.setStatus(0);
return updateById(user);
}
}
測試類(UserServiceTest.java)
import com.example.demo.DemoApplication;
import com.example.demo.entity.User;
import com.example.demo.service.IUserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@SpringBootTest(classes = DemoApplication.class)
public class UserServiceTest {
@Autowired
private IUserService userService;
// 測試示例1:年齡范圍查詢
@Test
public void testUserByAgeRange() {
List<User> userList = userService.getUserByAgeRange(18, 30);
System.out.println("18-30歲用戶:" + userList);
}
// 測試示例2:批量插入
@Test
public void testBatchInsert() {
List<User> userList = new ArrayList<>();
User u1 = new User();
u1.setUsername("張三");
u1.setEmail("zhangsan@test.com");
u1.setAge(25);
u1.setStatus(1);
User u2 = new User();
u2.setUsername("李四");
u2.setEmail("lisi@test.com");
u2.setAge(28);
u2.setStatus(1);
userList.add(u1);
userList.add(u2);
int count = userService.batchInsertUsers(userList);
System.out.println("批量插入成功數(shù)量:" + count);
}
// 測試示例3:模糊查詢+排序
@Test
public void testListByUsernameLike() {
List<User> userList = userService.listUsersByUsernameLike("張");
System.out.println("用戶名含'張'的用戶(按年齡降序):" + userList);
}
// 測試示例4:統(tǒng)計年齡段
@Test
public void testCountAgeGroup() {
Map<String, Long> ageGroupMap = userService.countUserByAgeGroup();
System.out.println("年齡段統(tǒng)計:" + ageGroupMap);
}
// 測試示例5:禁用用戶
@Test
public void testDisableUser() {
boolean success = userService.disableUserById(1L);
System.out.println("禁用用戶是否成功:" + success);
}
}
數(shù)據(jù)庫
CREATE TABLE `t_user` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主鍵', `username` varchar(50) NOT NULL COMMENT '用戶名', `email` varchar(100) DEFAULT NULL COMMENT '郵箱', `age` int DEFAULT NULL COMMENT '年齡', `status` int DEFAULT 1 COMMENT '狀態(tài):1-正常 0-禁用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
總結(jié)
自定義Service方法的核心:
繼承 IService/ServiceImpl 后,可通過 baseMapper 調(diào)用自定義Mapper方法,或通過 Wrapper 直接使用MP的內(nèi)置方法。
關(guān)鍵規(guī)范:
- 業(yè)務(wù)層必須做參數(shù)校驗,避免非法輸入;
- 批量操作/組合操作需加
@Transactional保證事務(wù); - 復(fù)雜SQL建議寫在XML中,簡單條件用
Wrapper更簡潔。
擴展思路:
自定義方法可覆蓋“查詢封裝、批量操作、業(yè)務(wù)組合、數(shù)據(jù)統(tǒng)計”等場景,核心是復(fù)用MP的基礎(chǔ)能力,同時適配業(yè)務(wù)需求。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
IntelliJ IDEA將導(dǎo)入的項目轉(zhuǎn)成maven項目
這篇文章主要介紹了IntelliJ IDEA將導(dǎo)入的項目轉(zhuǎn)成maven項目,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
基于Java注解(Annotation)的自定義注解入門介紹
要深入學(xué)習(xí)注解,我們就必須能定義自己的注解,并使用注解,在定義自己的注解之前,我們就必須要了解Java為我們提供的元注解和相關(guān)定義注解的語法2013-04-04
java8新特性-lambda表達式入門學(xué)習(xí)心得
這篇文章主要介紹了java8新特性-lambda表達式入門學(xué)習(xí)心得,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03

