wordpress 去掉自豪,关键词优化推广策略,网站空间控制面板软件,wordpress右下角广告目录 MyBatis简介JDBC缺点#xff1a;MyBatis针对于JDBC进行简化#xff0c;简化思路#xff1a; MyBatis快速入门具体构建步骤解决SQL映射文件的警告提示 Mapper代理开发案例#xff1a;使用Mapper代理方式完成案例具体步骤详解#xff1a;Mapper代理方式 Mapper核心配置… 目录 MyBatis简介JDBC缺点MyBatis针对于JDBC进行简化简化思路 MyBatis快速入门具体构建步骤解决SQL映射文件的警告提示 Mapper代理开发案例使用Mapper代理方式完成案例具体步骤详解Mapper代理方式 Mapper核心配置文件配置文件完成增删改查1配置文件实现CRUD1.1 环境准备1.2 查询所有数据1.2.1 编写接口方法1.2.2 编写SQL语句1.2.3 编写测试方法1.2.4 起别名解决上述问题1.2.5 使用resultMap解决上述问题1.2.6 小结 1.3 查询详情1.3.1 编写接口方法1.3.2 编写SQL语句1.3.3 编写测试方法1.3.4 参数占位符1.3.5 parameterType使用1.3.6 SQL语句中特殊字段处理 1.4 多条件查询1.4.1 编写接口方法1.4.2 编写SQL语句1.4.3 编写测试方法1.4.4 动态SQL 1.5 单个条件动态SQL1.5.1 编写接口方法1.5.2 编写SQL语句1.5.3 编写测试方法 1.6 添加数据1.6.1 编写接口方法1.6.2 编写SQL语句1.6.3 编写测试方法1.6.4 添加-主键返回 1.7 修改1.7.1 编写接口方法1.7.2 编写SQL语句1.7.3 编写测试方法 1.8 删除一行数据1.8.1 编写接口方法1.8.2 编写SQL语句1.8.3 编写测试方法 1.9 批量删除1.9.1 编写接口方法1.9.2 编写SQL语句1.9.3 编写测试方法 1.10 Mybatis参数传递1.10.1 多个参数1.10.2 单个参数 2注解实现CRUD 视频课程链接黑马2小时MyBatis
配套源码下载
MyBatis简介
是一款持久层框架用于简化JDBC开发
持久层就是
负责将数据保存到数据库的那一层代码JavaEE三层架构表现层、业务层、持久层
表现层负责做页面展示的业务层做逻辑处理持久层对数据进行持久化
框架
框架就是
一个半成品软件是一套可重用的、通用的、软件基础代码模型
在框架的基础上构建软件编写更加高效、规范、通用、可扩展
JDBC缺点
1、硬编码
注册驱动获取连接SQL语句 在这个位置写了很多字符串这就叫硬编码。
如果字符串的值发生变动了就要改动代码。这就意味着要重新编译重新打包重新运行维护性差
2、操作繁琐
手动设置参数手动封装结果集 MyBatis针对于JDBC进行简化简化思路
硬编码》配置文件
操作繁琐》让其自动完成
MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作 MyBatis快速入门
需求 具体构建步骤
1、创建User表添加数据数据表准备如下
//user.sql
create database mybatis;
use mybatis;drop table if exists tb_user;create table tb_user(id int primary key auto_increment,username varchar(20),password varchar(20),gender char(1),addr varchar(30)
);INSERT INTO tb_user VALUES (1, zhangsan, 123, 男, 北京);
INSERT INTO tb_user VALUES (2, 李四, 234, 女, 天津);
INSERT INTO tb_user VALUES (3, 王五, 11, 男, 西安);
2、创建模块导入坐标
使用Maven安装MyBatis来构建项目需将以下的依赖代码置于pom.xml文件中
//pom.xml
dependencies!--mybatis 依赖--dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.5/version/dependency!--mysql 驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.46/version/dependency!--junit 单元测试--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.13/versionscopetest/scope/dependency!-- 添加slf4j日志api --dependencygroupIdorg.slf4j/groupIdartifactIdslf4j-api/artifactIdversion1.7.20/version/dependency!-- 添加logback-classic依赖 --dependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactIdversion1.2.3/version/dependency!-- 添加logback-core依赖 --dependencygroupIdch.qos.logback/groupIdartifactIdlogback-core/artifactIdversion1.2.3/version/dependency/dependencieslogback除了这三个坐标信息之外还需要一个配置文件所以把logback.xml配置文件放在resources中
3、编写MyBatis核心配置文件用来替换连接信息解决硬编码的问题
在resources中创建一个新的文件mybatis-config.xml
在中进行配置
//mybatis-config.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE configurationPUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd
configurationtypeAliasespackage namecom.itheima.pojo//typeAliases!--environments配置数据库连接环境信息。可以配置多个environment通过default属性切换不同的environment--environments defaultdevelopmentenvironment iddevelopmenttransactionManager typeJDBC/dataSource typePOOLED!--数据库连接信息--property namedriver valuecom.mysql.jdbc.Driver/property nameurl valuejdbc:mysql:///mybatis?useSSLfalse/property nameusername valueroot/property namepassword value1234//dataSource/environmentenvironment idtesttransactionManager typeJDBC/dataSource typePOOLED!--数据库连接信息--property namedriver valuecom.mysql.jdbc.Driver/property nameurl valuejdbc:mysql:///mybatis?useSSLfalse/property nameusername valueroot/property namepassword value1234//dataSource/environment/environmentsmappers!--加载sql映射文件--!-- mapper resourcecom/itheima/mapper/UserMapper.xml/--!--Mapper代理方式--package namecom.itheima.mapper//mappers/configuration4、编写SQL映射文件用来统一管理sql语句解决硬编码问题
在中修改。
然后在resources中建立一个包mapper用来存放Mapper文件
如果写的是User表那就是UserMapper.xml如果写的是Order表那就是OrdererMapper.xml
//UserMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd!--namespace:名称空间
--mapper namespacecom.itheima.mapper.UserMapper!--statement--select idselectAll resultTypepojo.Userselect *from tb_user;/select/mappernamespace:名称空间
看这里面的标签应该知道之后的SQL语句应该就是写在这个Mapper中
resultType: 对应的返回结果的类型id是唯一标识
在mybatis-config.xml文件中写加载sql映射文件
//mybatis-config.xml
mapper resourceUserMapper.xml/因为两个xml文件是平级的所以直接写文件名字就行。
5、编码
1定义POJO类
在java下创建一个包叫pojo在包中创建一个User.java里面内容如下
package com.itheima.pojo;// alt 鼠标左键 整列编辑
public class User {private Integer id;private String username;private String password;private String gender;private String addr;public Integer getId() {return id;}public void setId(Integer id) {this.id id;}public String getUsername() {return username;}public void setUsername(String username) {this.username username;}public String getPassword() {return password;}public void setPassword(String password) {this.password password;}public String getGender() {return gender;}public void setGender(String gender) {this.gender gender;}public String getAddr() {return addr;}public void setAddr(String addr) {this.addr addr;}Overridepublic String toString() {return User{ id id , username username \ , password password \ , gender gender \ , addr addr \ };}
}
有了pojo类了我们就可以在对应的UserMapper.xml的resultType中写返回类型是pojo.User。我们的需求是查询所有所以id就起名为selectAll。然后在标签里写SQL查询语句。
2加载核心配置文件获取SqlSessionFactory对象
在java下写一个核心测试类MyBatisDemo.java
3获取sqlSession对象执行SQL语句
用sqlSession对象来执行SQL语句具体如下
//MyBatisDemo.java
package com.itheima;import com.itheima.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** Mybatis 快速入门代码*/
public class MyBatisDemo {public static void main(String[] args) throws IOException {//1. 加载mybatis的核心配置文件获取 SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象用它来执行sqlSqlSession sqlSession sqlSessionFactory.openSession();//3. 执行sqlListUser users sqlSession.selectList(test.selectAll);System.out.println(users);//4. 释放资源sqlSession.close();}
}
Resources是java提供的一个资源加载类
selectOne() , selectList()括号里放的是mapper的唯一标识
4释放资源
解决SQL映射文件的警告提示
产生原因IDEA和数据库没有建立连接不识别表信息
解决方式在IDEA中配置MySQL数据库连接 可以在IDEA中写SQL语句有自动补全代码提示很方便打开IDEA数据库上面有个笔的标志。
Mapper代理开发
目的就是让MyBatis的代码更加简单。
解决原生方式中的硬编码问题简化后期执行SQL 案例使用Mapper代理方式完成案例 1、
▶️ 在java下创建一个mapper包在这个下面写Mapper接口。
▶️ 要保证mapper接口和SQL映射文件UserMapper.xml在同一目录下有两种做法
1把SQL映射文件直接放在mapper包。但是不建议用这种方式因为映射文件属于是resources放java下不方便管理。
2在resources下建立一个mapper包把UserMapper.xml放到这个里面推荐使用
在resources下创建包的时候发现没有package只有directory所以如果要创建多级包的话需要用“/”进行分隔2、Mapper接口全限定名
//UserMapper.xml
mapper namespacecom.itheima.mapper.UserMapper3、映射文件中的SQL语句的ID保持与Mapper接口中定义方法一致
//UserMapper.java
ListUser selectAll();记得要同时改配置文件的路径
//mybatis-config.xml
mapper resourcecom/itheima/mapper/UserMapper.xml/4、编码main函数
package com.itheima;import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** Mybatis 代理开发*/
public class MyBatisDemo2 {public static void main(String[] args) throws IOException {//1. 加载mybatis的核心配置文件获取 SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象用它来执行sqlSqlSession sqlSession sqlSessionFactory.openSession();//3. 执行sql//ListUser users sqlSession.selectList(test.selectAll);//3.1 获取UserMapper接口的代理对象UserMapper userMapper sqlSession.getMapper(UserMapper.class);ListUser users userMapper.selectAll();System.out.println(users);//4. 释放资源sqlSession.close();}
}
具体步骤详解
首先获取sqlSession SqlSession sqlSession sqlSessionFactory.openSession();通过sqlSession来获取一个对应的mapper接口作为代理对象通过
UserMapper userMapper sqlSession.getMapper(UserMapper.class);这行代码就能找到UserMapper这个接口又因为在当前这个目录下有一个同名的映射文件所以可以找到对应的UserMapper.xml接着找到里面对应的SQL语句。
然后通过UserMapper.selectAll();来调用他的方法。一调方法这个方法对应的应该是一个sql语句的ID然后通过这个ID找到这个文件里面对应的ID有了ID就可以获取SQL语句。
又因为UserMapper.java中selectAll的返回值是个List所以它的底层执行的其实还是selectList所以就相当于自动帮你写了selectList那行代码
Mapper代理方式
更简单的写法
如果Mapper接口名称和SQL映射文件名称相同并在同一目录下则可以使用包扫描的方式简 化SQL映射文件的加载
//mybatis-config.xml
package namecom.itheima.mapper/Mapper核心配置文件
mybatis-config.xml 用于配置数据库连接环境信息可以配置多个用来配置多个数据库比如开发的数据库用于测试的数据库还可以调整动态的切换数据源 这个先不用修改之后的Spring 会进行管理 数据库连接池MyBatis默认的是POOLED不用修改Spring管理 类型别名 扫描com.itheima.pojo这个包下给这个包里的所有实体类起了一个别名默认不区分大小写也可以不用带包的名称UserMapper.xml中的resultType里可以直接写那个别名 typeAliasespackage namecom.itheima.pojo/
/typeAliases注意配置各个标签的时候需要遵循前后顺序 配置文件、注解两种方式
配置文件完成增删改查
就是将SQL语句写到配置文件里完成条件查询批量删除的操作
1配置文件实现CRUD 如上图所示产品原型里面包含了品牌数据的 查询 、按条件查询、添加、删除、批量删除、修改 等功能而这些功能其实就是对数据库表中的数据进行CRUD操作。接下来我们就使用Mybatis完成品牌数据的增删改查操作。以下是我们要完成功能列表 查询 查询所有数据查询详情条件查询 添加修改 修改全部字段修改动态字段 删除 删除一个批量删除 我们先将必要的环境准备一下。
1.1 环境准备 数据库表tb_brand及数据准备 -- tb_brand.sql
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(-- id 主键id int primary key auto_increment,-- 品牌名称brand_name varchar(20),-- 企业名称company_name varchar(20),-- 排序字段ordered int,-- 描述信息description varchar(100),-- 状态0禁用 1启用status int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values (三只松鼠, 三只松鼠股份有限公司, 5, 好吃不上火, 0),(华为, 华为技术有限公司, 100, 华为致力于把数字世界带入每个人、每个家庭、每个组织构建万物互联的智能世界, 1),(小米, 小米科技有限公司, 50, are you ok, 1);实体类 Brand 在 com.itheima.pojo 包下创建 Brand 实体类。 //Brand.java
public class Brand {// id 主键private Integer id;// 品牌名称private String brandName;// 企业名称private String companyName;// 排序字段private Integer ordered;// 描述信息private String description;// 状态0禁用 1启用private Integer status;//省略 setter and getter。自己写时要补全这部分代码
}编写测试用例 测试代码需要在 test/java 目录下创建包及测试用例。项目结构如下 安装 MyBatisX 插件 MybatisX 是一款基于 IDEA 的快速开发插件为效率而生。 主要功能 XML映射配置文件 和 接口方法 间相互跳转根据接口方法生成 statement 安装方式 点击 file 选择 settings 就能看到如下图所示界面 注意安装完毕后需要重启IDEA 插件效果 红色头绳的表示映射配置文件(UserMapper.xml)蓝色头绳的表示mapper接口(UserMapper.java)。在mapper接口点击红色头绳的小鸟图标会自动跳转到对应的映射配置文件在映射配置文件中点击蓝色头绳的小鸟图标会自动跳转到对应的mapper接口。也可以在mapper接口中定义方法自动生成映射配置文件中的 statement 如图所示 1.2 查询所有数据 如上图所示就页面上展示的数据而这些数据需要从数据库进行查询。接下来我们就来讲查询所有数据功能而实现该功能我们分以下步骤进行实现 编写接口方法Mapper接口 参数无 查询所有数据功能是不需要根据任何条件进行查询的所以此方法不需要参数。 结果List 我们会将查询出来的每一条数据封装成一个 Brand 对象而多条数据封装多个 Brand 对象需要将这些对象封装到List集合中返回。 执行方法、测试
1.2.1 编写接口方法
在 java下的com.itheima.mapper 包写创建名为 BrandMapper.java 的接口。并在该接口中定义 ListBrand selectAll() 方法。
public interface BrandMapper {/*** 查询所有*/ListBrand selectAll();
}1.2.2 编写SQL语句
在 reources 下创建 com/itheima/mapper 目录结构并在该目录下创建名为 BrandMapper.xml 的映射配置文件来编写SQL
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.itheima.mapper.BrandMapperselect idselectAll resultTypebrand //id和上面接口名一样select *from tb_brand;/select
/mapper1.2.3 编写测试方法
在test下test包中的 MybatisTest 类中编写测试查询所有的方法
Test
public void testSelectAll() throws IOException {//1. 获取SqlSessionFactory对象用这个对象去加载核心配置文件String resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 然后来获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//3. 获取Mapper接口的代理对象把BrandMapper.class传进去返回一个brandMapper对象BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);//4. 执行方法返回ListListBrand brands brandMapper.selectAll();System.out.println(brands);//5. 释放资源sqlSession.close();}注意现在我们感觉测试这部分代码写起来特别麻烦我们可以先忍忍。以后我们只会写上面的第3步的代码其他的都不需要我们来完成。 执行测试方法结果如下 从上面结果我们看到了问题有些数据封装成功了而有些数据并没有封装成功。为什么这样呢
这个问题可以通过两种方式进行解决
给字段起别名使用resultMap定义字段和属性的映射关系
1.2.4 起别名解决上述问题
从上面结果可以看到 brandName 和 companyName 这两个属性的数据没有封装成功查询 实体类 和 表中的字段 发现在实体类中属性名是 brandName 和 companyName 而表中的字段名为 brand_name 和 company_name如下图所示 。那么我们只需要保持这两部分的名称一致这个问题就迎刃而解。 我们可以在写sql语句时给这两个字段起别名将别名定义成和属性名一致即可。
select idselectAll resultTypebrandselectid, brand_name as brandName, company_name as companyName, ordered, description, statusfrom tb_brand;
/select而上面的SQL语句中的字段列表书写麻烦如果表中还有更多的字段同时其他的功能也需要查询这些字段时就显得我们的代码不够精炼。Mybatis提供了sql 片段可以提高sql的复用性。
SQL片段 将需要复用的SQL片段抽取到 sql 标签中 sql idbrand_columnid, brand_name as brandName, company_name as companyName, ordered, description, status
/sqlid属性值是唯一标识引用时也是通过该值进行引用。 在原sql语句中进行引用 使用 include 标签引用上述的 SQL 片段而 refid 指定上述 SQL 片段的id值。 select idselectAll resultTypebrandselectinclude refidbrand_column /from tb_brand;
/select1.2.5 使用resultMap解决上述问题
起别名 sql片段的方式可以解决上述问题但是它也存在问题。如果还有功能只需要查询部分字段而不是查询所有字段那么我们就需要再定义一个 SQL 片段这就显得不是那么灵活。
那么我们也可以使用resultMap来定义字段和属性的映射关系的方式解决上述问题。 在映射配置文件中使用resultMap定义 字段 和 属性 的映射关系 resultMap idbrandResultMap typebrand!--id完成主键字段的映射column表的列名property实体类的属性名result完成一般字段的映射column表的列名property实体类的属性名--result columnbrand_name propertybrandName/result columncompany_name propertycompanyName/
/resultMap注意在上面只需要定义 字段名 和 属性名 不一样的映射而一样的则不需要专门定义出来。 SQL语句正常编写 select idselectAll resultMapbrandResultMapselect *from tb_brand;
/select1.2.6 小结
实体类属性名 和 数据库表列名 不一致不能自动封装数据
起别名在SQL语句中对不一样的列名起别名别名和实体类属性名一样 可以定义 片段提升复用性 resultMap定义 完成不一致的属性名和列名的映射
而我们最终选择使用 resultMap的方式。查询映射配置文件中查询所有的 statement 书写如下 resultMap idbrandResultMap typebrand!--id完成主键字段的映射column表的列名property实体类的属性名result完成一般字段的映射column表的列名property实体类的属性名--result columnbrand_name propertybrandName/result columncompany_name propertycompanyName/
/resultMapselect idselectAll resultMapbrandResultMapselect *from tb_brand;
/select1.3 查询详情 有些数据的属性比较多在页面表格中无法全部实现而只会显示部分而其他属性数据的查询可以通过 查看详情 来进行查询如上图所示。
查看详情功能实现步骤 编写接口方法Mapper接口 参数id 查看详情就是查询某一行数据所以需要根据id进行查询。而id以后是由页面传递过来。 结果Brand 根据id查询出来的数据只要一条而将一条数据封装成一个Brand对象即可 编写SQL语句SQL映射文件 执行方法、进行测试
1.3.1 编写接口方法
在 BrandMapper 接口中定义根据id查询数据的方法
/*** 查看详情根据Id查询*/
Brand selectById(int id);1.3.2 编写SQL语句
在 BrandMapper.xml 映射配置文件中编写 statement使用 resultMap 而不是使用 resultType
select idselectById resultMapbrandResultMapselect *from tb_brand where id #{id};
/select注意上述SQL中的 #{id}先这样写一会我们再详细讲解 1.3.3 编写测试方法
在 test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法 Test
public void testSelectById() throws IOException {//接收参数该id以后需要传递过来int id 1;//1. 获取SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//3. 获取Mapper接口的代理对象BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);//4. 执行方法Brand brand brandMapper.selectById(id);System.out.println(brand);//5. 释放资源sqlSession.close();
}执行测试方法结果如下 1.3.4 参数占位符
查询到的结果很好理解就是id为1的这行数据。而这里我们需要看控制台显示的SQL语句能看到使用进行占位。说明我们在映射配置文件中的写的 #{id} 最终会被进行占位。接下来我们就聊聊映射配置文件中的参数占位符。
mybatis提供了两种参数占位符 #{} 执行SQL时会将 #{} 占位符替换为将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是 PreparedStatement参数传递时候用安全 ${} 拼接SQL。底层使用的是 Statement会存在SQL注入问题适合用在表名或者列名不固定的情况。如下图将 映射配置文件中的 #{} 替换成 ${} 来看效果 select idselectById resultMapbrandResultMapselect *from tb_brand where id ${id};
/select重新运行查看结果如下 注意从上面两个例子可以看出以后开发我们使用 #{} 参数占位符。 1.3.5 parameterType使用
对于有参数的mapper接口方法我们在映射配置文件中应该配置 ParameterType 来指定参数类型。只不过该属性都可以省略。如下图
select idselectById parameterTypeint resultMapbrandResultMapselect *from tb_brand where id ${id};
/select1.3.6 SQL语句中特殊字段处理
以后肯定会在SQL语句中写一下特殊字符比如某一个字段大于某个值如下图 可以看出报错了因为映射配置文件是xml类型的问题而 等这些字符在xml中有特殊含义所以此时我们需要将这些符号进行转义可以使用以下两种方式进行转义 转义字符 下图的 lt; 就是 的转义字符。 ![CDATA[内容]] 1.4 多条件查询 我们经常会遇到如上图所示的多条件查询将多条件查询的结果展示在下方的数据列表中。而我们做这个功能需要分析最终的SQL语句应该是什么样思考两个问题
条件表达式如何连接
条件字段 企业名称 和 品牌名称 需要进行模糊查询所以条件应该是 简单的分析后我们来看功能实现的步骤 编写接口方法 参数所有查询条件结果List 在映射配置文件中编写SQL语句 编写测试方法并执行
1.4.1 编写接口方法
在 BrandMapper 接口中定义多条件查询的方法。
而该功能有三个参数我们就需要考虑定义接口时参数应该如何定义。Mybatis针对多参数有多种实现 散装参数 如果方法中有多个参数需要使用 Param(参数名称) 标记每一个参数在映射配置文件中就需要使用 #{参数名称} 进行占位。 ListBrand selectByCondition(Param(status) int status, Param(companyName) String companyName,Param(brandName) String brandName);**对象类封装参数**对象的属性名称要和参数占位符名称一样 将多个参数封装成一个 实体对象 将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时里面的内容必须和实体类属性名保持一致。 ListBrand selectByCondition(Brand brand);map集合 将多个参数封装到map集合中将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时里面的内容必须和map集合中键的名称一致。 ListBrand selectByCondition(Map map);1.4.2 编写SQL语句
在 BrandMapper.xml 映射配置文件中编写 statement使用 resultMap 而不是使用 resultType
select idselectByCondition resultMapbrandResultMapselect *from tb_brandwhere status #{status}and company_name like #{companyName}and brand_name like #{brandName}
/select1.4.3 编写测试方法
在 test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法
Test
public void testSelectByCondition() throws IOException {//接收参数int status 1;String companyName 华为;String brandName 华为;// 处理参数companyName % companyName %;brandName % brandName %;//1. 获取SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//3. 获取Mapper接口的代理对象BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);//4. 执行方法//方式一 接口方法参数使用 Param 方式调用的方法//ListBrand brands brandMapper.selectByCondition(status, companyName, brandName);//方式二 接口方法参数是 实体类对象 方式调用的方法//封装对象/* Brand brand new Brand();brand.setStatus(status);brand.setCompanyName(companyName);brand.setBrandName(brandName);*///ListBrand brands brandMapper.selectByCondition(brand);//方式三 接口方法参数是 map集合对象 方式调用的方法Map map new HashMap();map.put(status , status);map.put(companyName, companyName);map.put(brandName , brandName);ListBrand brands brandMapper.selectByCondition(map);System.out.println(brands);//5. 释放资源sqlSession.close();
}1.4.4 动态SQL
上述功能实现存在很大的问题。用户在输入条件时肯定不会所有的条件都填写这个时候我们的SQL语句就不能那样写的
例如用户只输入 当前状态 时SQL语句就是
select * from tb_brand where status #{status}而用户如果只输入企业名称时SQL语句就是
select * from tb_brand where company_name like #{companName}而用户如果输入了 当前状态 和 企业名称 时SQL语句又不一样
select * from tb_brand where status #{status} and company_name like #{companName}针对上述的需要Mybatis对动态SQL有很强大的支撑 if choose (when, otherwise) trim (where, set) foreach 我们先学习 if 标签和 where 标签 if 标签条件判断 test 属性逻辑表达式 select idselectByCondition resultMapbrandResultMapselect *from tb_brandwhereif teststatus ! nulland status #{status}/ifif testcompanyName ! null and companyName ! and company_name like #{companyName}/ifif testbrandName ! null and brandName ! and brand_name like #{brandName}/if
/select如上的这种SQL语句就会根据传递的参数值进行动态的拼接。如果此时status和companyName有值那么就会值拼接这两个条件。 执行结果如下 但是它也存在问题如果此时给的参数值是 Map map new HashMap();
// map.put(status , status);
map.put(companyName, companyName);
map.put(brandName , brandName);拼接的SQL语句就变成了 select * from tb_brand where and company_name like ? and brand_name like ?而上面的语句中 where 关键后直接跟 and 关键字这就是一条错误的SQL语句。这个就可以使用 where 标签解决。 插一句也可以改变语句来解决 // 每一条前面都加and, 然后在最前面写where 11
select idselectByCondition resultMapbrandResultMapselect *from tb_brandwhere 1 1if teststatus ! nulland status #{status}/ifif testcompanyName ! null and companyName ! and company_name like #{companyName}/ifif testbrandName ! null and brandName ! and brand_name like #{brandName}/if/selectwhere 标签 作用 替换where关键字会动态的去掉第一个条件前的 and如果所有的参数没有值则不加where关键字 select idselectByCondition resultMapbrandResultMapselect *from tb_brandwhereif teststatus ! nulland status #{status}/ifif testcompanyName ! null and companyName ! and company_name like #{companyName}/ifif testbrandName ! null and brandName ! and brand_name like #{brandName}/if/where
/select注意需要给每个条件前都加上 and 关键字。
1.5 单个条件动态SQL 如上图所示在查询时只能选择 品牌名称、当前状态、企业名称 这三个条件中的一个但是用户到底选择哪儿一个我们并不能确定。这种就属于单个条件的动态SQL语句。
这种需求需要使用到 choosewhenotherwise标签 实现 而 choose 标签类似于Java 中的switch语句when就是caseotherwise就是default。
通过一个案例来使用这些标签
1.5.1 编写接口方法
在 BrandMapper 接口中定义单条件查询的方法。
/*** 单条件动态查询* param brand* return*/
ListBrand selectByConditionSingle(Brand brand);1.5.2 编写SQL语句
在 BrandMapper.xml 映射配置文件中编写 statement使用 resultMap 而不是使用 resultType
select idselectByConditionSingle resultMapbrandResultMapselect *from tb_brandwherechoose!--相当于switch--when teststatus ! null!--相当于case--status #{status}/whenwhen testcompanyName ! null and companyName ! !--相当于case--company_name like #{companyName}/whenwhen testbrandName ! null and brandName ! !--相当于case--brand_name like #{brandName}/when/choose/where
/select1.5.3 编写测试方法
在 test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法
Test
public void testSelectByConditionSingle() throws IOException {//接收参数int status 1;String companyName 华为;String brandName 华为;// 处理参数companyName % companyName %;brandName % brandName %;//封装对象Brand brand new Brand();//brand.setStatus(status);brand.setCompanyName(companyName);//brand.setBrandName(brandName);//1. 获取SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//3. 获取Mapper接口的代理对象BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);//4. 执行方法ListBrand brands brandMapper.selectByConditionSingle(brand);System.out.println(brands);//5. 释放资源sqlSession.close();
}执行测试方法结果如下 那么这里也有个问题如果用户一个都不选这个值就是空where后面没有东西就会报错怎么解决呢choose标签下还有一个标签代码如下
select idselectByConditionSingle resultMapbrandResultMapselect *from tb_brandwherechoose!--相当于switch--when teststatus ! null!--相当于case--status #{status}/whenwhen testcompanyName ! null and companyName ! !--相当于case--company_name like #{companyName}/whenwhen testbrandName ! null and brandName ! !--相当于case--brand_name like #{brandName}/whenotherwise11/otherwise/choose
/select但是推荐用标签就不用特意写一个otherwise了
1.6 添加数据 如上图是我们平时在添加数据时展示的页面而我们在该页面输入想要的数据后添加 提交 按钮就会将这些数据添加到数据库中。接下来我们就来实现添加数据的操作。 编写接口方法 参数除了id之外的所有的数据。id对应的是表中主键值而主键我们是 自动增长 生成的。不需要返回什么所以void。 编写SQL语句 编写测试方法并执行
明确了该功能实现的步骤后接下来我们进行具体的操作。
1.6.1 编写接口方法
在 BrandMapper 接口中定义添加方法。 /*** 添加*/
void add(Brand brand);1.6.2 编写SQL语句
在 BrandMapper.xml 映射配置文件中编写添加数据的 statement
insert idaddinsert into tb_brand (brand_name, company_name, ordered, description, status)values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
/insert1.6.3 编写测试方法
在 test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法
Test
public void testAdd() throws IOException {//接收参数int status 1;String companyName 波导手机;String brandName 波导;String description 手机中的战斗机;int ordered 100;//封装对象Brand brand new Brand();brand.setStatus(status);brand.setCompanyName(companyName);brand.setBrandName(brandName);brand.setDescription(description);brand.setOrdered(ordered);//1. 获取SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//SqlSession sqlSession sqlSessionFactory.openSession(true); //设置自动提交事务这种情况不需要手动提交事务了//3. 获取Mapper接口的代理对象BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.add(brand);//4.1提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}执行结果如下 这里要注意insert操作必须要有commit();操作(4.1)不然事务会回滚记录进不了数据库。如果不写commit();可以设置自动提交事务这种情况不需要手动提交事务了
SqlSession sqlSession sqlSessionFactory.openSession(true); 1.6.4 添加-主键返回
在数据添加成功后有时候需要获取插入数据库数据的主键主键是自增长。
比如添加订单和订单项如下图就是京东上的订单 订单数据存储在订单表中订单项存储在订单项表中。 添加订单数据 添加订单项数据订单项中需要设置所属订单的id
添加完订单项后需要返回一个订单id代表加在了这个订单中。
明白了什么时候 主键返回 。接下来我们简单模拟一下在添加完数据后打印id属性值能打印出来说明已经获取到了。
我们将上面添加品牌数据的案例中映射配置文件里 statement 进行修改如下
insert idadd useGeneratedKeystrue keyPropertyidinsert into tb_brand (brand_name, company_name, ordered, description, status)values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
/insert在 insert 标签上添加如下属性 useGeneratedKeys是够获取自动增长的主键值。true表示获取。默认是falsekeyProperty 指定将获取到的主键值封装到哪儿个属性里也就是主键 1.7 修改 如图所示是修改页面用户在该页面书写需要修改的数据点击 提交 按钮就会将数据库中对应的数据进行修改。注意一点如果哪儿个输入框没有输入内容我们是将表中数据对应字段值替换为空白还是保留字段之前的值答案肯定是保留之前的数据。
接下来我们就具体来实现
1.7.1 编写接口方法
在 BrandMapper 接口中定义修改方法。 /*** 修改*/
void update(Brand brand);上述方法参数 Brand 就是封装了需要修改的数据而id肯定是有数据的这也是和添加方法的区别。 1.7.2 编写SQL语句
在 BrandMapper.xml 映射配置文件中编写修改数据的 statement。
update idupdateupdate tb_brandsetif testbrandName ! null and brandName ! brand_name #{brandName},/ifif testcompanyName ! null and companyName ! company_name #{companyName},/ifif testordered ! nullordered #{ordered},/ifif testdescription ! null and description ! description #{description},/ifif teststatus ! nullstatus #{status}/if/setwhere id #{id};
/updateset 标签可以用于动态包含需要更新的列忽略其它不更新的列。 1.7.3 编写测试方法
在 test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法
Test
public void testUpdate() throws IOException {//接收参数int status 0;String companyName 波导手机;String brandName 波导;String description 波导手机,手机中的战斗机;int ordered 200;int id 6;//封装对象Brand brand new Brand();brand.setStatus(status);// brand.setCompanyName(companyName);// brand.setBrandName(brandName);// brand.setDescription(description);// brand.setOrdered(ordered);brand.setId(id);//1. 获取SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//SqlSession sqlSession sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);//4. 执行方法int count brandMapper.update(brand);System.out.println(count);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}在MyBatis中当执行如update、insert或delete这样的数据修改操作时返回值通常表示的是这些操作影响的数据库记录的行数。
执行测试方法结果如下 从结果中SQL语句可以看出只修改了 status 字段值因为我们给的数据中只给Brand实体对象的 status 属性设置值了。这就是 set 标签的作用。
1.8 删除一行数据 如上图所示每行数据后面都有一个 删除 按钮当用户点击了该按钮就会将该行数据删除掉。那我们就需要思考这种删除是根据什么进行删除呢是通过主键id删除因为id是表中数据的唯一标识。
接下来就来实现该功能。
1.8.1 编写接口方法
在 BrandMapper 接口中定义根据id删除方法。
/*** 根据id删除*/
void deleteById(int id);1.8.2 编写SQL语句
在 BrandMapper.xml 映射配置文件中编写删除一行数据的 statement
delete iddeleteByIddelete from tb_brand where id #{id};
/delete1.8.3 编写测试方法
在 test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法 Test
public void testDeleteById() throws IOException {//接收参数int id 6;//1. 获取SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//SqlSession sqlSession sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.deleteById(id);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}运行过程只要没报错直接到数据库查询数据是否还存在。
1.9 批量删除 如上图所示用户可以选择多条数据然后点击上面的 删除 按钮就会删除数据库中对应的多行数据。
1.9.1 编写接口方法
在 BrandMapper 接口中定义删除多行数据的方法。
/*** 批量删除*/
void deleteByIds(int[] ids);参数是一个数组数组中存储的是多条数据的id 1.9.2 编写SQL语句
在 BrandMapper.xml 映射配置文件中编写删除多条数据的 statement。
编写SQL时需要遍历数组来拼接SQL语句。Mybatis 提供了 foreach 标签供我们使用
foreach 标签
用来迭代任何可迭代的对象如数组集合。
collection 属性遍历哪个集合或数组 mybatis会将数组参数封装为一个Map集合。 默认array 数组使用Param注解改变map集合的默认key的名称 item 属性本次迭代获取到的元素。每一个元素separator 属性集合项迭代之间的分隔符。foreach 标签不会错误地添加多余的分隔符。也就是最后一次迭代不会加分隔符。open 属性该属性值是在拼接SQL语句之前拼接的语句只会拼接一次close 属性该属性值是在拼接SQL语句拼接后拼接的语句只会拼接一次
delete iddeleteByIdsdelete from tb_brand where idinforeach collectionarray itemid separator, open( close)#{id}/foreach;
/delete假如数组中的id数据是{1,2,3}那么拼接后的sql语句就是 delete from tb_brand where id in (1,2,3);1.9.3 编写测试方法
在 test/java 下的 com.itheima.mapper 包下的 MybatisTest类中 定义测试方法
Test
public void testDeleteByIds() throws IOException {//接收参数int[] ids {5,7,8};//1. 获取SqlSessionFactoryString resource mybatis-config.xml;InputStream inputStream Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession sqlSessionFactory.openSession();//SqlSession sqlSession sqlSessionFactory.openSession(true);//3. 获取Mapper接口的代理对象BrandMapper brandMapper sqlSession.getMapper(BrandMapper.class);//4. 执行方法brandMapper.deleteByIds(ids);//提交事务sqlSession.commit();//5. 释放资源sqlSession.close();
}1.10 Mybatis参数传递
Mybatis 接口方法中可以接收各种各样的参数如下
多个参数单个参数单个参数又可以是如下类型 POJO 类型Map 集合类型Collection 集合类型List 集合类型Array 类型其他类型
1.10.1 多个参数
如下面的代码就是接收两个参数而接收多个参数需要使用 Param 注解那么为什么要加该注解呢这个问题要弄明白就必须来研究Mybatis 底层对于这些参数是如何处理的。
User select(Param(username) String username,Param(password) String password);select idselect resultTypeuserselect *from tb_userwhere username#{username}and password#{password}
/select我们在接口方法中定义多个参数Mybatis 会将这些参数封装成 Map 集合对象值就是参数值而键在没有使用 Param 注解时有以下命名规则 以 arg 开头 第一个参数就叫 arg0第二个参数就叫 arg1以此类推。如 map.put(“arg0”参数值1); map.put(“arg1”参数值2); 以 param 开头 第一个参数就叫 param1第二个参数就叫 param2依次类推。如 map.put(“param1”参数值1); map.put(“param2”参数值2);
代码验证 在 UserMapper 接口中定义如下方法 User select(String username,String password);在 UserMapper.xml 映射配置文件中定义SQL select idselect resultTypeuserselect *from tb_userwhere username#{arg0}and password#{arg1}
/select或者 select idselect resultTypeuserselect *from tb_userwhere username#{param1}and password#{param2}
/select运行代码结果如下 在映射配合文件的SQL语句中使用用 arg 开头的和 param 书写代码的可读性会变的特别差此时可以使用 Param 注解。
在接口方法参数上使用 Param 注解Mybatis 会将 arg 开头的键名替换为对应注解的属性值。
代码验证 在 UserMapper 接口中定义如下方法在 username 参数前加上 Param 注解 User select(Param(username) String username, String password);Mybatis 在封装 Map 集合时键名就会变成如下 map.put(“username”参数值1); map.put(“arg1”参数值2); map.put(“param1”参数值1); map.put(“param2”参数值2); 在 UserMapper.xml 映射配置文件中定义SQL select idselect resultTypeuserselect *from tb_userwhere username#{username}and password#{param2}
/select运行程序结果没有报错。而如果将 #{} 中的 username 还是写成 arg0 select idselect resultTypeuserselect *from tb_userwhere username#{arg0}and password#{param2}
/select运行程序则可以看到错误
结论以后接口参数是多个时在每个参数上都使用 Param 注解。这样代码的可读性更高。
1.10.2 单个参数 POJO 类型 直接使用。要求 属性名 和 参数占位符名称 一致 Map 集合类型 直接使用。要求 map集合的键名 和 参数占位符名称 一致 Collection 集合类型 Mybatis 会将集合封装到 map 集合中如下 map.put(“arg0”collection集合); map.put(“collection”collection集合; 可以使用 Param 注解替换map集合中默认的 arg 键名。 List 集合类型 Mybatis 会将集合封装到 map 集合中如下 map.put(“arg0”list集合); map.put(“collection”list集合); map.put(“list”list集合); 可以使用 Param 注解替换map集合中默认的 arg 键名。 Array 类型 Mybatis 会将集合封装到 map 集合中如下 map.put(“arg0”数组); map.put(“array”数组); 可以使用 Param 注解替换map集合中默认的 arg 键名。 其他类型 比如int类型参数占位符名称 叫什么都可以。尽量做到见名知意
建议将来都是用Param注解来修改Map集合中默认的键名并使用修改后的名称来获取值这样可读性更高
2注解实现CRUD
使用注解开发会比配置文件开发更加方便。如下就是使用注解进行开发
Select(value select * from tb_user where id #{id})
public User select(int id);注意 注解是用来替换映射配置文件方式配置的所以使用了注解就不需要再映射配置文件中书写对应的 statement Mybatis 针对 CURD 操作都提供了对应的注解已经做到见名知意。如下
查询 Select添加 Insert修改 Update删除 Delete
接下来我们做一个案例来使用 Mybatis 的注解开发
代码实现
将之前案例中 UserMapper.xml 中的 根据id查询数据 的 statement 注释掉 在 UserMapper 接口的 selectById 方法上添加注解 运行测试程序也能正常查询到数据
我们课程上只演示这一个查询的注解开发其他的同学们下来可以自己实现都是比较简单。
注意在官方文档中 入门 中有这样的一段话 所以注解完成简单功能配置文件完成复杂功能。
而我们之前写的动态 SQL 就是复杂的功能如果用注解使用的话就需要使用到 Mybatis 提供的SQL构建器来完成而对应的代码如下 上述代码将java代码和SQL语句融到了一块使得代码的可读性大幅度降低。