首页 > 其他分享 >SpringBoot集成MyBatis-Plus

SpringBoot集成MyBatis-Plus

时间:2024-06-14 09:46:25浏览次数:19  
标签:SpringBoot param entity field Plus import MyBatis table public

SpringBoot集成MyBatis-Plus代码生成器

背景

​ MyBatis-Plus代码生成器相较于MyBatis代码生成器,可以多生成controller层和service层,并且配置更丰富,通过对Freemarker默认模板的修改和增加自定义模板配置适配,可提升开发效率

操作步骤

  • 项目目录结构
    • MyFreemarkerTemplateEngine继承FreemarkerTemplateEngine,用于自定义模板设置
    • templates.generator目录下为自定义的Freemarker模板
    • MybatisCeneratorTest为测试类

image-20240613091141166

1.pom文件中增加依赖

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.5.7</version>
        </dependency>
		<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

2.在test目录下新增测试类用于生成文件

  • 代码中的mysql连接,用户名和密码需要做相应替换
  • 具体配置参考代码生成器配置
@SpringBootTest
public class MybatisGeneratorTest {
    @Test
    public void generatorSqlFile() {
        // 使用 FastAutoGenerator 快速配置代码生成器
        FastAutoGenerator fastAutoGenerator = FastAutoGenerator.create("jdbc:mysql://192.168.11.128:3306/pai_coding?serverTimezone=GMT%2B8&tinyInt1isBit=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true", "lichao", "Huawei12#$")
                .globalConfig(builder -> {
                    builder.author("lichao") // 设置作者
                            .outputDir("src\\main\\java") // 输出目录
                            .enableSwagger();  // 开启 Swagger 模式

                })
                .dataSourceConfig(builder ->
                        builder.databaseQueryClass(SQLQuery.class)
                                .typeConvert(new MySqlTypeConvert())
                                .dbQuery(new MySqlQuery())
                )
                .packageConfig(builder -> {
                    builder.parent("com.lichao.tobebetter") // 设置父包名
                            .entity("entity") // 设置实体类包名
                            .mapper("mapper") // 设置 Mapper 接口包名
                            .service("service") // 设置 Service 接口包名
                            .serviceImpl("service.impl") // 设置 Service 实现类包名
                            .pathInfo(Collections.singletonMap(OutputFile.xml,
                                "src\\main\\resources\\mapper")); // 设置 Mapper XML 文件包名, 取代.xml()避免使用父包名前缀
                });

        // 增加自定义模板配置
        fastAutoGenerator.injectionConfig(consumer -> {
            List<CustomFile> customFileList = new ArrayList<>();
            CustomFile customFile = new CustomFile.Builder().fileName("RetJson.java")
                    .templatePath("/templates/generator/retjson.java.ftl")
//                    .enableFileOverride()
                    .build();
            customFileList.add(customFile);
            consumer.customFile(customFileList);
        });

        // 该部分仅用于模板调试测试,用于禁止对应类生成
//        fastAutoGenerator.templateConfig(builder -> {
//            builder//.disable(TemplateType.XML)         // 禁用实体类生成
//                    .disable(TemplateType.CONTROLLER)
//                    .disable(TemplateType.SERVICE)
//                    .disable(TemplateType.SERVICE_IMPL)
////                    .disable(TemplateType.MAPPER);
//        });

        // Entity策略配置
        fastAutoGenerator.strategyConfig(builder -> {
            builder.addInclude("banner") // 设置需要生成的表名
                .entityBuilder()
                .disableSerialVersionUID()
                .enableLombok()
                .enableRemoveIsPrefix()
                .enableTableFieldAnnotation()
                .enableFileOverride()
                .logicDeleteColumnName("deleted")
                .naming(NamingStrategy.no_change)
                .columnNaming(NamingStrategy.underline_to_camel)
                .addSuperEntityColumns("created_by", "created_time", "updated_by", "updated_time")
                .formatFileName("%sEntity");
        });

        // Controller 策略配置
        fastAutoGenerator.strategyConfig(builder -> {
            builder.controllerBuilder()
                .template("/templates/generator/controller.java")
//                .enableHyphenStyle()
                .enableRestStyle()
                .formatFileName("%sAction")
                .enableFileOverride();
        });

        // Service 策略配置
        fastAutoGenerator.strategyConfig(builder -> {
            builder.serviceBuilder()
                .serviceTemplate("/templates/generator/service.java")
                .serviceImplTemplate("/templates/generator/serviceImpl.java")
                .enableFileOverride()
                .formatServiceFileName("%sService")
                .formatServiceImplFileName("%sServiceImpl");
        });

        // Mapper和Xml 策略配置
        fastAutoGenerator.strategyConfig(builder -> {
            builder.mapperBuilder()
                .mapperAnnotation(Mapper.class)  // 开启 @Mapper 注解
                .mapperTemplate("/templates/generator/mapper.java")  // 指定mapper模板路径
                .mapperXmlTemplate("/templates/generator/mapper.xml") // 指定xml文件模板路径
                .enableFileOverride()            // 覆盖已生成文件
                .enableBaseResultMap()           // 启用 BaseResultMap 生成
                .enableBaseColumnList()          // 启用 BaseColumnList
                .formatMapperFileName("%sMapper")   // 格式化 Mapper 文件名称
                .formatXmlFileName("%sMapper");     // 格式化 XML 实现类文件名称
        });

        // 使用Freemarker 模板引擎,MyFreemarkerTemplateEngine继承FreemarkerTemplateEngine
        fastAutoGenerator.templateEngine(new MyFreemarkerTemplateEngine());

        fastAutoGenerator.execute();
    }
}

