Springboot +tk.mybatis+generator 自动生成Mapper xml 插件配置及 常见 错误 MapperException 、BaseSelectProvider

1.新建sprintboot项目,先把需要的 选项勾选上

如Mysql,jdbc,web,mybatis 等你需要的,这是第一步,如果你需要配置tk.mybatis,你需要额外的导入 新的jar包 以及 pom.xml 的 build 中plugin generator 插件

1.1 首先你要 配置你的 application.properties 文件, 我的配置如下, username,pwd 改成自己的用户密码
#mybatis 配置
mybatis.type-aliases-package=com.jzj.tkdemo.domain.po
#mapper 文件存放xml
mybatis.mapper-locations=classpath:/mapper/*Mapper.xml
#启用驼峰规则将数据库 user_name 实体转化为userName
mybatis.configuration.map-underscore-to-camel-case=true

#数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=xxx
spring.datasource.password=xxx
1.2 pom 中要引入 tk.mybatis的包,如下 pom.xml
1.3 pom 中要引入 tk.sprint boot start 的包,如下 pom.xml
1.4 pom 中要引入build 的generator 的maven插件 指明 generator的配置文件 generatorConfig.xml 所在位置,如下 pom.xml
1.5 项目resource 下 新建目录 mapper文件夹 存放 *Mapper.xml文件 及 generator 文件夹存放 generatorConfig.xml配置文件

下面是我的pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.jzj</groupId>
    <artifactId>tkdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>tkdemo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- tk-mybatis 及分页插件-->
        <!--mybatis tk框架-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>1.2.4</version>
        </dependency>
        <!---分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!---mybatis tk框架-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>


            <!--Mybatis generator 映射文件自动生成-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.21</version>
                    </dependency>
                    <dependency>
                        <groupId>tk.mybatis</groupId>
                        <artifactId>mapper</artifactId>
                        <version>4.0.4</version>
                    </dependency>
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.7</version>
                    </dependency>
                </dependencies>
                <!--Mybatis generator 配置文件 generatorCongig.xml 的路径-->
                <configuration>
                    <configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.先配置Generator maven 插件

咱们先说 插件,Generator 插件最简单 ,首先你的有数据库 我的数据库 test,然后你的有 数据库的表 user, 这些创建完成后,你可以先配置插件

2.1创建test 库 的数据表 语句
CREATE TABLE `user` (
  `id` int(32) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `user_name` varchar(32) NOT NULL DEFAULT '' COMMENT '"用户姓名"',
  `password` varchar(50) NOT NULL DEFAULT '' COMMENT '用户密码',
  `safe` tinyint(1) NOT NULL COMMENT '是否安全',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
2.2 配置generator的配置文件generatorConfig.xml

这个generatorConfig.xml 是 我们生成插件 所需要的配置信息 如 你的PO实体包,你的Mapper文件路径,你的实体类名称及 你的要创建sqlMapper的数据库表信息

1.你需要新建一个base 文件夹,放你的BaseMapper 后面所有的数据库Mapper都继承这个Base 我的是 com.jzj.tkdemo.domain.base包
2.你需要新建一个 po文件夹,放你的数据库是实体 com.jzj.tkdemo.domain.po
3.你需要resources 文件夹下 有 mapper文件夹, 存放你的数据库XML文件
4.你需要在resources 文件夹下 有 generator文件夹, 存放你的数据库generatorConfig.xml 文件

下面是 我的 generatorConfig.xml 配置文件信息, 这个xml在 resources下面的 generator 文件夹下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

    <properties resource="application.properties"/>

    <context defaultModelType="flat" id="mysql" targetRuntime="MyBatis3Simple">
        <!-- 生成的Java文件的编码 -->
        <property name="javaFileEncoding" value="UTF-8"/>


        <!-- 生成根Mapper 所有的Mappwe都 继承这个 根   -->
        <!-- 这个地方 注意一下 , 和你配置的 Application上面 MapperScan 的 mapper包扫描 不要再一个文件夹下,
        比如我的 我的包扫描是 @MapperScan("com.jzj.tkdemo.dao") 这个地方是 其他的包
        总而言之就是  BaseMapper 不要放在Mapper的 包扫描中, 具体原因看 下面介绍
        -->
        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <property name="mappers" value="com.jzj.tkdemo.domain.base.BaseMapper"/>
        </plugin>


        <jdbcConnection
                driverClass="${spring.datasource.driver-class-name}"
                connectionURL="${spring.datasource.url}"
                userId="${spring.datasource.username}"
                password="${spring.datasource.password}">
        </jdbcConnection>

        <!-- 生成的数据库实体 PO 所在位置 -->
        <javaModelGenerator targetPackage="com.jzj.tkdemo.domain.po"
                            targetProject="src/main/java">
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- MAPPER XML java 文件所在位置-->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject="src/main/resources">
        </sqlMapGenerator>

        <!-- Mapper.java 所在的文件夹,也就是mapper接口 文件夹
            1,ANNOTATEDMAPPER:会生成使用Mapper接口+Annotation的方式创建(SQL生成在annotation中),不会生成对应的XML;
            2,XMLMAPPER:会生成Mapper接口,接口完全依赖XML;
            3.这个包是 com.jzj.tkdemo.dao  不要把上面的BaseMapper 放在下面 切记切记
        -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.jzj.tkdemo.dao"
                             targetProject="src/main/java">
        </javaClientGenerator>


        <!-- user 是数据库表, UserPO 是你根据报表 要生成的 实体类-->
        <table schema="" tableName="user" domainObjectName="UserPO"></table>

    </context>
</generatorConfiguration>
2.3 然后你可以看到看到 你的 工程中的 maven 插件中 有一个 mybatis-generator 插件, 可以直接双击运行,你的 dao,po,mapper 文件夹中就会自动生成

在这里插入图片描述

UserPOMapper.java,UserPO.java,UserPOMapper.xml 文件自动生成到相应文件夹

UserPOMapper.java 自动继承BaseMapper在这里插入图片描述
UserPO.java 自动生成及注解在这里插入图片描述
UserPOMapper.xml 自动生成在这里插入图片描述

综上,generator 插件配置完成

3.然后开始使用,写自己的Controller,Service及Impl实现

3.1 写一个Controller, 新建com.jzj.tkdemo.controller 文件夹,新建TKUserController类 用于web访问
package com.jzj.tkdemo.controller;

import com.jzj.tkdemo.domain.po.UserPO;
import com.jzj.tkdemo.service.ITkUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 描述:
 *
 * @author jiazijie
 * @since 2019-04-02 下午9:47
 */
