文章目录

  • 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层是直接与数据库进行操作的。
  1. Mapper层:也可以称为DAO层,是数据库CRUD的接口,只有方法名,具体实现在mapper.xml文件中,对数据库进行数据持久化操作(把数据放到持久化的介质中,同时提供CRUD操作)
  2. src/main/resource文件夹中的mapper.xml文件,里面存储的是真正的数据库CRUD语句
  3. Pojo层:存放实体类,与数据库中的属性基本保持一致,一般包括getter、setter、toString方法(未使用插件lombok的情况下)

1.2:框架间联系

controller层(处理前台发送的请求)--->service定义接口(业务逻辑)--->serviceImpl(对接口函数进行实现)
--->mapper(Mapper接口,方法名与Mapper.xml中定义的statement的id相同)--->mapper.xml(写sql语句查询数据库)

Java设计RestfulApi接口 java rest接口开发_restful


由此可见,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响应码,判断请求状态,进而做出提醒。

Java设计RestfulApi接口 java rest接口开发_sql_02

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属性进行配置-->

Java设计RestfulApi接口 java rest接口开发_sql_03

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)**,对传参加入注解完成映射就可以了