3.为了指定输出目录覆盖了原有的自定义模板输出方法,增加了RetJson模板用于通用返回,RetJson不覆盖输出,配置修改在MybatisGeneratorTest.java增加自定义模板配置部分

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.apache.commons.lang3.StringUtils;

import javax.validation.constraints.NotNull;
import java.io.File;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;

public class MyFreemarkerTemplateEngine extends FreemarkerTemplateEngine {
    public static final String UTIL_CLASS_STR = "retjson.java;";
    @Override
    protected void outputCustomFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
        String entityName = tableInfo.getEntityName();
        String parentPath = getPathInfo(OutputFile.parent);
        customFiles.forEach(file -> {
            if (UTIL_CLASS_STR.contains(file.getFileName().toLowerCase(Locale.ENGLISH))) {
            // 对自定义模板控制输出路径,其他自定义模板按原来逻辑处理
                String fileName = String.format(parentPath + File.separator + "utils" + File.separator + "%s", file.getFileName());
                outputFile(new File(fileName), objectMap, file.getTemplatePath(), file.isFileOverride());
            } else {
                String filePath = StringUtils.isNotBlank(file.getFilePath()) ? file.getFilePath() : parentPath;
                if (StringUtils.isNotBlank(file.getPackageName())) {
                    filePath = filePath + File.separator + file.getPackageName().replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
                }
                Function<TableInfo, String> formatNameFunction = file.getFormatNameFunction();
                String fileName = filePath + File.separator + (null != formatNameFunction ? formatNameFunction.apply(tableInfo) : entityName) + file.getFileName();
                outputFile(new File(fileName), objectMap, file.getTemplatePath(), file.isFileOverride());
            }
        });
    }
}

4.模板代码

  • 模板代码修改了原始的继承基类,只适配简单的增删改查
  • Controller层使用RetJson类作为通用返回
  • SQL新增方法默认数据库主键属性为id,数据库主键自增

controller.java.ftl

package ${package.Controller};

import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import ${package.Parent}.utils.RetJson;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>

import javax.validation.Valid;

