• MyBatis查询数据库(1)-------JavaEE


    一:什么是Mybatis?

    1)MyBatis是一款优秀的持久层框架,它支持自定义的SQL,存储过程以及高级映射,

    2)MyBatis几乎去除了所有JDBC代码以及设置参数和获取结果集的工作,是一个对象映射框架

    3)MyBatis可以通过简单的XML和或者注解来进行配置和映射原始类型,简单来说MyBatis是简单的用来实现程序与数据库进行交互的工具,也就是更简单的操作和读取数据库的工具

    1. 1)MyBatis是一款优秀的持久层框架,它支持自定义SQL,存储过程以及高级映射
    2. 2)MyBatis去除了几乎所有的JDBC代码以及设置参数和获取结果集的操作,之前我们在写JDBC的时候,咱们首先要进行获取一个DataSource,再将他封装成一个单例的模式,再从DataSource里面拿到一个Connection对象,得到链接,我们还有通过Connection得到一个执行器PrepareStatement,然后再配合我进行拼装的SQL执行SQL得到一个ResultSet对象,然后再进行Where循环,赋值给对象,最后我还要进行关闭,我的整个一个精力全部操作代码上面,而不是在业务代码上面;
    3. 3)MyBatis的出现让程序员只关注到业务开发,而不是在流程上,况且获取到DataSource,Connection,都是一样的套路,有大量的相同代码;
    4. 4)简单的来说,MyBatis是更简单的完成程序和数据库交互的工具,也就是更简单的操作和读取数据库的工具;
    5. 5)MyBatis可以通过简单的XML或者注解来进行配置(不用)和映射原始数据类型,接口,成为数据库中的记录;

     

    1))MyBatis是一个ORM框架,ORM是对象关系映射,在面向对象的编程语言当中,将关系型数据库中的数据和对象建立起映射关系,进而自动地完成数据和对象之间的相互转换

    将输入数据(传入对象)+SQL映射成原生SQL,将结果集映射成返回对象,即是输出对象

    2)数据库表-------类

    记录(行数据)---->对象

    字段---->对象的属性

    一般的ORM框架,会将数据库模型中的每一张表都映射成一个Java类,也就是说MyBatis可以像操作对象一样来进行操作数据库中的表,可以实现对象和数据库之间的转换;

    所以说方法的定义是在接口里面进行实现的,具体的方法的实现是在XML里面实现的;

    3)前后端交互过程:前端给后端发送一个ajax请求到后端,先到达的是控制器层,控制器曾来进行验证参数,参数验证完这后没有问题,向下一级发送,调用服务层Service,在调用mapper接口,完成数据库中的表和Java代码中的类的映射;

    4)每一次数据库的操作都会对应着一个抽象方法,这个接口只做声明,而没有具体的实现;

    二:如何学习MyBatis? 

    1.进行配置MyBatis的开发环境

    1)先准备数据库(准备表)

    1. mysql> create table User(
    2. -> userID int primary key auto_increment,
    3. -> classID int,
    4. -> username varchar(20),
    5. -> password varchar(20));
    6. Query OK, 0 rows affected (0.03 sec)

    2)添加MyBatis数据库框架的支持,老项目升级为MyBatis,创建新项目的时候直接添加MyBatis的依赖,选择MyBatis FrameWork和MYSQL Driver(在pom.xml里面右键点击generate)

    我们添加的依赖:

    Spring Boot DevTools

    Lombok

    Spring Web

    MyBatis Framework(Mybatis和MYSQL的驱动框架)

    MYSQL Driver(不同数据库类型所添加的驱动是不一样的)

    只有加了这两个依赖才可以实现程序到数据库的连接;

    3)添加配置文件,添加之前我们写过的有关JDBC的配置信息

    配置MyBatis相关的配置文件:

    1. 配置数据库连接信息:
    2. 1)连接数据库服务器地址
    3. 2)数据库用户名
    4. 3)数据库密码
    5. 4)数据库的驱动(数据库的类型)

    1.配置连接字符串:我们可以在yml里面进行配置:后面我们直接把它写道properties里面(可有可无)

    1. #数据库连接配置(在yml里面)
    2. spring:
    3. datasource:
    4. url:jdbc:mysql://127.0.0.1:3306/java200?characterEncoding=utf-8&useSSL=false
    5. username:root
    6. password:12503487
    7. driver-class-name: com.mysql.cj.jdbc.Driver

    2.编写配置文件: 

    1)我们还要进行创建两个配置文件:application-dev1.properties和application-dev2.properties

    2)我们还需要在原生的application.properties配置文件里面,加上一个属性,设置活跃的配置文件

    1. #指定配置文件的环境,包括开发环境和生产环境
    2. spring.profiles.active=dev1

    3)在dev1中配置数据库的连接信息:

    1. logging.level.root=warn
    2. #数据库连接配置:
    3. spring.datasource.url=jdbc:mysql://127.0.0.1:3306/java200?characterEncoding=utf-8&useSSL=false
    4. spring.datasource.username=root
    5. spring.datasource.password=12503487
    6. spring.datasource.driver-class-name=com.mysql.jdbc.Driver//链接的是哪一个数据库
    7. #设置驱动

    MYSQL8.0之后的写法:driver-class-name=com.mysql.cj.jdbc.driver

     3.进行配置Mybatis中的XML路径,创建xml文件:是为了保存MyBatis里面的查询数据库的具体SQL,一个Interface对应着一个XML文件,为了找到实现interface接口方法的XML在哪里

    1. mybatis.mapper-locations=classpath:mapper/**Mapper.xml
    2. #classpath表示项目的根路径,这里面的mapper和resources下的mapper是对应的,况且这里面的mapper的名称可以是任意的,我们想要在mapper目录里面创建
    3. #xml文件,后缀名就必须是Mapper.xml

    我们在resource目录下创建一个mapper目录;

    然后我们在从MyBatisMapper文件里面写下面代码: 

    1. mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN"
    2. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    3. <mapper namespace="com.example.demo.UserMapper.SpringBootMapper">
    4. <select id="GetAll" resultType="com.example.demo.User">
    5. select * from User;
    6. select>
    7. mapper>

     

    2.进行使用MyBatis模式和语法进行操作数据库

    注意:xml是方法(JDBC)的实现,接口是方法的声明

    编写代码:以查找为例

    1.添加实体类:我们在demo包下新创建一个包,里面定义一个类,叫做User,这个类叫做实体类,这个类的每一个属性都要和对应数据库表中的列名是相同的;

    1. package com.example.demo;
    2. import lombok.Getter;
    3. import lombok.Setter;
    4. import lombok.ToString;
    5. @Setter
    6. @Getter
    7. @ToString
    8. public class User {
    9. private int classID;
    10. private int userID;
    11. private String username;
    12. private String password;
    13. }

    1.添加Controller类:在demo里面进行创建一个Controller包,在这个包里面创建一个UserController类

    1. import com.example.demo.Service.UserService;
    2. import com.example.demo.User;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.stereotype.Controller;
    5. import org.springframework.web.bind.annotation.RequestMapping;
    6. import org.springframework.web.bind.annotation.ResponseBody;
    7. import java.util.List;
    8. @Controller
    9. public class UserController {
    10. @Autowired
    11. UserService userService;
    12. @RequestMapping("/selectAll")
    13. @ResponseBody
    14. public List GetAll()
    15. {
    16. return userService.GetAll();
    17. }
    18. }

    2.添加Service:在demo里面进行创建一个Service包,然后再从这个包里面创建一个UserService类(在里面要引入上一步创建的接口)

    1. package com.example.demo.Service;
    2. import com.example.demo.User;
    3. import com.example.demo.UserMapper.SpringBootMapper;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.stereotype.Service;
    6. import java.util.List;
    7. @Service
    8. public class UserService {
    9. @Autowired
    10. private SpringBootMapper mapper;
    11. public List GetAll() {
    12. return mapper.GetAll();
    13. }
    14. }

    3.添加Mapper接口:我们再从demo里面进行创建一个包,叫做UserMapper,里面创建一个接口,叫做SpringBootMapper

    1. package com.example.demo.UserMapper;
    2. import com.example.demo.User;
    3. import org.apache.ibatis.annotations.Mapper;
    4. import org.springframework.web.bind.annotation.Mapping;
    5. import java.util.List;
    6. @Mapper
    7. public interface SpringBootMapper {
    8. public List GetAll();
    9. }

     

    我们的mapper目录下面的xml文件中的重要字段的解析:

    1)namespace:里面存放的是我们要实现的方法声明式的接口的一个完整路径

    2)因为我们要进行的是查询操作,所以我们需要使用select标签,里面的id属性表示我们的声命式接口的方法名,这是表示方法名

    3)我们的resultType表示的是返回值的类型(这里面表示的是实体类对象的路径),是不可以进行省略的,如果省略就会进行报错;

    注意:我们在这里面写的MyBatis Mapper.xml进行查询返回的类型的设置:这两种方法都是可以成功的将查询结果映射到我们自己所写的类上面

    1.resultType:里面要填写返回结果的类型

    2.resultMap:返回映射也叫做返回字典,他和resultType它们之间的使用是互不相同的,首先我们是需要进行设置一个resultMap,里面的id是可以随便写的,但是type里面要写整个idea里面要进行映射的类的路径,我们其实用这种形式主要是为了解决用户自定义的类名中的字段和数据库中的列不相等的情况

    共同点:他们的功能都是一样的,都是为了来进行指定结果类型

    不同点:resultType的用法简单,但是说如果实体类里面的属性名和表中的字段名不一致的话就会查询不出来结果

    resultMap的用法相对来说比较麻烦,因为他要声明多个列,但是他可以实现属性和字段的不一致的映射,让咱们的查询结果可以正常;

    写的方法有这样两种:

    resultMap里面存放的是上一个resultMap对应的ID属性,而resultType里面写的是对应的要进行映射的类的路径;

    公共部分:

     1)使用resultType:这个属性是不可以进行忽略的,否则是无法和我们的Java的类对应的列进行映射,就类似于我们已经查询到了数据库的一条一条的信息,但是我们无法返回给Java代码;

    
    
    

    现在我们来进行修改,之前我们的User类中的字段是和数据库中的表的字段是相同的,现在我们都把他们改成不相同的情况,然后再次来进行操作:

    1. 我们偷偷的在前面加上了一个Student
    2. package com.example.demo;
    3. import lombok.Getter;
    4. import lombok.Setter;
    5. import lombok.ToString;
    6. @Setter
    7. @Getter
    8. @ToString
    9. public class User {
    10. private int StudentClassID;
    11. private int StudentUserID;
    12. private String StudentUsername;
    13. private String Password;
    14. }

    2)使用resultMap:模板:

      
    上面的id字段是可以随便写的
    
            
    
            
            
        
    这个id字段表示需要关联的接口的方法
        
    
    
    1. mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN"
    2. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    3. <mapper namespace="com.example.demo.UserMapper.SpringBootMapper">
    4. <resultMap id="BaseMap" type="com.example.demo.User">
    5. <id column="userID" property="StudentUserID">id>
    6. <result column="classID" property="StudentClassID">result>
    7. <result column="username" property="StudentUsername">result>
    8. <result column="password" property="password">result>
    9. resultMap>
    10. <select id="GetAll" resultMap="BaseMap">
    11. select * from User
    12. select>
    13. mapper>
    1. Invalid bound statement (not found):com.example.demo.Mapper.MyBatisMapper.GetAll
    2. 还有就是说进行配置Mybatis的xml的文件配置配置错的时候也是会出现报错的(和上面的报错信息是相同的)
    3. 上面的内容我们写完之后直接在浏览器上输入:http://localhost:8080/GetAll,就可以看到数据库的信息了;通过费德勒抓包,返回的响应数据是Json;

     

    1)我们在这里面一定要注意: 我们为了进行验证resultMap的操作,我们在User中改了好几个和数据库名字不一样的字段,这肯定是在resultMap标签里面里面的嵌套标签result进行指定;

    2)那么这一句代码还用写吗?

       <result column="password" property="password"></result>

    一定是要写的,不要手懒,否则后面进行多表查询的时候我们是无法进行查询出相应的字段的

    对于我们向数据库中增加数据来说,程序应该返回两种类型的数据,一种是受影响的行数,一种是我想要拿到添加成功的id

     编写代码:以向数据库中添加数据为例,根据在浏览器上面输入的username和password进行向数据库中插入数据

    1. package com.example.demo.DatasourceClass;
    2. import lombok.Getter;
    3. import lombok.Setter;
    4. import lombok.ToString;
    5. @Setter
    6. @Getter
    7. @ToString
    8. public class JavaScript {
    9. int userIDHHH;
    10. int classIDHHH;
    11. String usernameHHH;
    12. String password;
    13. String CSS;
    14. }

    1.在UserController里面的代码:

    //这是针对插入操作的,添加用户,返回受影响的行数
    @RequestMapping("/InsertAll")
    @ResponseBody
    public int add(JavaScript javaScript)//返回值是int类型是因为插入之后程序会返回受影响的结果的行数,传过来的javascript对象就是要插入数据库里面的数据
    {
        if(javaScript==null||javaScript.getPassword()==null||javaScript.getUsernameHHH()==null)
        {
            System.out.println(javaScript.getPassword()+javaScript.getUsernameHHH());
            return -1;
        }
        return userService.add(javaScript);
    }

    2.在UserService里面的代码:

    @Service
    public class UserService {
        @Resource
        private MyBatisMapper myBatisMapper;
        public List GetAll()
        {
            return myBatisMapper.GetAll();
        }
        public int add(JavaScript javaScript) {
            return myBatisMapper.add(javaScript);
        }
    }

    3.在Mapper里面的代码:

    package com.example.demo.Mapper;
    import com.example.demo.DatasourceClass.JavaScript;
    import org.apache.ibatis.annotations.Mapper;
    import java.util.List;
    @Mapper
    public interface MyBatisMapper {
          List GetAll();
        int add(JavaScript javascript);
    }
    

    4.在目录Mapper里面的MyBatis里面的代码:

    1. mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN"
    2. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    3. <mapper namespace="com.example.demo.Mapper.MyBatisMapper">
    4. <resultMap id="BaseMap" type="com.example.demo.DatasourceClass.JavaScript">
    5. <id column="userID" property="userIDHHH">id>
    6. <result column="classID" property="classIDHHH">result>
    7. <result column="username" property="usernameHHH">result>
    8. resultMap>
    9. <select id="GetAll" resultMap="BaseMap">
    10. select * from JavaScript
    11. select>
    12. <insert id="add">
    13. insert into JavaScript(username,password)value(#{usernameHHH},#{password})
    14. 注意:当前类中的名字是和数据库中的名字是不一样的,#里面要写当前类中的名字
    15. insert>
    16. mapper>

     创建SpringBoot单元测试:

    1)创建准备条件:测试框架,默认添加测试的目录,默认是已经被创建的;

    2)在需要进行测试的类左边进行右键双击Generate生成,选择生成单元测试,生成测试类和测试的方法

    Testing library:单元测试框架,选择默认即可

    ClassName:生成单元测试的类名

    Superclass:表示单元测试的父类,不需要直接设置成空就可以了

    Destination package:生成单元测试的目录 

    Generate:是否生成前置方法或者后置方法(不动)

    Member:测试方法列表

    最后点击OK就行了

    3)要给当前类加上@SpringBootTest注解,声明当前的类是在SpringBoot容器里面运行的,也就是说咱们要进行测试的类是一个SpringBoot

    4)在方法中构建咱们的测试代码:

    我们再来实现一下我们进行添加用户,返回一个新增用户的主键ID

    1. UserController里面的代码:是返回插入数据的UserID
    2. @RequestMapping("/InsertAll")
    3. @ResponseBody
    4. public int add(JavaScript javaScript)//返回值是int类型是因为插入之后程序会返回受影响的结果的行数,传过来的javascript对象就是要插入数据库里面的数据
    5. {
    6. if(javaScript==null||javaScript.getPassword()==null||javaScript.getUsernameHHH()==null)
    7. {
    8. System.out.println(javaScript.getPassword()+javaScript.getUsernameHHH());
    9. return -1;
    10. }
    11. //执行数据库添加操作,执行完添加操作,会将我们的新添加数据自增的UserID设置到JavaScript里面的UserID上面
    12. userService.add(javaScript);
    13. return javaScript.getUserIDHHH();
    14. }
    15. XML里面的代码:
    16. "add" useGeneratedKeys="true" keyProperty="userIDHHH" keyColumn="userID">
    17. insert into JavaScript(username,password)value(#{usernameHHH},#{password})

    1)useGenerateKeys:这会令MyBatis使用JDBC的getGeneratedKeys方法来去取出有数据库内部生成的主键

    2)keyColumn:类中属性

    3)keyColumn:数据库表中属性

    3.实现修改操作:

    UserController里面的代码:

    1. @RequestMapping("/upDate")
    2. @ResponseBody
    3. public int Start(JavaScript javaScript)
    4. {
    5. //我们在这里面进行一个非空校验,我们想要修改的是密码
    6. if(javaScript==null||javaScript.getUserIDHHH()<=0||javaScript.getPassword()==null||javaScript.getPassword().equals(""))
    7. {
    8. return -1;
    9. }
    10. return userService.update(javaScript);
    11. }

    我们进行实现一下UserService里面的代码:

    1. public int update(JavaScript javaScript) {
    2. return myBatisMapper.update(javaScript);
    3. }

    我们进行实现一下XML里面的代码:

    1. <update id="update">
    2. update JavaScript set password=#{password} where userID=#{userIDHHH};
    3. update>

    4.实现删除操作:

    1. UserController里面的代码:
    2. @RequestMapping("/Delete")
    3. @ResponseBody
    4. public int Delete(int userIDHHH)
    5. {
    6. if(userIDHHH<0)
    7. return -1;
    8. return userService.Delete(userIDHHH);
    9. }
    10. UserService里面的代码:
    11. public int Delete(int userID) {
    12. return myBatisMapper.Delete(userID);
    13. }
    14. 接口里面的代码:
    15. int Delete(int userID);
    16. XML文件里面的代码:
    17. "Delete">
    18. delete from JavaScript where userID=#{userIDHHH}

  • 相关阅读:
    R语言ggplot2可视化:使用ggpubr包的ggline函数可视化折线图(点线图、line plot)、同一水平的多个点用线连接起来
    linux systemctl删除失效的服务单元
    Docker-Consul概述
    oracle10g 监听异常处理
    android源码学习-android异常处理机制
    离散数学 --- 根树,根数的遍历,最优树和哈夫曼算法
    SpringBoot学习
    基于Java的医院预约挂号系统设计与实现(源码+lw+部署文档+讲解等)
    Mysql命令行常用基本操作
    AI&Cloud 分论坛 07-AI原生数据库与RAG【文档管理】
  • 原文地址:https://blog.csdn.net/weixin_61518137/article/details/125844179