baomidou / mybatis-plus

An powerful enhanced toolkit of MyBatis for simplify development
https://baomidou.com
Apache License 2.0
16.42k stars 4.31k forks source link

新版代码生成配置器在禁用Service生成时,ServiceImpl仍然会import不存在的Service #6015

Closed MuuuShin closed 7 months ago

MuuuShin commented 7 months ago

当前使用版本(必填,否则不予处理)

mybatis-plus-boot-starter以及mybatis-plus-generator均为3.5.5

该问题是如何引起的?(确定最新版也有问题再提!!!)

仅禁用Service的情况下,生成的ServiceImpl仍然带有对应的import以及implement,如图:

image

image

重现步骤(如果有就写完整)

使用Freemarker引擎模板,部分代码如下:

FastAutoGenerator.create()
.templateConfig(builder -> {
                    builder.disable(TemplateType.XML,TemplateType.SERVICE);
                })

报错信息

generator并无报错.但是很明显这个代码肯定跑不了)

MuuuShin commented 7 months ago

我瞄了一眼包里的template应该是正常的 serviceImpl.java.ftl image 但是不知道为啥没生效

nieqiurong commented 7 months ago

看配置是globalConfig().disableServiceInterface(),后面一版本改掉这种方式.

MuuuShin commented 7 months ago

看配置是globalConfig().disableServiceInterface(),后面一版本改掉这种方式.

确实是这样,已经找到了

看文档没有我就没考虑还可能在globalConfig里的情况 image

nieqiurong commented 7 months ago

下个版本用 generator.strategy(strategyConfig().serviceBuilder().disableService().build());

MuuuShin commented 7 months ago

下个版本用 generator.strategy(strategyConfig().serviceBuilder().disableService().build());

好的,感谢!

nieqiurong commented 7 months ago

用3.5.6-SNAPSHOT版本试试看看

LinWanCen commented 7 months ago

我也遇到了,自己调了好多东西,还有模板

image

package io.github.linwancen.share.gen;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import io.github.linwancen.share.common.BaseController;
import io.github.linwancen.util.CmdUtils;
import org.apache.ibatis.annotations.Mapper;
import org.jetbrains.annotations.NotNull;

import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * MyBatis Plus 代码生成器
 * <br>请去掉启动前构建
 * <br>按表名分包,带 package-info.java,不带 I 前缀,Service 层不用接口
 * <br>Controller 模板增加了继承,其他模板删去作者和日期,以便每次生成的代码一致
 * <br>从 Git 获取作者(弃用)
 */