/**
 * <p>
 * ${table.comment!} 前端控制器
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
<#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} {
<#else>
public class ${table.controllerName} {
</#if>
    @Autowired
    private ${table.serviceName} ${table.serviceName?uncap_first}Impl;

    @ApiOperation(value = "${table.comment}详情", response = ${entity}.class)
    @GetMapping(value = "/info/{id}")
    public  Object info(@PathVariable Long id) {
        Object data = ${table.serviceName?uncap_first}Impl.info(id);
        return RetJson.ok(data);
    }

    @ApiOperation(value = "${table.comment}新增")
    @PostMapping(value = "/add")
    public  Object add(@Valid @RequestBody ${entity} param) {
        ${table.serviceName?uncap_first}Impl.save(param);
        return RetJson.ok();
    }

    @ApiOperation(value = "${table.comment}修改")
    @PostMapping(value = "/modify")
    public  Object modify(@Valid @RequestBody ${entity} param) {
        ${table.serviceName?uncap_first}Impl.modify(param);
        return RetJson.ok();
    }

    @ApiOperation(value = "${table.comment}删除(单个条目)")
    @GetMapping(value = "/remove/{id}")
    public  Object remove(@PathVariable Long id) {
        ${table.serviceName?uncap_first}Impl.remove(id);
        return RetJson.ok();
    }
}
</#if>

entity.java.ftl

package ${package.Entity};

<#list table.importPackages as pkg>
import ${pkg};
</#list>
<#if springdoc>
import io.swagger.v3.oas.annotations.media.Schema;
<#elseif swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
    <#if chainModel>
import lombok.experimental.Accessors;
    </#if>
</#if>

/**
 * <p>
 * ${table.comment!}
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
<#if entityLombokModel>
@Getter
@Setter
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if table.convert>
@TableName("${schemaName}${table.name}")
</#if>
<#if springdoc>
@Schema(name = "${entity}", description = "${table.comment!}")
<#elseif swagger>
@ApiModel(value = "${entity}对象", description = "${table.comment!}")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#elseif entitySerialVersionUID>
public class ${entity} implements Serializable {
<#else>
public class ${entity} {
</#if>
<#if entitySerialVersionUID>

    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if field.keyFlag>
        <#assign keyPropertyName="${field.propertyName}"/>
    </#if>

    <#if field.comment!?length gt 0>
        <#if springdoc>
    @Schema(description = "${field.comment}")
        <#elseif swagger>
    @ApiModelProperty("${field.comment}")
        <#else>
    /**
     * ${field.comment}
     */
        </#if>
    </#if>
    <#if field.keyFlag>
        <#-- 主键 -->
        <#if field.keyIdentityFlag>
    @TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
        <#elseif idType??>
    @TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
        <#elseif field.convert>
    @TableId("${field.annotationColumnName}")
        </#if>
        <#-- 普通字段 -->
    <#elseif field.fill??>
    <#-- -----   存在字段填充设置   ----->
        <#if field.convert>
    @TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
        <#else>
    @TableField(fill = FieldFill.${field.fill})
        </#if>
    <#elseif field.convert>
    @TableField("${field.annotationColumnName}")
    </#if>
    <#-- 乐观锁注解 -->
    <#if field.versionField>
    @Version
    </#if>
    <#-- 逻辑删除注解 -->
    <#if field.logicDeleteField>
    @TableLogic
    </#if>
    private ${field.propertyType} ${field.propertyName};
</#list>
<#------------  END 字段循环遍历  ---------->
<#if !entityLombokModel>
    <#list table.fields as field>
        <#if field.propertyType == "boolean">
            <#assign getprefix="is"/>
        <#else>
            <#assign getprefix="get"/>
        </#if>

    public ${field.propertyType} ${getprefix}${field.capitalName}() {
        return ${field.propertyName};
    }

    <#if chainModel>
    public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
    <#else>
    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
    </#if>
        this.${field.propertyName} = ${field.propertyName};
        <#if chainModel>
        return this;
        </#if>
    }
    </#list>
</#if>
<#if entityColumnConstant>
    <#list table.fields as field>

    public static final String ${field.name?upper_case} = "${field.name}";
    </#list>
</#if>
<#if activeRecord>

    @Override
    public Serializable pkVal() {
    <#if keyPropertyName??>
        return this.${keyPropertyName};
    <#else>
        return null;
    </#if>
    }
</#if>
<#if !entityLombokModel>

    @Override
    public String toString() {
        return "${entity}{" +
    <#list table.fields as field>
        <#if field_index==0>
            "${field.propertyName} = " + ${field.propertyName} +
        <#else>
            ", ${field.propertyName} = " + ${field.propertyName} +
        </#if>
    </#list>
        "}";
    }
</#if>
}

mapper.java.ftl

package ${package.Mapper};

import ${package.Entity}.${entity};
<#if mapperAnnotationClass??>
import ${mapperAnnotationClass.name};
</#if>

import java.util.List;

/**
 * <p>
 * ${table.comment!} Mapper 接口
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
<#if mapperAnnotationClass??>
@${mapperAnnotationClass.simpleName}
</#if>
<#if kotlin>
interface ${table.mapperName}
<#else>
public interface ${table.mapperName} {
    /**
    * ${table.comment!}详情
    * @param id
    * @return
    */
    ${entity} getById(Long id);

    /**
    * ${table.comment!}新增
    * @param param 根据需要进行传值
    * @return
    */
    void save(${entity} param);

    /**
    * ${table.comment!}修改
    * @param param 根据需要进行传值
    * @return
    */
    void modify(${entity} param);

    /**
    * ${table.comment!}删除(单个条目)
    * @param id
    * @return
    */
    void removeById(Long id);
}
</#if>

mapper.xml.ftl

<?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="${package.Mapper}.${table.mapperName}">

<#if enableCache>
    <!-- 开启二级缓存 -->
    <cache type="${cacheClassName}"/>

</#if>
<#if baseResultMap>
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
<#list table.fields as field>
<#if field.keyFlag><#--生成主键排在第一位-->
        <id column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