@RestController
public class TkUserController {

    @Autowired
    private ITkUserService tkUserService;

    @RequestMapping("selectUser/{id}")
    private String getUser(@PathVariable String id) {
        UserPO user = tkUserService.selectById(Integer.parseInt(id));
        return user.toString();
    }


    @RequestMapping("addUser")
    private int addUser() {
        UserPO user = new UserPO();
        user.setUserName("aaa");
        user.setPassword("pwd");
        user.setSafe(true);
        int count = tkUserService.insertUser(user);
        return count;
    }

    @RequestMapping("updateUser/{name}")
    private void update(@PathVariable String name) {
        UserPO user = new UserPO();
        user.setUserName(name);
        user.setPassword("pwd");
        user.setSafe(true);
        user.setId(1);
        tkUserService.updateUser(user);
    }
}

3.2 写接口ITKUserService 及实现

接口 ITkUserService

package com.jzj.tkdemo.service;

import com.jzj.tkdemo.domain.po.UserPO;

/**
 * 描述:
 *
 * @author jiazijie
 * @since 2019-04-03 下午10:47
 */
public interface ITkUserService {

    UserPO  selectById(Integer id);

    int insertUser(UserPO userPO);

    int updateUser(UserPO userPO);
}

实现 TKUserServiceImpl

package com.jzj.tkdemo.service;

import com.jzj.tkdemo.dao.UserPOMapper;
import com.jzj.tkdemo.domain.po.UserPO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 描述:
 *
 * @author jiazijie
 * @since 2019-04-03 下午10:48
 */
@Service
public class TkUserServiceImpl implements ITkUserService {


    @Resource
    private UserPOMapper userPOMapper;

    @Override
    public UserPO selectById(Integer id) {

        UserPO userPO = userPOMapper.selectByPrimaryKey(id);
        return userPO;
    }

    @Override
    public int insertUser(UserPO userPO) {
        int count = userPOMapper.insert(userPO);
        return count;
    }

    @Override
    public int updateUser(UserPO userPO) {
       int count = userPOMapper.updateByPrimaryKey(userPO);
       return count;
    }
}

3.3 然后 看你的Application 入口函数

