文章目录
- 1:Spring boot
- 1.1:SpringBoot框架
- 1.2:框架间联系
- 1.3:各层框架的使用
- 1:mapper层
- 2:Controller层
- 1.4:应用输出运行基本信息
- 2:Restful 介绍
- 1:restFul设计规范
- 2:接口传参
- 1:get接口传参
- 2:post接口如何传参
- 3:利用Spring boot开发restFul接口
- 1:创建pojo层
- 2:创建mapper层
- 3:创建service层
- 4:创建controller层
- 5:配置application.properties
- 6:springboot启动自动打开浏览器
- 7:创建表和插入表
- 7:主类启动服务
- 8:单元测试
- 9:项目pom.xml依赖
- 4:实战优化
- 4.1:第三节优化
- 4.2:mapper.xml详解
- 4.3:mybatis写入获取自增主键
- 5:问题汇总
- 5.1:Invalid bound statement (not found) .mapper文件
- 5.2:a compent requied a bean of "自己定义的mapper类",配置加载不到spring容器中
- 5.3:对于所有的找到不到mapper类或者加载不到配置文件的问题
- 5.4:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
- 5.5:Parameter 'xxx' not found. Available parameters are [arg1, arg0, param1, param2].
1:Spring boot
1.1:SpringBoot框架
SpringBoot框架一般分为View层、Controller层、Service层、Mapper层、pojo层。
View层:视图层,根据接到的数据展示页面给用户
Controller层:响应用户需求,决定用什么视图,需要准备什么数据来显示。Controller层负责前后端交互,接收前端请求,调用Service层,接收Service层返回的数据,最后返回具体的数据和页面到客户端
Service层:Service层也可以分为三个方面
(1)接口:用来声明方法
(2)继承实现接口
(3)impl:接口的实现(将mapper和service进行整合的文件)
Service层存放业务逻辑处理,有一些关于数据库处理的操作,但是不是直接和数据库打交道,有接口,
也有接口的实现方法,在impl实现接口类中需要导入mapper类,mapper层是直接与数据库进行操作的。
- Mapper层:也可以称为DAO层,是数据库CRUD的接口,只有方法名,具体实现在mapper.xml文件中,对数据库进行数据持久化操作(把数据放到持久化的介质中,同时提供CRUD操作)
- src/main/resource文件夹中的mapper.xml文件,里面存储的是真正的数据库CRUD语句
- Pojo层:存放实体类,与数据库中的属性基本保持一致,一般包括getter、setter、toString方法(未使用插件lombok的情况下)
1.2:框架间联系
controller层(处理前台发送的请求)--->service定义接口(业务逻辑)--->serviceImpl(对接口函数进行实现)
--->mapper(Mapper接口,方法名与Mapper.xml中定义的statement的id相同)--->mapper.xml(写sql语句查询数据库)
由此可见,Service层在Mapper层之上,在Controller层之下,既调用Mapper接口,又提供接口给Controller层用。
分层后,访问数据库和进行Service之间分工明确,对Service的需求修改,无需修改Mapper层,如果有访问数据库的新需求,也只需要在Mapper层修改。
1.3:各层框架的使用
1:mapper层
mapper层一般单独的为一个包
- 扫描mapper第一种方式
每个mapper接口上添加@Mapper注解 这个注解会通过spring boot启动注解自动扫描 - 扫描mapper第二种方式
在main函数中使用@MapperScan(basePackages = “com.demo.mapper”)标注dao所在的包名,这种方式如果引入会有红色波浪线问题 再加上@Repository这个注解就没有了
两种方式选择其一就行。我实践的是方式1
2:Controller层
@RestController注解表示每个方法返回的数据将直接写入响应体
我们有每个操作的路由(@GetMapping、@PostMapping、@PutMapping和@DeleteMapping,对应于 HTTP GET、POST、PUT和DELETE调用)
接口如何处理传参,我们可以使用@RequestParam
注解实现获取前端URL中的参数。具体使用见例子
url请求:("/basic/user?name=小红") 此时会将name=小红传递给方法的name参数,多个参数使用&连接。
@GetMapping(value = "/user_info")
public List<user> getUser(@RequestParam(value = "name") String name) {
//此时我们可以通过定义的name属性获取url中属性为name的值。
}
1.4:应用输出运行基本信息
spring boot可以使用spring.banner.location属性更改程序启动时打印的横幅。比如默认的spring boot图形,我们在resources目录下新建banner.txt将需要打印的内容写在其中即可
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
**************************************************************************************
${application.title} ${application.version}
Base on Spring Boot ${spring-boot.version}
**************************************************************************************
System.properties:
--------------------------------------------------------------------------------------
java.specification.version = ${java.specification.version}
java.specification.vendor = ${java.specification.vendor}
java.specification.name = ${java.specification.name}
java.vm.specification.version = ${java.vm.specification.version}
java.vm.specification.vendor = ${java.vm.specification.vendor}
java.vm.specification.name = ${java.vm.specification.name}
java.home = ${java.home}
java.version = ${java.version}
java.vendor = ${java.vendor}
java.vendor.url = ${java.vendor.url}
java.vm.version = ${java.vm.version}
java.vm.vendor = ${java.vm.vendor}
java.vm.name = ${java.vm.name}
java.class.version = ${java.class.version}
java.class.path = ${java.class.path}
java.library.path = ${java.library.path}
java.io.tmpdir = ${java.io.tmpdir}
java.ext.dirs = ${java.ext.dirs}
os.name = ${os.name}
os.arch = ${os.arch}
os.version = ${os.version}
user.name = ${user.name}
user.home = ${user.home}
user.dir = ${user.dir}
使用时在application.proerties中配置banner.txt文件的位置。不配置也会默认加载。
spring.banner.location=classpath:banner.txt
运行查看效果
2:Restful 介绍
- http是在应用层的超文本传输协议。
- Restful 基于HTTP、URI、XML、JSON等标准和协议,支持轻量级、跨平台、跨语言的架构设计。是Web服务的一种新的架构风格(一种思想)。
其客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:
GET用来获取资源,
POST用来新建资源(也可以用于更新资源),
PUT用来更新资源,
DELETE用来删除资源;
其利用URL进行资源请求,根据http响应码,判断请求状态,进而做出提醒。
1:restFul设计规范
URI = scheme “😕/” host “:” port “/” path [ “?” query ][ “#” fragment ]
scheme: 指底层用的协议,如http、https、ftp
host: 服务器的IP地址或者域名
port: 端口,http默认为80端口
path: 访问资源的路径,就是各种web 框架中定义的route路由
通常一个RESTful API的path组成如下:
/{version}/{resources}/{resource_id}
version:API版本号,有些版本号放置在头信息中也可以,通过控制版本号有利于应用迭代。
resources:资源,RESTful API推荐用小写英文单词的复数形式。
resource_id:资源的id,访问或操作该资源。
query: 对于需要传递的参数可以使用?分隔后加到后面,比如key=value等
查询字符串,为发送给服务器的参数,在这里更多发送数据分页、排序等参数。
fragment: 锚点,定位到页面的资源
1:url命名规范
- 1:不用大写字母,所有单词使用英文且小写。
- 2:连字符用中杠"-“而不用下杠”_"
- 3:正确使用 "/"表示层级关系,URL的层级不要过深,并且越靠前的层级应该相对越稳定
- 4:结尾不要包含正斜杠分隔符"/"
- 5:URL中不出现动词,用请求方式表示动作
*:6:资源表示用复数不要用单数 - 7:不要使用文件扩展名
2:接口传参
接口传参可以使用@RequestParam注解实现,@RequestParam将查询字符串参数的值绑定属性名到方法的参数属性中。此查询字符串参数不是required。如果请求中不存在,则使用defaultValue
接口传参可以使用@RequestParam 或者@RequestBody
@RequestParam 传参可以是单独的参数;
@RequestBody则是吧参数都封装为了一个bean对象进行传参
以@RequestParam举例
@PostMapping (value = "/insert")
public String insert(@RequestParam (value = "host") String host,@RequestParam (value = "port") String port,@RequestParam (value = "email") String email,@RequestParam (value = "report_name") String report_name,@RequestParam (value = "password") String password) {
String sql = String.format("insert into insert_email_getaway_config_info(host,port,email,password,report_name) values ('%s','%s','%s','%s','%s')", host, port, email, password, report_name);
System.out.println(sql);
hsqlDB.insertData(sql);
return "insert success";
}
接口调用,可以使用postman测试接口
url格式如下,后面参数和path用?分隔,各个参数间用&分隔
/insert?host=127.0.0.1&port=8888&email=1&password=1&report_name=小红
一般建议用@RequestBody封装对象来传参,利于维护!!!
@PostMapping(value = "/insert_email_getaway_config")
public String insertEmailGetawayConfig(@RequestBody EmailGetawayBean email) {
//获取值 email.getEmail();
}
@Data
public class EmailGetawayBean {
String host, port, email, password, report_name;
}
1:get接口传参
//接口使用举例 http://localhost:9999/view/get_info?type=sms
@GetMapping(value = "/get_system_config")
public List<systemConfig> getSystemConfigInfo(@RequestParam(required = false) String type) {//使用type}
2:post接口如何传参
3:利用Spring boot开发restFul接口
1:创建pojo层
用于对应数据库对应的属性,必须提供对应的getter,setter,toString方法。如果使用lombok使用@data注解即可实现。
映射方式1:
Spring boot查询数据库底层使用mybatis进行交互,如果没有明确写明实体类和表的字段映射,就是同名对应,匹配成功则数据交互成功,匹配失败则数据交互失败,导致接收空值。
@Data
public class user{
String name,age,like,addr;
}
映射方式2:使用@data+@TableField
如:把表中的id映射到bean的user_id字段
@TableField(value="id")
private string user_id
多表关联查询存在字段重名或者不一致问题可以使用这种方式解决,不想使用@TableField也可以在mapper.xml配置中使用resultMap来完成映射。详见第四节
2:创建mapper层
底层利用mybatis和数据库进行交互,提供CRUD增删改查操作。
单独创建mapper的包放mapper类,使用注解@Mapper
利用@Select(“${sqlStr}”)创造一个查询语句,将查询结果映射为user
@Param(“sqlStr”) 注解为传参映射作用
@Mapper
public interface QueryHsqlMapper {
//根据路由和传参的sql语句执行数据库操作
@Select("${sqlStr}")
List<user> getData(@Param("sqlStr") String sqlStr);
}
利用类上的@Mapper注解可实现springboot启动时自动扫描。
使用步骤如下
- 1:在main函数中使用注解表明该mapper类所在的包位置或者mapper类中使用@mapper注解。选其一
@MapperScan(basePackages = "com.demo.mapper")
@SpringBootApplication()
public class Main {
private static final Logger LOG = LoggerFactory.getLogger(Main.class.getName());
public static void main(String[] args) throws IOException, InterruptedException {
SpringApplication.run(Main.class, args);
}
- 2:在resources目录下创建mapper.xml配置文件
写入内容
<?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.demo.mapper.QueryHsqlMapper">
</mapper>
- 3:application.properties文件中使用mapper.xml配置mybatis
mybatis.mapper-locations=classpath*:/mapper/*Mapper.xml
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.cache-enabled=false
3:创建service层
1:创建接口
2:实现接口,使用注解@Slf4j @Service
public interface QueryHsqlDB {
List<user> getData(String sqlStr);
}
@Slf4j
@Service
public class QueryHsqlDBImple implements QueryHsqlDB {
@Resource
QueryHsqlMapper mapper;
@Override
public List<user> getData(String sqlStr) {
List<user> data = mapper.getData(sqlStr);
return data;
}
}
4:创建controller层
定义请求的方式(get/put/post/delete),请求的路径等,使用注解
@RestController
@CrossOrigin
@RequestMapping({“/data”}) //定义url访问的路径
@RestController
@CrossOrigin
@RequestMapping({"/data"})
public class Controller {
@Resource
private QueryHsqlDB queryHsqlDB;
@GetMapping(value = "/user")
public List<user> getuser() {
String sql="select * from user";
return queryHsqlDB.getData(sql)
}
访问时路径即可/data/user即会调用getuser方法,将返回结果传给客户端
此种方式查询的sql是写死的,存在硬编码的问题,后续进行优化。
5:配置application.properties
springboot采用properties文件作为总配置文件,默认application.properties放在src/main/resource文件,在、该配置文件中可以使用通配符*用来表示相同类型的文件。比如多个Mapper.xml
下面介绍一些常用配置
# tomcat启动也就是访问web的端口号
server.port=11080
#xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
mybatis.mapper-locations=classpath*:/mapper/*Mapper.xml
# 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射
mybatis.configuration.map-underscore-to-camel-case=true
#jdbc数据库相关配置
#指定数据库驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库jdbc连接url地址,serverTimezone设置数据库时区东八区
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/login?characterEncoding=UTF-8&serverTimezone=GMT%2B8
#数据库账号
spring.datasource.username=root
spring.datasource.password=root
数据库的创建表和插入数据
#建表,利用*实现模糊匹配
spring.datasource.schema=classpath:create*.sql
#插入数据
#进行该配置后,每次启动程序,程序都会运行resources/insert.sql文件,对数据库的数据操作,相当于往表中插入数据。
spring.datasource.data=classpath:insert*.sql
#前端的静态资源加载,一般为resoources路径下的文件,个人创建/resources/templates目录存放
spring.resources.static-locations=classpath:templates/
spring.mvc.view.suffix=.html
# 自定义属性用于配置启动时自动打开浏览器
openProject.isOpen=true
openProject.web.openUrl=http://localhost:${server.port}/#/
自定义属性配置
#自定义属性
com.name="111"
com.name1="222"
# 取值需要在类上使用@Configuration注解后再使用@Value(value="${com.name}")的方式获取赋值并使用
@Value(value="${com.name}")
private String name;//既可以将name值赋予变量
6:springboot启动自动打开浏览器
windows和linux均可,使用@Configuration完成和配置文件的映射,用@Value(“${属性}”) 获取属性的值
先在application.properties中定义属性
server.port=9999
openProject.web.openUrl=http://localhost:${server.port}/#/
@Configuration
public class GetLinuxIp {
@Value("${openProject.web.openUrl}") //完成属性映射
private static String url;
private static final Logger LOG = LoggerFactory.getLogger(GetLinuxIp.class.getName());
public static String getInet4Address() { //获取运行服务器的ip
Enumeration<NetworkInterface> nis;
String ip = null;
try {
nis = NetworkInterface.getNetworkInterfaces();
for (; nis.hasMoreElements();) {
NetworkInterface ni = nis.nextElement();
Enumeration<InetAddress> ias = ni.getInetAddresses();
for (; ias.hasMoreElements();) {
InetAddress ia = ias.nextElement();
//ia instanceof Inet6Address && !ia.equals("")
if (ia instanceof Inet4Address && !ia.getHostAddress().equals("127.0.0.1")) {
ip = ia.getHostAddress();
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return ip;
}
public static void AutoOpenUrl() throws InterruptedException, IOException {//打开服务器的逻辑实现
Runtime run = Runtime.getRuntime();
String os = System.getProperty("os.name").toLowerCase();
if (os.indexOf("win") >= 0) { //判断操作系统
try {
run.exec("rundll32 url.dll,FileProtocolHandler " + url);
} catch (Exception e) {
e.printStackTrace();
LOG.error(e.getMessage());
}
} else if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) {
String currentIp = GetLinuxIp.getInet4Address();
String[] browsers = {"firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape"};
String browser = null;
for (int count = 0; count < browsers.length && browser == null; count++) {
if (Runtime.getRuntime().exec(
new String[]{"which", browsers[count]}).waitFor() == 0) {
browser = browsers[count];
}
}
if (browser != null) {
Runtime.getRuntime().exec(new String[]{browser, url.replaceAll("localhost", currentIp)});
}
}
LOG.info("启动浏览器打开项目成功:" + url);
}
}
7:创建表和插入表
一般用于测试或者demo中的数据模拟,比如结合hsqldb等内存数据库,表的加载可以在application.properties中进行使用,详见步骤5。
比如创建用户表:create.sql
CREATE TABLE user_info(
user_id varchar(255) NOT NULL PRIMARY KEY, // PRIMARY KEY设置主键
name varchar(255) DEFAULT NULL,
age varchar(255) DEFAULT NULL,
like varchar(255) DEFAULT NULL,
addr varchar(255) DEFAULT NULL
);
进行数据插入:insert.sql
insert into user_info values("001","小红","18","篮球","西安");
7:主类启动服务
SpringApplication提供了一种方便的方法来引导从main()方法启动的 Spring 应用程序。在许多情况下,您可以委托给静态SpringApplication.run方法,如下例所示:
如果在mapper类中已经使用了@mapper注解此处就不需要@MapperScan(basePackages = “com.demo.mapper”)
@MapperScan(basePackages = "com.demo.mapper") //用于扫描mapper文件,一般指定到包路径,在mapper层使用@mapper注解同理两种均可
@SpringBootApplication() //main函数的固定注解
public class Main {
private static final Logger LOG = LoggerFactory.getLogger(Main.class.getName());
public static void main(String[] args) throws IOException, InterruptedException {
SpringApplication.run(Main.class, args); //指定启动的主类即可
LOG.info("started......");
} }
8:单元测试
常用测试工具
JUnit :单元测试 Java 应用程序的事实标准。
Spring Test & Spring Boot Test:Spring Boot 应用程序的实用程序和集成测试支持。
AssertJ:一个流畅的断言库。
Hamcrest:匹配器对象库(也称为约束或谓词)。
Mockito:Java 模拟框架。
JSONassert : JSON 的断言库。
JsonPath:JSON 的 XPath。
@SpringBootTest 指定测试类在SpringBoot环境下运行
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Main.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ControllerTest {
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种
}
@Test /*用于模拟接口请求查看返回的结果*/
public void testGet() throws Exception {
ResultActions perform = mockMvc.perform(MockMvcRequestBuilders.get("/data"));
String contentAsString = perform.andReturn().getResponse().getContentAsString();
System.out.println(contentAsString);
Assert.assertTrue(contentAsString.contains("小红"));
}
9:项目pom.xml依赖
连接mysql的话需要引入相关依赖。
springboot常用依赖说明 依赖说明:
1:mybatis和mybatis-plus只引入其中一个包就行了,不要重复
2:结合spring boot引入的必须是 **<artifactId>mybatis-plus-spring-boot-starter</artifactId>
**不能是mybatis-plus-core。否则会导致加载mapper.xml配置文件失败,报**Invalid bound statement (not found)**
<groupId>org.example</groupId>
<artifactId>smhll_redis_restful</artifactId>
<version>1.0-SNAPSHOT</version>
<name>smhll_redis_restful</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<fastjson>1.2.41</fastjson>
<springboot>1.5.15.RELEASE</springboot>
<redis.version>4.2.0</redis.version>
<lombok.version>1.18.20</lombok.version>
<commons.io.version>2.5</commons.io.version>
<mybatis.version>2.1.2</mybatis.version>
<commons.version>3.11</commons.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${springboot}</version>
<scope>test</scope>
</dependency>
<!-- -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<version>${springboot}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${springboot}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- 添加内存数据库 org.hsqldb用于测试 -->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!--还是引入其中一个实现类-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
</dependencies>
<!--项目打包依赖-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest> <!--指定运行测试类的路径-->
<mainClass>com.demo.Main</mainClass>
</manifest>
</archive>
</configuration>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
4:实战优化
4.1:第三节优化
关于第三节中controller中的sql硬编码问题进行优化。
采用sql放在mapper.xml中进行维护,后期更新配置不用改代码
4.2:mapper.xml详解
MyBatis的关注点在POJO与SQL之间的映射关系,mapper.xml就是实现这种关系的。里面还可以加if判断,foreach循环等操作。接口类型包括select查询,insert插入,delete删除等等对于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.training.mapper.UserMapper">
<!--定义接口方法对应的 SQL 语句,传参通过mapper类传入-->
<select id="findByName" parameterType="String" resultType="com.training.entity.User">
select * from user where name=#{name}
</select>
<!--多个传参时parameterType可以忽略,取值通过下标取值-->
<select id="getByNameAge" resultType="com.xf.pojo.User">
select * from t_user where name = #{0} and age = #{1}
</select>
</mapper>
namespace:配置我们mapper类的位置
select id:配置我们的mapper类中的查询方法名,
parameterType:定义传参的类型
resultType:sql查询结果映射到那个pojo类
对于pojo字段映射麻烦的关联查询可以使用resultMap 映射
<resultMap type="customer" id="customerMap">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
</resultMap>
<!--type是pojo类名,id是定义resultMap 自己的id,用于在写sql模块时resultType属性进行配置-->
4.3:mybatis写入获取自增主键
springboot+mybatis+mysql
数据写入mysql,mysql表设置了自增主键,现在从spring写接口进行数据插入。
1:controller层传参使用封装的bean对象,不用传主键
2:mapper将bean对象传入
3:mapper.xml配置 <insert id=“id” useGeneratedKeys="true"后。mybatis会去查找最大的主键然后赋值给bean对象完成传参,此处我们只用#{id}就可获取值
<insert id="id" useGeneratedKeys="true" keyProperty="id">
INSERT INTO t_user(id,username,password) VALUES(#{id}, #{username}, #{password});
</insert>
5:问题汇总
5.1:Invalid bound statement (not found) .mapper文件
用mapper.xml映射文件中的 namespace 和 select 标签的 id 去需要我们是mapper类中的方法
原因1:配置文件中的包名和方法名可能写错找不到方法
原因2:mapper.xml配置文件压根没有找到。
解决1:修改正确的配置文件完成映射
解决2:查看配置文件的路径,同时必须在application.properties中进行配置。pom.xml依赖包必须用**<artifactId>mybatis-plus-spring-boot-starter</artifactId>
**不能是mybatis-plus-core。否则会导致加载mapper.xml配置不到,报这种问题
5.2:a compent requied a bean of “自己定义的mapper类”,配置加载不到spring容器中
使用的mybatis maven依赖不能是mybatis-plus-boot-starter
,必须是**<artifactId>mybatis-plus-spring-boot-starter</artifactId>
**。
5.3:对于所有的找到不到mapper类或者加载不到配置文件的问题
1:查看相关注解是否添加,以及是否正确
2:application.yaml配置中是否配置mybatis.mapper-locations或者mybatis-plus.mapper-locations
用哪个必须和自己引用的依赖包是一致,否则找不到
3:resource下定义的*.mapper.xml中配置namespace 和 select 标签的 id 必须正确
4:mybatis引入的maven依赖必须是两个之一,不需要其他mybatis依赖了
<artifactId>mybatis-plus-spring-boot-starter</artifactId>`
<artifactId>mybatis-spring-boot-starter</artifactId>`
5.4:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
网上已经有很多文章说明可能导致这个报错的原因,无非是以下几种:
1.检查xml文件的namespace是否正确,id和方法名是否一致
2.Mapper.java的方法在Mapper.xml中没有,然后执行Mapper的方法会报此
3.xxxMapper.java的方法返回值是List,而select元素没有正确配置ResultMap,或者只配置ResultType
4.mapper.xml中配置是否正确,返回值传参和bean对象是否能映射上,映射失败会报问题。
我的问题是在mapper.xml中指定了databaseId=“mysql”,删除后就正常运行了
5.5:Parameter ‘xxx’ not found. Available parameters are [arg1, arg0, param1, param2].
传入的参数和sppring容器中的参数映射失败了,在mapper,service层的方法参数上都加上**(@Param(“value”) String value)**,对传参加入注解完成映射就可以了