<#list table.commonFields as field><#--生成公共字段 -->
        <result column="${field.name}" property="${field.propertyName}" />
</#list>
<#list table.fields as field>
<#if !field.keyFlag><#--生成普通字段 -->
        <result column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
    </resultMap>

</#if>
<#if baseColumnList>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
<#list table.fields as field>
        ${r"`"}${field.columnName}${r"`"}<#if field_has_next>,</#if>
</#list>
    </sql>

    <#if baseColumnList>
    <select id="getById" resultMap="BaseResultMap">
        select
            <include refid="Base_Column_List"/>
        from ${table.name}
        where id = ${r"#{id}"}
    </select>
    <#else>
    <select id="getById" resultType="${package.Entity}.${entity}">
        select
            <#list table.fields as field>
                ${r"`"}${field.columnName}${r"`"}<#if field_has_next>,</#if>
            </#list>
            ${table.fieldNames}
        from ${table.name}
        where id = ${r"#{id}"}
    </select>
    </#if>

    <insert id="save">
        insert into ${table.name}
        (
        <#list table.fields as field>
            <#if field.columnName == "id">
            <#else>
            ${r"`"}${field.columnName}${r"`"}<#if field_has_next>,</#if>
            </#if>
        </#list>
        )
        values (
        <#list table.fields as field>
            <#if field.columnName == "id">
            <#elseif field.columnName == 'create_time' || field.columnName == 'update_time'>
            now()<#if field_has_next>,</#if>
            <#else >
            ${r"#{"}${field.propertyName}${r"}"}<#if field_has_next>,</#if>
            </#if>
        </#list>
        )
    </insert>

    <update id="modify">
        update ${table.name}
        <set>
        <#list table.fields as field>
            <#if field.columnName == "id" || field.columnName == 'create_time'>
            <#else >
            <if test="${field.propertyName} != null and ${field.propertyName} != ''">
                ${r"`"}${field.columnName}${r"`"} = ${r"#{"}${field.propertyName}${r"}"},
            </if>
            </#if>
        </#list>
        </set>
        where id = ${r"#{id}"}
    </update>

    <delete id="removeById">
        delete from ${table.name} where id = ${r"#{id}"}
    </delete>
</#if>
</mapper>

retjson.java.ftl

package ${package.Parent}.utils;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
* <p>
* ${table.comment!} 返回工具类
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if kotlin>
open class RetJSON {

}
<#else>
@Getter
@Setter
@ToString
public class RetJson {
    public static final int SUCCESS_CODE = 0;

    public static final int FAILED_CODE = -1;

    /** 状态码 */
    private int code;
    /** 消息 */
    private String msg;
    /** 数据 */
    private Object data;

    public RetJson() {
        this.code = SUCCESS_CODE;
        this.msg = "success";
    }

    public RetJson(Object data) {
        this.data = data;
        this.code = SUCCESS_CODE;
        this.msg = "success";
    }

    public RetJson(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    /**
    * 执行成功
    */
    public static Object ok(){
        return new RetJson();
    }

    /**
    * 执行成功
    * @param data 返回数据
    */
    public static Object ok(Object data){
        return new RetJson(data);
    }

    /**
    * 执行失败
    * @param msg   消息
    */
    public static Object err(String msg){
        return new RetJson(FAILED_CODE, msg);
    }
}
</#if>

service.java.ftl

package ${package.Service};

import ${package.Entity}.${entity};
import ${superServiceClassPackage};

import java.util.List;

/**
 * <p>
 * ${table.comment!} 服务类
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
<#if kotlin>
interface ${table.serviceName}
<#else>
public interface ${table.serviceName} {
    /**
    * ${table.comment!}详情
    * @param id 主键
    * @return ${entity}
    */
    ${entity} info(Long id);

    /**
    * ${table.comment!}新增
    * @param param 根据需要进行传值
    */
    void save(${entity} param);

    /**
    * ${table.comment!}修改
    * @param param 根据需要进行传值
    */
    void modify(${entity} param);

    /**
    * ${table.comment!}删除(单个条目)
    * @param id
    */
    void remove(Long id);
}
</#if>

serviceImpl.java.ftl

package ${package.ServiceImpl};

