当前位置: 代码网 > it编程>编程语言>Java > mybatis-plus自定义业务实现方式

mybatis-plus自定义业务实现方式

2026年03月17日 Java 我要评论
结构src/main/java/com/example/demo/├── demoapplication.java // 启动类├── entity/user.java

结构

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 实现类(自定义方法实现)
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") // 对应数据库表名
public class user {
    @tableid(type = idtype.auto)
    private long id;         // 主键自增
    private string username; // 用户名
    private string email;    // 邮箱
    private integer age;     // 年龄
    private integer status;  // 状态: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:根据年龄范围查询(也可通过wrapper实现,这里演示xml方式) "
    list<user> selectbyagerange(@param("minage") integer minage, @param("maxage") integer maxage);

    " 自定义sql:统计不同年龄段的用户数量 "
    list<map<string, object>> countuserbyagegroup();
}

mapper xml 文件(usermapper.xml)

resources/mapper 下创建,存放自定义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">

    <!-- 对应 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>
    

    <!-- 对应 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:根据年龄范围查询用户(调用mapper自定义sql)"
    list<user> getuserbyagerange(integer minage, integer maxage);

    "示例2:批量插入用户(基于mp的savebatch扩展)"
    int batchinsertusers(list<user> userlist);

    "示例3:根据用户名模糊查询并按年龄降序排序(纯mp wrapper实现)"
    list<user> listusersbyusernamelike(string usernamekeyword);

    "示例4:统计不同年龄段的用户数量(调用mapper自定义sql)"
    map<string, long> countuserbyagegroup();

    "示例5:逻辑删除+状态更新(业务组合操作)"
    boolean disableuserbyid(long userid);
}

service 实现类(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:调用mapper自定义sql实现年龄范围查询"
    @override
    public list<user> getuserbyagerange(integer minage, integer maxage) {
        // 非空校验(业务层必备)
        if (minage == null || maxage == null || minage > maxage) {
            throw new illegalargumentexception("年龄范围参数不合法");
        }
        return basemapper.selectbyagerange(minage, maxage);
    }

    "示例2:批量插入(扩展mp的savebatch,增加批次控制和返回值)"
    @override
    @transactional(rollbackfor = exception.class) // 事务保证
    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实现模糊查询+排序"
    @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); // 调用iservice的默认方法
    }

    "示例4:统计年龄段数量(处理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:组合业务操作(逻辑删除+状态更新)"
    @override
    @transactional(rollbackfor = exception.class)
    public boolean disableuserbyid(long userid) {
        // 1. 查询用户是否存在
        user user = getbyid(userid);
        if (user == null) {
            return false;
        }
        // 2. 更新状态为禁用(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("批量插入成功数量:" + count);
    }

    // 测试示例3:模糊查询+排序
    @test
    public void testlistbyusernamelike() {
        list<user> userlist = userservice.listusersbyusernamelike("张");
        system.out.println("用户名含'张'的用户(按年龄降序):" + userlist);
    }

    // 测试示例4:统计年龄段
    @test
    public void testcountagegroup() {
        map<string, long> agegroupmap = userservice.countuserbyagegroup();
        system.out.println("年龄段统计:" + agegroupmap);
    }

    // 测试示例5:禁用用户
    @test
    public void testdisableuser() {
        boolean success = userservice.disableuserbyid(1l);
        system.out.println("禁用用户是否成功:" + success);
    }
}

数据库

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 '状态:1-正常 0-禁用',
  primary key (`id`)
) engine=innodb default charset=utf8mb4;

总结

自定义service方法的核心

继承 iservice/serviceimpl 后,可通过 basemapper 调用自定义mapper方法,或通过 wrapper 直接使用mp的内置方法。

关键规范

  • 业务层必须做参数校验,避免非法输入;
  • 批量操作/组合操作需加 @transactional 保证事务;
  • 复杂sql建议写在xml中,简单条件用 wrapper 更简洁。

扩展思路

自定义方法可覆盖“查询封装、批量操作、业务组合、数据统计”等场景,核心是复用mp的基础能力,同时适配业务需求。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com