public class MyBatisPlusGen {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/share_sql?serverTimezone=Asia/Shanghai";
        String username = "root";
        String password = "root";
        gen(url, username, password, ".mpg");
    }

    public static void gen(String url, String username, String password, String suffix) {
        Class<?> clazz = MyBatisPlusGen.class;
        String packageName = clazz.getPackage().getName() + suffix;
        String outputDir = outputDir(clazz);
        FreemarkerTemplateEngine templateEngine = new FreemarkerTemplateEngine();
        AtomicReference<String> oldPathRef = new AtomicReference<>();
        FastAutoGenerator.create(url, username, password)
                .globalConfig(builder -> builder
                        .enableSpringdoc()
                        .disableOpenDir()
                        .disableServiceInterface()
                        // .author(gitName())
                        .outputDir(outputDir))
                .dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                    int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                    if (typeCode == Types.SMALLINT) {
                        // 自定义类型转换
                        return DbColumnType.INTEGER;
                    }
                    return typeRegistry.getColumnType(metaInfo);
                }))
                .templateEngine(templateEngine)
                .templateConfig(builder ->{
                    // builder.controller("")
                })
                .strategyConfig(builder -> {
                    builder.entityBuilder().enableFileOverride().enableLombok();
                    builder.mapperBuilder().enableFileOverride().mapperAnnotation(Mapper.class);
                    // 不带 I 前缀 https://blog.csdn.net/nnuan/article/details/116478075
                    builder.serviceBuilder().enableFileOverride()
                            .formatServiceImplFileName("%sService")
                            .formatServiceFileName("%sService");
                    builder.controllerBuilder().enableFileOverride().enableRestStyle().superClass(BaseController.class);
                })
                // 清空类型包名
                .packageConfig(builder -> builder
                        .parent("")
                        .controller(packageName)
                        .service(packageName)
                        .serviceImpl(packageName)
                        .mapper(packageName)
                        .entity(packageName))
                .injectionConfig(builder -> builder.customFile(c -> c
                        .fileName("package-info.java")
                        .formatNameFunction(tableInfo -> "")
                        .templatePath("/templates/package-info.java.ftl")
                        .enableFileOverride()
                ).beforeOutputFile((tableInfo, tempMap) -> {
                    // 包名添加表名包
                    String tablePackage = packageName + "." + tableInfo.getName().replace("_", ".");
                    Object o = tempMap.get("package");
                    if (o instanceof Map) {
                        Map<?, ?> packageMap = (Map<?, ?>) o;
                        HashMap<Object, String> newPackageMap = new HashMap<>();
                        packageMap.forEach((o1, o2) -> {
                            if (packageName.equals(o2)) {
                                newPackageMap.put(o1, tablePackage);
                            }
                        });
                        tempMap.put("package", newPackageMap);
                    }
                    // 存路径
                    Map<OutputFile, String> pathInfo = templateEngine.getConfigBuilder().getPathInfo();
                    if (oldPathRef.get() == null) {
                        oldPathRef.set(pathInfo.get(OutputFile.entity));
                    }
                    // 路径拼接表名包
                    String tableNamePackage = tableInfo.getName().replace("_", "/") + "/";
                    pathInfo.forEach((k, v) -> pathInfo.put(k, oldPathRef.get() + "/" + tableNamePackage));
                }))
                .execute();
    }

    @NotNull
    protected static String outputDir(Class<?> clazz) {
        String outputDir = "";
        URL thisClassPath = clazz.getResource("/");
        if (thisClassPath != null) {
            outputDir = thisClassPath.getPath()
                    .replace("target/test-classes", "src/main/java")
                    .replace("%20", " ");
            if (outputDir.contains(":")) {
                // fix windows OpenDir /D:/... Error
                outputDir = outputDir.substring(1);
            }
        }
        return outputDir;
    }

    @SuppressWarnings("unused")
    @NotNull
    protected static String gitName() {
        AtomicReference<String> result = new AtomicReference<>();
        CmdUtils.exec("git config user.name", 1000, (out, err) ->
                result.set(new String(out.toByteArray(), StandardCharsets.UTF_8).trim()));
        String gitName = result.get();
        if (gitName != null && !gitName.isEmpty()) {
            return gitName;
        }
        return System.getProperty("user.name");
    }
}
package ${package.Controller};

<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
import ${package.Entity}.${entity};
<#if table.serviceInterface>
import ${package.Service}.${table.serviceName};
</#if>
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.RequestMapping;
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
</#if>

/**
 * ${table.comment!} 前端控制器
 */
@Tag(name = "${table.name!}", description = "${table.comment!}")
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>
<#else>
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass}<${entity}, <#if table.serviceInterface>${table.serviceName}<#else>${table.serviceImplName}</#if>> {
    public ${table.controllerName}(<#if table.serviceInterface>${table.serviceName}<#else>${table.serviceImplName}</#if> service) {
        super(service);
    }
<#else>
public class ${table.controllerName} {
</#if>
}
</#if>
JJoinn commented 4 months ago

我也碰到了 我试了两种方式,都无法避免生成了impl文件, 我的版本是3.5.6

FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/member", "root", "root")
                .globalConfig(builder -> {
                    builder.author("Gavin") // 设置作者
                            .outputDir(System.getProperty("user.dir") + "/src/main/java") // 输出目录
                            .disableOpenDir()
                            .disableServiceInterface();
                })
                .packageConfig(builder -> {
                    builder.parent("com.qcz.qmplatform.generator") // 设置父包名
                            .entity("domain.pojo") // 设置实体类包名
                            .mapper("mapper") // 设置 Mapper 接口包名
                            .service("service") // 设置 Service 接口包名
                            .xml("mappers"); // 设置 Mapper XML 文件包名
                })
                .strategyConfig(builder -> {
                    builder.addInclude("tbl_member") // 设置需要生成的表名
                            .addTablePrefix("tbl_", "sys_", "ope_")
                            .entityBuilder()
                            .enableLombok() // 启用 Lombok
                            .enableTableFieldAnnotation() // 启用字段注解
                            .controllerBuilder()
                            .enableRestStyle(); // 启用 REST 风格
//                    builder.serviceBuilder()
//                            .disableServiceImpl(); // 禁用 Service 实现类生成
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用 Freemarker 模板引擎
                .execute(); // 执行生成