import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
<#if generateService>
import ${package.Service}.${table.serviceName};
</#if>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * ${table.comment!} 服务实现类
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
@Service
<#if kotlin>
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>()<#if generateService>, ${table.serviceName}</#if> {

}
<#else>
public class ${table.serviceImplName} <#if generateService> implements ${table.serviceName}</#if> {
    @Autowired
    private ${table.mapperName} ${table.mapperName?uncap_first};

    /**
    * ${table.comment!}详情
    * @param id 主键
    * @return ${entity}
    */
    @Override
    public ${entity} info(Long id) {
        return ${table.mapperName?uncap_first}.getById(id);
    }

    /**
    * ${table.comment!}新增
    * @param param 根据需要进行传值
    */
    @Override
    public void save(${entity} param) {
        ${table.mapperName?uncap_first}.save(param);
    }

    /**
    * ${table.comment!}修改
    * @param param 根据需要进行传值
    */
    @Override
    public void modify(${entity} param) {
        ${table.mapperName?uncap_first}.modify(param);
    }

    /**
    * ${table.comment!}删除(单个条目)
    * @param id
    */
    @Override
    public void remove(Long id) {
        ${table.mapperName?uncap_first}.removeById(id);
    }
}
</#if>

生成代码结构如下:

image-20240614091141627

  • 自定义模板文件

​ 查看源码com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine,如果有自定义文件,先生成自定义文件,再生成默认模板,所以自定义文件不能替换默认模板

image-20240614091354472

  • 默认模板自定义模板路径

​ 查看源码com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine中mapper和xml文件生成部分可知自定义模板由getMapperTemplate方法获取

image-20240614092457819

​ 默认获取自常量ConstVal.TEMPLATE_MAPPER

image-20240614092818566

​ 可通过方法mapperTemplate方法覆盖

image-20240614092757247

参考

标签:SpringBoot,param,entity,field,Plus,import,MyBatis,table,public
From: https://www.cnblogs.com/litayun/p/18247166

相关文章

  • 设置springboot scheduled多线程,解决多个定时任务并发问题(转载)
    项目上有几个定时任务都是同时间点要执行的,最近发现多个定时任务为单线程排队执行,后来经过查资料发现@schedule注解默认是单线程的,如果定时任务比较多或者有的定时任务比较耗时,会影响到其他定时任务的执行,通过以下方法解决多个定时任务同时并发执行问题。第1种:增加配置类@Configu......
  • 详细描述MyBatis缓存的实现原理?
    MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以使用简单的XML或注解进行配置和映射原始类型、接口和Java的POJO(PlainOldJavaObjects,普通的Java对象)为数据库中......
  • 使用MyBatis的注意事项有哪些
    这篇文章给大家分享的是有关使用MyBatis的注意事项有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、MyBatis的HelloWord1.根据xml配置文件(全局配置文件mybatis-config.xml)创建一个SqlSessionFactory对象有数据源一些运行环境信息<?xml ve......
  • MyBatis之工作原理,简单CRUD,一篇让你明白原理
    一、MyBatis之工作原理MyBatis是一个半自动映射框架。所谓半自动,是相对Hibernate全表映射而言的,MyBatis需要手动匹配提供POJO、SQL和映射关系。我们知道,jdbc有四个核心对象(1)DriverManager,用于注册数据库连接(2)Connection,与数据库连接对象(3)Statement/PrepareStatement,操作数......
  • 基于SpringBoot+Vue+uniapp的餐厅点餐系统的详细设计和实现(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 基于SpringBoot+Vue+uniapp的球队训练信息管理系统的详细设计和实现(源码+lw+部署文档
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • 基于SpringBoot+Vue+uniapp的高校图书馆个性化服务的详细设计和实现(源码+lw+部署文档
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • java:【@ComponentScan】和【@SpringBootApplication】扫包范围的冲突
    #代码结构如下:注意【com.chz.myBean.branch】和【com.chz.myBean.main】这两个包是没有生重叠的。主程序【MyBeanTest1、MyBeanTest2、MyBeanTest3】这两个类是在包【com.chz.myBean.main】下#示例代码【pom.xml】<dependency><groupId>org.springframework.bo......
  • 【java计算机毕设】图书管理系统javaweb java MySQL springboot vue html maven送文档
    1项目功能【java计算机专业学长毕业设计分享】智慧图书管理系统JavaSpringBootvueHTMLMySQL前后端分离2项目介绍系统功能:智慧图书管理系统包括管理员和用户两种角色。管理员的功能包括在个人中心修改个人信息和密码,管理员功能模块管理管理员。基础数据管理模......
  • springboot Invalid bound statement (not found): com.elitel.xxx.dao.xxx 错误处
    如果这篇文章能给你带来帮助,不胜荣幸,如果有错误也请批评指正,一起学习,共同进步!今天给同事看了个问题,发现了这个问题,之前也遇见过,可是没有遇见这种情况,这次我记录一下。首先来说,造成这个错误的原因是什么。它是在SpringBoot应用程序中遇到“Invalidboundstatement(not......