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