加上Mapper 包扫描 ,扫描你自己的Mapper 文件,BaseMapper 接口千万别 写进这个包里面 @MapperScan(“com.jzj.tkdemo.dao”)
我的入口函数

package com.jzj.tkdemo;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

@SpringBootApplication
@MapperScan("com.jzj.tkdemo.dao")
public class TkdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(TkdemoApplication.class, args);
    }

}

大功告成, 可以 启动了,然后访问Controller 页面

添加用户User http://localhost:8080/addUser 返回 1 添加数量
查询用户User http://localhost:8080/selectUser/1 查询 id=1 的员工信息
更新用户User http://localhost:8080/updateUser/aaabbb 将员工Id为1的 员工 姓名设置为 aaabbb

4. 遇到的错误 ,这才是重点

4.1 第一个错误,最经常犯的 Application启动类上 没有 MapperScan Mapper包扫描

Spring bean 注入失败 Injection of resource dependencies failed NoSuchBeanDefinitionException Dependency annotations 错误:

nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘tkUserServiceImpl’: Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘com.jzj.tkdemo.dao.UserPOMapper’ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}

这是因为 Spring 无法发现你的 mapper文件 ,在Application上加上包扫描 就可以了 @MapperScan(“com.jzj.tkdemo.dao”)

3.2 第二个错误,最经常犯的 Application启动类上 加上 MapperScan Mapper包扫描 结果导错了MapperScan的 包

正确导入的是 import tk.mybatis.spring.annotation.MapperScan;
错误导入的是 import org.mybatis.spring.annotation.MapperScan;

报错 java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseInsertProvider.() 等信息

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method (tk.mybatis.mapper.provider.base.BaseInsertProvider.dynamicSQL).  Cause: java.lang.InstantiationException: tk.mybatis.mapper.provider.base.BaseInsertProvider] with root cause

java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseInsertProvider.<init>()
	at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_181]
	at java.lang.Class.newInstance(Class.java:412) ~[na:1.8.0_181]
	at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:117) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.builder.annotation.ProviderSqlSource.getBoundSql(ProviderSqlSource.java:103) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:292) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:64) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:40) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:46) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:558) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) ~[mybatis-3.4.5.jar:3.4.5]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:63) ~[mybatis-3.4.5.jar:3.4.5]
	at com.sun.proxy.$Proxy83.update(Unknown Source) ~[na:na]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198) ~[mybatis-3.4.5.jar:3.4.5]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185) ~[mybatis-3.4.5.jar:3.4.5]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433) ~[mybatis-spring-1.3.1.jar:1.3.1]
	at com.sun.proxy.$Proxy71.insert(Unknown Source) ~[na:na]
	at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:278) ~[mybatis-spring-1.3.1.jar:1.3.1]
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:57) ~[mybatis-3.4.5.jar:3.4.5]
或者 不用加MapperScan 你可以不导入 MapperScan jar包

直接在你的UserPOMapper 类上加上 @Mapper 注解 也可以,但是这样 每一个Mapper都加,费力不讨好,所以还是用包扫描 比较好
在这里插入图片描述

3.3 BaseMapper 在你的Mapper包 扫描内, 和其他的数据库Mapper 在同一个包扫描内

这个错误比较隐晦,藏的比较深,一般大家为了方便Mapper.java 放在一起,就将BaseMapper 父类放在类Mapper 包内,自动生成的Mapper.java 也在同一个包内,方便 但是这样会导致问题,报的错误时 reflect 反射类型错误,说类转换失败 其实就是 你把BaseMapper放在类 mapper包扫描中

报错:Invocation of init method failed;
nested exception is tk.mybatis.mapper.MapperException: tk.mybatis.mapper.MapperException: java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class

tk.mybatis.mapper.MapperException 错误
java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class 错误

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baseMapper' defined in file [/Users/jiazijie/Documents/offtime/sblearn/tkdemo/target/classes/com/jzj/tkdemo/dao/BaseMapper.class]: Invocation of init method failed; nested exception is tk.mybatis.mapper.MapperException: tk.mybatis.mapper.MapperException: java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1762) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:830) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]

项目github 地址:https://github.com/jzjie007/spboot/tree/master/tkdemo

搞定, 欢迎拍砖 这只是一次简单的 sprint boot 和 generator 和 tk.mybatis 的结合

猜你喜欢

转载自blog.csdn.net/u010134642/article/details/89007485