1)MyBatis是一款优秀的持久层框架,持久化就是数据是保存在磁盘里面的,它支持自定义的SQL,存储过程以及高级映射,Mybatis去除几乎所有的JDBC代码以及设置参数或者是结果集的操作,MyBatis可以使用简单的XML或者是注解来进行配置和映射原始类型,将接口和POJOJAVA中的老式对象映射成数据库的纪录
2)简单来说就是MyBatis对JDBC代码进行了封装,它是更简单的完成程序和数据库交互的工具,也就是更简单的交互和读取数据库的工具
3)所以可以使用MyBatis的时候可以创建Mapper层接口以及对应的xml文件,也可以使用注解来代替xml和写SQL的方式,但是 SQL 语句复杂的时候使用注解这种方式不太好实现且不太美观
MyBatis是一个ORM框架,对象映射框架,在面向对象编程语言中,将关系型数据库中的数据和对象建立起映射关系,进而来完成数据和对象之间的相互转换
1)将输入数据和传入的对象+SQL映射成原生SQL
2)将结果集映射成返回对象,就是输出对象
一般的ORM框架都会将数据库的模型的每一张表都映射成一个JAVA的类,也就是说使用MyBatis可以像操作对象一样来进行操作数据库中的表,可以实现对象和数据库中的表的转换
1)自定义SQL:
自己写SQL,select,update,insert,delete;
2)存储过程:
1.1)一大堆SQL的组成,将SQL方法化,if判断语句,可以实现复杂的业务,这时候把逻辑从程序方移动到SQL方了,要求程序员的SQL功底非常好;
1.2)就算JAVA程序在复杂的话,我还可以debug,我可以一步一步去跟,跟到方法里面,调试很方便,但是存储过程调试很麻烦,无法调试,存储过程自己写的,过一段时间自己都看不懂,业务逻辑不要写在SQL里面,甚至程序员都搞不懂,但是大部分公司不用存储过程;
3)高级映射:除了程序中表的映射和对象的映射,还可以实现高级映射,还可以实现一对一,一对多,多对多之间的一个映射,进行连表查询,一对一,一对多,多对多比如说博客系统,一个作者对应多篇文章,一篇文章对应着一个作者;
2)MyBatis几乎去除了所有JDBC代码以及设置参数和获取结果集的工作,是一个对象映射框架,MyBatis可以通过简单的XML或者注解来进行配置和映射原始类型,简单来说MyBatis是简单的用来实现程序与数据库进行交互的工具,也就是更简单的操作和读取数据库的工具
MyBatis是一个桥梁,是用来链接程序和数据库的,是一个对象映射框架
总结:MyBatis是一个优秀的ORM持久层框架,也就是一个优秀的ORM对象映射框架
1)MyBatis是一款优秀的持久层框架,它支持自定义SQL,存储过程以及高级映射
2)MyBatis去除了几乎所有的JDBC代码以及设置参数和获取结果集的操作,之前我们在写JDBC的时候,咱们首先要进行获取一个DataSource,再将他封装成一个单例的模式,再从DataSource里面拿到一个Connection对象,得到链接,我们还有通过Connection得到一个执行器PrepareStatement,然后再配合我进行拼装的SQL执行SQL得到一个ResultSet对象,然后再进行Where循环,赋值给对象,最后我还要进行关闭,我的整个一个精力全部操作固定流程代码上面,而不是在业务代码上面,表的数据直接映射到框架上面;
3)MyBatis的出现让程序员只关注到业务开发,而不是在流程上,况且获取到DataSource,Connection,都是一样的套路,有大量的相同代码;
4)简单的来说,MyBatis是更简单的完成程序和数据库交互的工具,也就是更简单的操作和读取数据库的工具;
5)MyBatis可以通过简单的XML或者注解来进行配置(不用)和映射原始数据类型,接口,成为数据库中的记录,还可以通过注解的方式实现增删改查的功能,实现基本的增删改查是可以的,但是实现在复杂一点的功能注解+自定义SQL是非常别扭的;
6)MyBatis想要使用XML来进行写SQL,是很灵活的,灵活性代价就是自己写SQL,可以处理更复杂的业务场景;
1)MyBatis是一个ORM框架,ORM是对象关系映射,在面向对象的编程语言当中,将关系型数据库中的数据和对象建立起映射关系,进而自动地完成数据和对象之间的相互转换,将数据库中表的字段和类中的属性进行映射,将输入数据(传入对象)+SQL映射成原生SQL,将结果集映射成返回对象,即是输出对象,将表中的字段值映射到一个对象里面,MYSQL是提供了一个数据存储的软件,但是MyBatis是一个中间的桥梁,用来连接程序和数据库进行对象关系映射的(重要)
2)数据库表-------类
记录(行数据)---->对象
字段---->对象的属性
3)一般的ORM框架,会将数据库模型中的每一张表都映射成一个Java类,也就是说MyBatis可以像操作对象一样来进行操作数据库中的表,可以实现对象和数据库之间的转换;
所以说方法的定义是在接口里面进行实现的,具体的方法的实现是在XML里面实现的;
4)前后端交互过程:前端给后端发送一个ajax请求到后端,先到达的是控制器层,控制器层来进行验证参数,参数验证完这后没有问题,向下一级发送,调用服务层Service,在调用mapper接口,完成数据库中的表和Java代码中的类的映射;
5)每一次数据库的操作都会对应着一个抽象方法,这个接口只做声明,而没有具体的实现,是用来最终的映射的,XML文件里面写最终的一个实现,里面有SQL语句,里面指定了上面方法接口和对应的实体类的路径,而咱们的配置文件里面又写了XML文件路径;
6)配置文件(里面有XML文件路径)---->XML文件(包含SQL语句)(XML文件包含接口的路径和实体类的路径)------>接口文件(方法声明),这里面的XML文件和接口文件共同完成了数据库的查询,执行SQL,将结果映射到程序的对象里面;
一)先进行配置MyBatis项目框架的开发环境
1)先准备数据库(准备测试表)
drop table if exists user; drop database if exists HomeWork; create table User( userID int primary key auto_increment, classID int, username varchar(20), password varchar(20)); create table Blog( BlogID int primary key auto_increment, //这个字段不可以和上面的User表中的自增主键相同,否则联表查询会出现问题 BlogContent varchar(60), BlogTitle varchar(60), PostTime dateTime, UserID (int));
2)创建SpringBoot项目:
添加MyBatis数据库框架的支持,老项目升级为MyBatis,创建新项目的时候直接添加MyBatis的依赖,选择MyBatis FrameWork和MYSQL Driver,在pom.xml里面右键点击generate;
我们添加的依赖:
1)Spring Boot DevTools(热部署)
2)Lombok
3)Spring Web(MVC)
4)MyBatis Framework(Mybatis和MYSQL的驱动框架)
5)MYSQL Driver(不同数据库类型所添加的驱动是不一样的)
6)只有加了这两个依赖才可以实现程序到数据库的连接;
MyBatis本身又是一个门面模式,MYSQL Driver是底层的一个驱动就是具体干活的
3)添加配置文件,添加之前我们写过的有关JDBC的配置信息
配置数据库链接字符串和MyBatis保存的XML路径,你如果不配置这些信息,你直接进行启动项目之后是启动失败的;
配置MyBatis相关的配置文件,在配置文件下面写以下信息:
配置数据库连接信息: 1)连接数据库服务器地址 2)数据库用户名 3)数据库密码 4)数据库的驱动(底层数据库的类型) 5)开启MyBatis的SQL打印 6)进行配置Mybatis中的XML保存路径
4)编写properties配置文件
MyBatis 的基本使用流程:
1)创建一个使用注解@Mapper修饰的接口(用来给 Service 层调用),该注解来自 MyBatis,作用是与配置的Mapper.xml结尾的文件做连接;
2)在该接口里面定义方法;
3)在 xml 文件中按照 MyBatis 的规则编写 sql(接口的具体实现),xml 文件的作用是生成数据库可执行的 sql,并且能将结果映射到程序的对象中;4)比如要查询全部用户信息,其中标签头的id属性与要实现的方法名对应,resultType表示需要映射的类是哪一个,需要写出完整的包名,这样就会将查询的结果存入到该类的对象中对对象数组中,有一点是需要注意的,那就是使用resultType映射对象一定得保证数据库中的字段名与对象中的属性名一模一样,否则不能匹配赋值;
2.1)我们还要进行创建两个配置文件:application-dev1.properties和application-dev2.properties
2.2)我们还需要在原生的application.properties配置文件里面,加上一个属性,设置活跃的配置文件
#指定配置文件的环境,包括开发环境和生产环境 spring.profiles.active=dev1 #注意在这里买那些配置文件的时候一定不要加分号手欠
2.3)在dev1中配置数据库的连接信息:开发环境(系统配置文件和自定义配置文件)
#数据库连接配置: spring.datasource.url=jdbc:mysql://127.0.0.1:3306/java200?characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=12503487 #设置驱动 spring.datasource.driver-class-name=com.mysql.jdbc.Driver//链接的是哪一个数据库 #先设置日志级别:logging.level.com.example.demo:debug #开启MyBatis的SQL打印: mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl MYSQL8.0之后的写法:driver-class-name=com.mysql.cj.jdbc.driver
2.4)进行配置Mybatis中的XML保存路径,创建xml文件,是属于一个资源文件,是为了保存MyBatis里面的查询数据库的具体SQL,一个Interface对应着一个XML文件,为了找到实现interface接口方法的XML在哪里;
mybatis.mapper-locations=classpath:mapper/**Mapper.xml #classpath表示项目的根路径,这里面的mapper和resources下的mapper是对应的,况且这里面的mapper的名称可以是任意的,我们想要在mapper目录里面创建 #xml文件,所有文件的后缀名就必须是Mapper.xml
我们在resources目录下创建一个mapper目录,里面可以进行创建各种不同的XML文件
# 配置数据库的连接字符串 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/Java100?characterEncoding=utf-8&useSSL=false username: root password: "12503487" driver-class-name: com.mysql.cj.jdbc.Driver # 设置 Mybatis 的 xml 保存路径 mybatis: mapper-locations: classpath:mapper/*Mapper.xml configuration: # 配置打印 MyBatis 执行的 SQL log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 配置打印 MyBatis 执行的 SQL logging: level: com: example: demo: debug
二)使用MyBatis的操作模式来进行操作数据库:
MyBatis想要实现数据库的查询,必须有两个文件
1)第一个就是数据库查询方法声明:JAVA接口的声明,里面声明方法;
2)第二个就是XML文件,里面写具体的方法的实现,在XML可以连接实体类和数据库;
1)创建接口文件:
2)然后我们在从MyBatisMapper.xml文件里面写下面代码:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--上面是XML实现方法声明interface接口的一个完整路径--> <mapper namespace="com.example.demo.UserMapper.SpringBootMapper"> //下面是resultType表示实体类的一个路径 <select id="GetAll" resultType="com.example.demo.User"> select * from User; <!--上面表示查询的SQL--> </select> <!--id表示接口里面的方法名,resultType表示返回的类型,也就是实体类的路径--> </mapper>
进行使用MyBatis模式和语法进行操作数据库
注意:xml文件是方法(JDBC)的实现,接口是方法的声明
MyBatis的执行流程:
1)前端用户会通过ajax访问服务器的时候会先到Controller这一层,控制器会先进行参数的校验,校验参数没有问题之后;
2)接下来会把请求向服务层去发,然后服务层也是一个代理,看看我调用几个接口,就是UserMapper的接口,先调用哪一个接口,后调用哪一个接口,mapper只是单一职责;
3)运行的时候,MyBatis把XML文件和interface做一个关联,关联完成之后,把方法里面的SQL生成一个原始的SQL,生成一个原始的SQL,接口中的参数占位符进行替换
4)会生成JDBC,并进行自动的调用,所以说MyBatis是基于JDBC,会生成JDBC的代码和原生SQL,并会自动执行JDBC;
1)查询操作使用select标签,查询标签至少设置两个属性,第一个是id表示与哪一个方法相对应,就是设置成相关联的方法的方法名,比如我们在 Mapper 接口中的查询方法是getUserById,则设置id="getUserById";
2)然后设置resultType属性的值,查询需要返回查询结果UserInfo对象,如果可能有多个结果,对应的方法返回值就写List<UserInfo>,否则写UserInfo即可,resultType属性中只需要设置成带包名的类名即可
编写代码:以查找为例,直接查找全部
1)添加实体类:我们在demo包下新创建一个包,里面定义一个类,叫做User,这个类叫做实体类,这个类的每一个属性都要和对应数据库表中的列名是相同的;
@Setter @Getter @ToString public class User { private int classID; private int userID; private String username; private String password; }
1)添加Controller类:在demo里面进行创建一个Controller包,在这个包里面创建一个UserController类
@Controller public class UserController { @Autowired UserService userService; @RequestMapping("/selectAll") @ResponseBody public List<User> GetAll() { return userService.GetAll(); } }
2.添加Service:在demo里面进行创建一个Service包,然后再从这个包里面创建一个UserService类(在里面要引入上一步创建的接口)
@Service public class UserService { @Autowired private SpringBootMapper mapper; public List<User> GetAll() { return mapper.GetAll(); } }
3)添加Mapper接口,我们再从demo里面进行创建一个包,叫做UserMapper,里面创建一个接口,叫做SpringBootMapper,咱们的这个Mapper接口加上之后,表示这个接口交给Spring进行管理了,就可以和咱们的XML文件,里面指定了这个接口的全限定包名+类名共同进行操作数据库了;
@Mapper public interface SpringBootMapper { public List<User> GetAll(); public List<User> GetAll(@Param(id)) }
mapper目录下面的xml文件中的重要字段的解析:
@Parm("字段")=select * from user where userID=#{字段}
1)namespace:里面存放的是我们要实现的方法声明式的接口的一个完整路径,包名+类名
2)因为我们要进行的是查询操作,所以我们需要使用select标签,里面的id属性表示我们的声命式接口的方法名,这是表示方法名
3)我们的resultType表示的是返回值的类型,这里面表示的是实体类对象的路径,是不可以进行省略的,如果省略就会进行报错;
注意:我们在这里面写的MyBatis Mapper.xml进行查询返回的类型的设置:这两种方法都是可以成功的将查询结果映射到我们自己所写的类上面
1.resultType:里面要填写返回结果的类型
2.resultMap:返回映射也叫做返回字典,他和resultType它们之间的使用是互不相同的,首先我们是需要进行设置一个resultMap,里面的id是可以随便写的,但是type里面要写整个idea里面要进行映射的类的路径,我们其实用这种形式主要是为了解决用户自定义的类名中的字段和数据库中的列不相等的情况,主要是为了把从数据库查询的字段映射到即将返回的对象中的属性;
共同点:他们的功能都是一样的,都是为了来进行指定结果类型,如果说用户名和最终的数据库的名字不相同那么我们最终还没有设置ResultMap属性,那么最终查询的字段对应的值就是为空;
不同点:
1)resultType的用法简单,但是说如果实体类里面的属性名和表中的字段名不一致的话就会查询不出来结果
2)resultMap的用法相对来说比较麻烦,因为他要声明多个列,但是他可以实现属性和字段的不一致的映射,让咱们的查询结果可以正常;
resultMap里面存放的是上一个resultMap对应的ID属性,而resultType里面写的是对应的要进行映射的类的路径;
1)使用resultType:这个属性是不可以进行忽略的,否则是无法和我们的Java的类对应的列进行映射就类似于我们已经查询到了数据库的一条一条的信息,但是我们无法返回给Java代码;
<!--上面是XML实现接口的一个完整路径--> <select id="GetAll" resultType="com.example.demo.DatasourceClass.User"> select * from User; <!--上面表示查询的SQL--> </select> <!--id表示接口里面的方法名,resultType表示返回的类型-->
现在我们来进行修改,之前我们的User类中的字段是和数据库中的表的字段是相同的,现在我们都把他们改成不相同的情况,然后再次来进行操作:
我们偷偷的在前面加上了一个Student @Setter @Getter @ToString public class User { private int StudentClassID; private int StudentUserID; private String StudentUsername; private String Password; }
2)使用resultMap:模板:
<resultMap id="BaseMap" type="com.example.demo.User">//里面填写的是数据库字段对应的实体类; 上面的id字段是可以随便写的 <!--下面是对于自增主键的映射--> <id column="数据库中的列的主键" property="Java类的字段"></id> <!--下面是针对于普通列的映射--> <result column="数据库中列的名字" property="Java类中的对应字段名字"></result> <result column="数据库中列的名字" property="Java类中的对应字段的名字"></result> </resultMap> 这个id字段表示需要关联的接口的方法 <select id="对应的Java声明接口方法方法" resultMap="上面的resultMap的id属性"> select查询语句 </select>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.UserMapper.SpringBootMapper"> <resultMap id="BaseMap" type="com.example.demo.User"> <id column="userID" property="StudentUserID"></id> <result column="classID" property="StudentClassID"></result> <result column="username" property="StudentUsername"></result> <result column="password" property="password"></result> </resultMap> <select id="GetAll" resultMap="BaseMap"> select * from User </select> </mapper>
Invalid bound statement (not found):com.example.demo.Mapper.MyBatisMapper.GetAll 还有就是说进行配置Mybatis的xml的文件配置配置错的时候也是会出现报错的(和上面的报错信息是相同的) 上面的内容我们写完之后直接在浏览器上输入:http://localhost:8080/GetAll,就可以看到数据库的信息了;通过费德勒抓包,返回的响应数据是Json;
1)我们在这里面一定要注意: 我们为了进行验证resultMap的操作,我们在User中改了好几个和数据库名字不一样的字段,这肯定是在resultMap标签里面里面的嵌套标签result进行指定,那么这一句代码还用写吗?
<result column="password" property="password"></result>
一定是要写的,不要手懒否则后面进行多表查询的时候我们是无法进行查询出相应的字段的
2)MyBatis会把XML和接口做一个关联,会根据你的方法中的参数生成一个原始的SQL,并且MyBatis会调用JDBC,会自动生成JDBC的代码和SQL,在通过JDBC的方式去调用数据库得到结果之后,返回给Service层,Service层再把结果返回给Controller层,Controller层再把结果返回给前端,这一次浇花就完成了
出现的问题:
1)项目创建的时候报出的错误;
2)当我们访问后端接口的时候出现的错误;
3)出错的原因就是没有设置yml文件对mapper和合适路径;
出现这种错误的原因是select标签没有设置ResultType或者是ResultMap