MavenMyBatis
MavenMyBatis
目标
能够使用Maven进行项目的管理
能够完成Mybatis代理方式查询数据
能够理解Mybatis核心配置文件的配置
1,Maven
Maven是专门用于管理和构建Java项目的工具,它的主要功能有:
提供了一套标准化的项目结构
提供了一套标准化的构建流程(编译,测试,打包,发布……)
提供了一套依赖管理机制
标准化的项目结构: 项目结构我们都知道,每一个开发工具(IDE)都有自己不同的项目结构,它们互相之间不通用。我再eclipse中创建的目录,无法在idea中进行使用,这就造成了很大的不方便,如下图:前两个是以后开发经常使用的开发工具
而Maven提供了一套标准化的项目结构,所有的IDE使用Maven构建的项目完全一样,所以IDE创建的Maven项目可以通用。如下图右边就是Maven构建的项目结构。
标准化的构建流程: 如上图所示我们开发了一套系统,代码需要进行编译、测试、打包、发布,这些操作如果需要反复进行就显得特别麻烦,而Maven提供了一套简单的命令来完成项目构建。
依赖管理: 依赖管理其实就是管理你项目所依赖的第三方资源(jar包、插件)。如之前我们项目中需要使用JDBC和Druid的话,就需要去网上下载对应的依赖包,复制到项目中,还要将jar包加入工作环境这一系列的操作。如下图所示
而Maven使用标准的 ==坐标== 配置来管理各种依赖,只需要简单的配置就可以完成依赖管理。
如上图右边所示就是mysql驱动包的坐标,在项目中只需要写这段配置,其他都不需要我们担心,Maven都帮我们进行操作了。
市面上有很多构建工具,而Maven依旧还是主流构建工具。
1.1 Maven简介
==Apache Maven== 是一个项目管理和构建==工具==,它基于项目对象模型(POM)的概念,通过一小段描述信息来管理项目的构建、报告和文档。
:Maven – Welcome to Apache Maven
通过上面的描述大家只需要知道Maven是一个工具即可。Apache 是一个开源组织,将来我们会学习很多Apache提供的项目。
1.1.1 Maven模型
项目对象模型 (Project Object Model)
依赖管理模型(Dependency)
插件(Plugin)
如上图所示就是Maven的模型,而我们先看紫框框起来的部分,他就是用来完成
标准化构建流程
。如我们需要编译,Maven提供了一个编译插件供我们使用,我们需要打包,Maven就提供了一个打包插件提供我们使用等。上图中紫框起来的部分,项目对象模型就是将我们自己抽象成一个对象模型,有自己专属的坐标,如下图所示是一个Maven项目:
依赖管理模型则是使用坐标来描述当前项目依赖哪儿些第三方jar包,如下图所示
上述Maven模型图中还有一部分是仓库。如何理解仓库呢?
1.1.2 仓库
大家想想这样的场景,我们创建Maven项目,在项目中使用坐标来指定项目的依赖,那么依赖的jar包到底存储在什么地方呢?其实依赖jar包是存储在我们的本地仓库中。而项目运行时从本地仓库中拿需要的依赖jar包。
仓库:用于存储资源,包含各种jar包。 仓库分类:
本地仓库:自己计算机上的一个目录,连接远程仓库获取资源
中央仓库:由Maven团队维护的全球唯一的仓库
地址: Central Repository:
远程仓库(私服):一般由公司团队搭建的私有仓库。非本机电脑的仓库,为本地仓库提供资源。
私服的作用:
- 保存具有版权的资源,包含购买或自主研发的jar
- 中央仓库里的jar都是开源的。不能存储具有版权的资源
- 一定范围内的共享资源,仅对内部开放,不对外共享
当项目中使用坐标引入对应依赖jar包后,首先会查本地仓库中是否有对应的jar包:
如果有,则在项目直接引用;
如果没有,则去中央仓库中下载对应的jar包到本地仓库。
如果还可以搭建远程仓库,将来jar包的查顺序则变为:
本地仓库 --> 远程仓库--> 中央仓库
1.2 Maven安装配置
解压 apache-maven-.6.1.rar 既安装完成
建议解压缩到没有中文、特殊字符的路径下。如课程中解压缩到
D:\soft
下。解压缩后的目录结构如下:
- bin目录 : 存放的是可执行命令。mvn 命令重点关注。
- conf目录 :存放Maven的配置文件。
settings.xml
配置文件后期需要修改。- lib目录 :存放Maven依赖的jar包。Maven也是使用java开发的,所以它也依赖其他的jar包。
配置环境变量 MAVE_HOME 为安装路径的bin目录
此电脑
右键 -->高级系统设置
-->高级
-->环境变量
在系统变量处新建一个变量
MAVE_HOME
在
Path
中进行配置打开命令提示符进行验证,出现如图所示表示安装成功
配置本地仓库
修改 conf/settings.xml 中的 <localRepository> 为一个指定目录作为本地仓库,用来存储jar包。
配置阿里云私服
中央仓库在国外,所以下载jar包速度可能比较慢,而阿里公司提供了一个远程仓库,里面基本也都有开源项目的jar包。
修改 conf/settings.xml 中的 <mirrors>标签,为其添加如下子标签:
<mirror> <id>alimaven</id> <name>aliyun maven</name> <url>/</url><mirrorOf>central</mirrorOf> </mirror>
全局setting与用户setting区别
- 全局setting定义了当前计算机里的Maven的公共配置
- 用户setting定义了当前用户的配置
1. Maven基本使用
1..1 Maven 常用命令
compile :编译
clean:清理
test:测试
package:打包
install:安装
命令演示:
在
资料\代码\maven-project
提供了一个使用Maven构建的项目,项目结构如下:而我们使用上面命令需要在磁盘上进入到项目的
pom.xml
目录下,打开命令提示符编译命令演示:
compile :编译执行上述命令可以看到:
从阿里云下载编译需要的插件的jar包,在本地仓库也能看到下载好的插件
在项目下会生成一个
target
目录同时在项目下会出现一个
target
目录,编译后的字节码文件就放在该目录下清理命令演示:
mvn clean执行上述命令可以看到
从阿里云下载清理需要的插件jar包
删除项目下的
target
目录打包命令演示:
mvn package执行上述命令可以看到:
从阿里云下载打包需要的插件jar包
在项目的
terget
目录下有一个jar包(将当前项目打成的jar包)测试命令演示:
mvn test该命令会执行所有的测试代码。执行上述命令效果如下
安装命令演示:
mvn install该命令会将当前项目打成jar包,并安装到本地仓库。执行完上述命令后到本地仓库查看结果如下:
插件创建工程
1..2 Maven 生命周期
Maven 构建项目生命周期描述的是一次构建过程经历经历了多少个事件
Maven 对项目构建的生命周期划分为套:
clean :清理工作。
default :核心工作,例如编译,测试,打包,安装,部署等。
site : 产生报告,发布站点等。这套声明周期一般不会使用。
clean生命周期
- pre-clean 执行一些需要在clean之前完成的工作
- clean 移除所有上一次构建生成的文件
- post-clean 执行一些需要在clean之后立刻完成的工作
site生命周期
- pre-site 执行一些需要在生成站点文档之前完成的工作
- site 生成项目的站点文档
- post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
- site-deploy 将生成的站点文档部署到特定的服务器上
default构建生命周期 同一套生命周期内,执行后边的命令,前面的所有命令会自动执行。例如默认(default)生命周期如下:
- 当我们执行
install
(安装)命令时,它会先执行compile
命令,再执行test
命令,再执行package
命令,最后执行install
命令。- 当我们执行
package
(打包)命令时,它会先执行compile
命令,再执行test
命令,最后执行package
命令。默认的生命周期也有对应的很多命令,其他的一般都不会使用,我们只关注常用的:
1.4 IDEA使用Maven
以后开发中我们肯定会在高级开发工具中使用Maven管理项目,而我们常用的高级开发工具是IDEA,所以接下来我们会讲解Maven在IDEA中的使用。
1.4.1 IDEA配置Maven环境
我们需要先在IDEA中配置Maven环境:
选择 IDEA中 File --> Settings
- 搜索maven
- 设置 IDEA 使用本地安装的 Maven,并修改配置文件路径
1.4.2 Maven 坐标详解
什么是坐标?
Maven 中的坐标是==资源的唯一标识==
使用坐标来定义项目或引入项目中需要的依赖
Maven 坐标主要组成
groupId:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.alibaba)
artifactId:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods-service)
version:定义当前项目版本号
Maven坐标的作用: 使用唯一标识,唯一性定位资源位置,通过该标识可以将资源的识别与下载工作交由机器完成。
如下图就是使用坐标表示一个项目:
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.2</version> </dependency>
==注意:==
上面所说的资源可以是插件、依赖、当前项目。
我们的项目如果被其他的项目依赖时,也是需要坐标来引入的。
1.4. IDEA 创建 Maven项目
创建模块,选择Maven,点击ext
- 填写模块名称,坐标信息,点击finish,创建完成
创建好的项目目录结构如下:
编写 HelloWorld,并运行
1.4.4 IDEA 导入 Maven项目
我们可以通过以下步骤进行项目的导入:
选择右侧Maven面板,点击 号
- 选中对应项目的pom.xml文件,双击即可
- 如果没有Maven面板,选择
- View --> Appearance --> Tool Window Bars
- 可以通过下图所示进行命令的操作:
配置 Maven-Helper 插件
选择 IDEA中 File --> Settings
- 选择 Plugins
- 搜索 Maven,选择第一个 Maven Helper,点击Install安装,弹出面板中点击Accept
重启 IDEA
安装完该插件后可以通过 选中项目右键进行相关命令操作,如下图所示:
1.5 依赖管理
1.5.1 使用坐标引入jar包
使用坐标引入jar包的步骤:
在项目的 pom.xml 中编写 <dependencies> 标签
在 <dependencies> 标签中 使用 <dependency> 引入坐标
定义坐标的 groupId,artifactId,version
<!-- 导入 mysql 驱动jar包--> <!-- 设置当前项目所依赖的所有jar--><dependencies> <!-- 设置具体的依赖--><dependency> <!-- 依赖所属组id--><groupId>mysql</groupId> <!-- 依赖所属项目id--><artifactId>mysql-connector-java</artifactId> <!-- 依赖版本号--><version>5.1.2</version></dependency></dependencies>
点击刷新按钮,使坐标生效
注意:
具体的坐标我们可以到如下网站进行搜索
/
快捷方式导入jar包的坐标:
每次需要引入jar包,都去对应的网站进行搜索是比较麻烦的,接下来给大家介绍一种快捷引入坐标的方式
在 pom.xml 中 按 alt insert,选择 Dependency
在弹出的面板中搜索对应坐标,然后双击选中对应坐标
点击刷新按钮,使坐标生效
自动导入设置:
上面每次操作都需要点击刷新按钮,让引入的坐标生效。当然我们也可以通过设置让其自动完成
选择 IDEA中 File --> Settings
在弹出的面板中到 Build Tools
选择 Any changes,点击 ok 即可生效
依赖传递
依赖具有传递性:
- 直接依赖:在当前项目里通过依赖配置建立的依赖关系
- 简介依赖:被资源的资源如果依赖其它资源,当前项目间接依赖其它资源
依赖传递冲突问题
路径优先:当依赖里出现相同的资源时,层级越深,优先级越低,层级越浅,优先级越高。
声明优先:当资源在相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后的
特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的。
可选依赖(不透明)
可选依赖指对隐藏当前所依赖的资源——不透明
optional:为true
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope><optional>true</optional></dependency>
排除依赖(不需要)
排除依赖指主动断开依赖的资源,被排除的资源无需指定版本——不需要
<exclusi> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId></exclusion> </exclusi>
1.5.2 依赖范围
通过设置坐标的依赖范围(scope),可以设置对应jar包的作用范围:编译环境、测试环境、运行环境。 如下图所示给
junit
依赖通过scope
标签指定依赖的作用范围。 那么这个依赖就只能作用在测试环境,其他环境下不能使用。<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.1</version><scope>test</scope></dependency>
那么
scope
都可以有哪些取值呢?
依赖范围 编译classpath 测试classpath 运行classpath 例子 compile(默认) Y Y Y logback test - Y - Junit provided Y Y - servlet-api runtime - Y Y jdbc驱动 system Y Y - 存储在本地的jar包
compile :作用于编译环境、测试环境、运行环境。
test : 作用于测试环境。典型的就是Junit坐标,以后使用Junit时,都会将scope指定为该值
provided :作用于编译环境、测试环境。我们后面会学习
servlet-api
,在使用它时,必须将scope
设置为该值,不然运行时就会报错runtime : 作用于测试环境、运行环境。jdbc驱动一般将
scope
设置为该值,当然不设置也没有任何问题注意:
如果引入坐标不指定
scope
标签时,默认就是 compile 值。以后大部分jar包都是使用默认值。依赖管理传递性
带有依赖范围的资源在进行传递时,作用范围将受到影响
2、Mybatis
2.1 Mybatis概述
2.1.1 Mybatis概念
MyBatis 是一款优秀的==持久层框架==,用于简化 JDBC 开发
MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。201年11月迁移到Github
:mybatis – MyBatis | 简介
持久层:
负责将数据到保存到数据库的那一层代码。
以后开发我们会将操作数据库的Java代码作为持久层。而Mybatis就是对jdbc代码进行了封装。
JavaEE三层架构:表现层、业务层、持久层
框架:
框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
在框架的基础之上构建软件编写更加高效、规范、通用、可扩展
举例给大家简单的解释一下什么是半成品软件。大家小时候见过给石膏娃娃涂鸦,有一个石膏娃娃,这个就是一个半成品。你可以在这个半成品的基础上进行不同颜的涂鸦。
了解了什么是Mybatis后,接下来说说以前
JDBC代码
的缺点以及Mybatis又是如何解决的。
2.1.2 JDBC 缺点
下面是 JDBC 代码,我们通过该代码分析都存在什么缺点:
硬编码
注册驱动、获取连接
上图标1的代码有很多字符串,而这些是连接数据库的四个基本信息,以后如果要将Mysql数据库换成其他的关系型数据库的话,这四个地方都需要修改,如果放在此处就意味着要修改我们的源代码。
SQL语句
上图标2的代码。如果表结构发生变化,SQL语句就要进行更改。这也不方便后期的维护。
操作繁琐
手动设置参数
手动封装结果集
上图标4的代码是对查询到的数据进行封装,而这部分代码是没有什么技术含量,而且特别耗费时间的。
2.1. Mybatis 优化
硬编码可以配置到==配置文件==
操作繁琐的地方mybatis都==自动完成==
如图所示:
MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作
2.2 Mybatis快速入门
需求:查询user表中所有的数据
创建user表,添加数据
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(0) ); ISERT ITO tb_user VALUES (1, zhangsan , 12 , 男 , 北京 ); ISERT ITO tb_user VALUES (2, 李四 , 24 , 女 , 天津 ); ISERT ITO tb_user VALUES (, 王五 , 11 , 男 , 西安 );
创建模块,导入坐标
在创建好的模块中的 pom.xml 配置文件中添加依赖的坐标
<dependencies><!--mybatis 依赖--><dependency><groupId></groupId><artifactId>mybatis</artifactId><version>.5.5</version></dependency> <!--mysql 驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency> <!--junit 单元测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.1</version><scope>test</scope></dependency> <!-- 添加slf4j日志api --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.20</version></dependency><!-- 添加logback-classic依赖 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.</version></dependency><!-- 添加logback-core依赖 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.</version></dependency> </dependencies>
注意:需要在项目的 resources 目录下创建logback的配置文件
编写 MyBatis 核心配置文件 -- > 替换连接信息 解决硬编码问题
在模块下的 resources 目录下创建mybatis的配置文件
mybatis-config.xml
,内容如下:<?xml version=1.0 encoding=UTF-8 ?> <!DOCTYPE configurationPUBLIC -//mybatis//DTD Config .0//E.dtd> <configuration> <typeAliases><package name=com.itheima.pojo/></typeAliases><!--environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment--><environments default=development><environment id=development><transactionManager type=JDBC/><dataSource type=POOLED><!--数据库连接信息--><property name=driver value=jdbc.Driver/><property name=url value=jdbc:mysql:///mybatis?useSSL=false/><property name=username value=root/><property name=password value=124/></dataSource></environment> <environment id=test><transactionManager type=JDBC/><dataSource type=POOLED><!--数据库连接信息--><property name=driver value=jdbc.Driver/><property name=url value=jdbc:mysql:///mybatis?useSSL=false/><property name=username value=root/><property name=password value=124/></dataSource></environment></environments><mappers><!--加载sql映射文件--><mapper resource=UserMapper.xml/></mappers> </configuration>
编写 SQL 映射文件 --> 统一管理sql语句,解决硬编码问题
在模块的
resources
目录下创建映射配置文件UserMapper.xml
,内容如下:<?xml version=1.0 encoding=UTF-8 ?> <!DOCTYPE mapper PUBLIC -//mybatis//DTD Mapper .0//E .dtd> <mapper namespace=test><select id=selectAll resultType=com.itheima.pojo.User>select * from tb_user;</select> </mapper>
编码
在
com.itheima.pojo
包下创建 User类public class User {private int id;private String username;private String password;private String gender;private String addr;//省略了 setter 和 getter }
在
com.itheima
包下编写 MybatisDemo 测试类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 = ();//. 执行sqlList<User> users = sqlSession.selectList(test.selectAll); //参数是一个字符串,该字符串必须是映射配置文件的namespace.println(users);//4. 释放资源();} }
解决SQL映射文件的警告提示:
在入门案例映射配置文件中存在报红的情况。问题如下:
产生的原因:Idea和数据库没有建立连接,不识别表信息。但是大家一定要记住,它并不影响程序的执行。
解决方式:在Idea中配置MySQL数据库连接。
IDEA中配置MySQL数据库连接
点击IDEA右边框的
Database
,在展开的界面点击选择
Data Source
,再选择MySQL
在弹出的界面进行基本信息的填写
点击完成后就能看到如下界面
而此界面就和
navicat
工具一样可以进行数据库的操作。也可以编写SQL语句
2.Mapper代理开发
2..1 Mapper代理开发概述
之前我们写的代码是基本使用方式,它也存在硬编码的问题,如下:
这里调用
selectList()
方法传递的参数是映射配置文件中的 namespace.id值。这样写也不便于后期的维护。如果使用 Mapper 代理方式(如下图)则不存在硬编码问题。通过上面的描述可以看出 Mapper 代理方式的目的:
解决原生方式中的硬编码
简化后期执行SQL
Mybatis 也是推荐使用 Mapper 代理的方式。下图是截止的图片
2..2 使用Mapper代理要求
使用Mapper代理方式,必须满足以下要求:
定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下。如下图:
设置SQL映射文件的namespace属性为Mapper接口全限定名
在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
2.. 案例代码实现
在
com.
包下创建 UserMapper接口,代码如下:public interface UserMapper {List<User> selectAll();User selectById(int id); }
在
resources
下创建com/itheima/mapper
目录,并在该目录下创建 UserMapper.xml 映射配置文件<!--namespace:名称空间。必须是对应接口的全限定名 --> <mapper namespace=com..UserMapper><select id=selectAll resultType=com.itheima.pojo.User>select *from tb_user;</select> </mapper>
在
com.itheima
包下创建 MybatisDemo2 测试类,代码如下:/*** 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 = ();//. 执行sql//.1 获取UserMapper接口的代理对象UserMapper userMapper = sqlSession.getMapper();List<User> users = userMapper.selectAll(); println(users);//4. 释放资源();} }
==注意:==
如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载。也就是将核心配置文件的加载映射配置文件的配置修改为
<mappers><!--加载sql映射文件--><!-- <mapper resource=com/itheima/mapper/UserMapper.xml/>--><!--Mapper代理方式--><package name=com./> </mappers>
2.4 核心配置文件
核心配置文件中现有的配置之前已经给大家进行了解释,而核心配置文件中还可以配置很多内容。我们可以通过查询看可以配置的内容。
接下来我们先对里面的一些配置进行讲解。
2.4.1 多环境配置
在核心配置文件的
environments
标签中其实是可以配置多个environment
,使用id
给每段环境起名,在environments
中使用default= 环境id
来指定使用哪儿段配置。我们一般就配置一个environment
即可。<environments default=development><environment id=development><transactionManager type=JDBC/><dataSource type=POOLED><!--数据库连接信息--><property name=driver value=jdbc.Driver/><property name=url value=jdbc:mysql:///mybatis?useSSL=false/><property name=username value=root/><property name=password value=12456/></dataSource></environment><environment id=test><transactionManager type=JDBC/><dataSource type=POOLED><!--数据库连接信息--><property name=driver value=jdbc.Driver/><property name=url value=jdbc:mysql:///mybatis?useSSL=false/><property name=username value=root/><property name=password value=12456/></dataSource></environment></environments>
2.4.2 类型别名
在映射配置文件中的
resultType
属性需要配置数据封装的类型(类的全限定名)。而每次这样写是特别麻烦的,Mybatis 提供了类型别名
(typeAliases) 可以简化这部分的书写。首先需要现在核心配置文件中配置类型别名,也就意味着给pojo包下所有的类起了别名(别名就是类名),不区分大小写。内容如下:
<typeAliases><!--name属性的值是实体类所在包--><package name=com.itheima.pojo/> </typeAliases>
通过上述的配置,我们就可以简化映射配置文件中
resultType
属性值的编写<mapper namespace=com..UserMapper><select id=selectAll resultType=user>select * from tb_user;</select> </mapper>
、Mybatis案例——环境准备
目标:
能够使用映射配置文件实现CRUD操作
能够使用注解实现CRUD操作
对数据库表中的数据进行CRUD操作。接下来我们就使用Mybatis完成品牌数据的增删改查操作。以下是我们要完成功能列表:
查询
查询所有数据
查询详情
条件查询
添加
修改
修改全部字段
修改动态字段
删除
删除一个
批量删除
环境准备
数据库表(tb_brand)及数据准备 -- 删除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 实体类。public class Brand {// id 主键private Integer id;// 品牌名称private String brandame;// 企业名称private String companyame;// 排序字段private Integer ordered;// 描述信息private String description;// 状态:0:禁用 1:启用private Integer status;//省略 setter and getter。自己写时要补全这部分代码 }
编写测试用例 测试代码需要在
test/java
目录下创建包及测试用例。项目结构如下:安装 MyBatisX 插件
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
主要功能
XML映射配置文件 和 接口方法 间相互跳转
根据接口方法生成 statement
安装方式
点击
file
,选择settings
,就能看到如下图所示界面红头绳的表示映射配置文件,蓝头绳的表示mapper接口。在mapper接口点击红头绳的小鸟图标会自动跳转到对应的映射配置文件,在映射配置文件中点击蓝头绳的小鸟图标会自动跳转到对应的mapper接口。也可以在mapper接口中定义方法,自动生成映射配置文件中的
注意:安装完毕后需要重启IDEA
插件效果
statement
,如图所示
.1、查询-查询所有&结果映射
查询所有数据
查询所有数据功能,而实现该功能我们分以下步骤进行实现:
编写接口方法:Mapper接口
参数:无
查询所有数据功能是不需要根据任何条件进行查询的,所以此方法不需要参数。
结果:List<Brand>
我们会将查询出来的每一条数据封装成一个
Brand
对象,而多条数据封装多个Brand
对象,需要将这些对象封装到List集合中返回。执行方法、测试
1、编写接口方法
在
com.
包写创建名为BrandMapper
的接口。并在该接口中定义List<Brand> selectAll()
方法。public interface BrandMapper { /*** 查询所有*/List<Brand> selectAll(); }
2、 编写SQL语句
在
reources
下创建com/itheima/mapper
目录结构,并在该目录下创建名为BrandMapper.xml
的映射配置文件<?xml version=1.0 encoding=UTF-8 ?> <!DOCTYPE mapperPUBLIC -//mybatis//DTD Mapper .0//E.dtd> <mapper namespace=com..BrandMapper><select id=selectAll resultType=brand>select *from tb_brand;</select> </mapper>
、 编写测试方法
在
MybatisTest
类中编写测试查询所有的方法@Test public void testSelectAll() throws IOException {//1. 获取SqlSessionFactoryString resource = mybatis-config.xml;InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2. 获取SqlSession对象SqlSession sqlSession = (); //. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(); //4. 执行方法List<Brand> brands = brandMapper.selectAll();println(brands); //5. 释放资源(); }
注意:现在我们感觉测试这部分代码写起来特别麻烦,我们可以先忍忍。以后我们只会写上面的第步的代码,其他的都不需要我们来完成。
执行测试方法结果如下:
从上面结果我们看到了问题,有些数据封装成功了,而有些数据并没有封装成功。为什么这样呢?
这个问题可以通过两种方式进行解决:
给字段起别名
使用resultMap定义字段和属性的映射关系
4 、起别名解决上述问题
从上面结果可以看到
brandame
和companyame
这两个属性的数据没有封装成功,查询 实体类 和 表中的字段 发现,在实体类中属性名是brandame
和companyame
,而表中的字段名为brand_name
和company_name
,如下图所示 。那么我们只需要保持这两部分的名称一致这个问题就迎刃而解。我们可以在写sql语句时给这两个字段起别名,将别名定义成和属性名一致即可。
<select id=selectAll resultType=brand>selectid, brand_name as brandame, company_name as companyame, ordered, description, statusfrom tb_brand; </select>
而上面的SQL语句中的字段列表书写麻烦,如果表中还有更多的字段,同时其他的功能也需要查询这些字段时就显得我们的代码不够精炼。Mybatis提供了
sql
片段可以提高sql的复用性。SQL片段:
将需要复用的SQL片段抽取到
sql
标签中<sql id=brand_column>id, brand_name as brandame, company_name as companyame, ordered, description, status </sql>
id属性值是唯一标识,引用时也是通过该值进行引用。
在原sql语句中进行引用
使用
include
标签引用上述的 SQL 片段,而refid
指定上述 SQL 片段的id值。<select id=selectAll resultType=brand>select<include refid=brand_column />from tb_brand; </select>
5、 使用resultMap解决上述问题
起别名 sql片段的方式可以解决上述问题,但是它也存在问题。如果还有功能只需要查询部分字段,而不是查询所有字段,那么我们就需要再定义一个 SQL 片段,这就显得不是那么灵活。
那么我们也可以使用resultMap来定义字段和属性的映射关系的方式解决上述问题。
在映射配置文件中使用resultMap定义 字段 和 属性 的映射关系
<resultMap id=brandResultMap type=brand><!--id:完成主键字段的映射column:表的列名property:实体类的属性名result:完成一般字段的映射column:表的列名property:实体类的属性名--><result column=brand_name property=brandame/><result column=company_name property=companyame/> </resultMap>
注意:在上面只需要定义 字段名 和 属性名 不一样的映射,而一样的则不需要专门定义出来。
SQL语句正常编写
<select id=selectAll resultMap=brandResultMap>select *from tb_brand; </select>
6 、小结
实体类属性名 和 数据库表列名 不一致,不能自动封装数据
==起别名:==在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样
可以定义 <sql>片段,提升复用性
==resultMap:==定义<resultMap> 完成不一致的属性名和列名的映射
而我们最终选择使用 resultMap的方式。查询映射配置文件中查询所有的 statement 书写如下:
<resultMap id=brandResultMap type=brand><!--id:完成主键字段的映射column:表的列名property:实体类的属性名result:完成一般字段的映射column:表的列名property:实体类的属性名--><result column=brand_name property=brandame/><result column=company_name property=companyame/> </resultMap> <select id=selectAll resultMap=brandResultMap>select *from tb_brand; </select>
.2、查询-查看详情
有些数据的属性比较多,在页面表格中无法全部实现,而只会显示部分,而其他属性数据的查询可以通过
查看详情
来进行查询查看详情功能实现步骤:
编写接口方法:Mapper接口
参数:id
查看详情就是查询某一行数据,所以需要根据id进行查询。而id以后是由页面传递过来。
结果:Brand
根据id查询出来的数据只要一条,而将一条数据封装成一个Brand对象即可
编写SQL语句:SQL映射文件
执行方法、进行测试
1 、编写接口方法
在
BrandMapper
接口中定义根据id查询数据的方法/*** 查看详情:根据Id查询*/ Brand selectById(int id);
2 、编写SQL语句
在
BrandMapper.xml
映射配置文件中编写statement
,使用resultMap
而不是使用resultType
<select id=selectById resultMap=brandResultMap>select *from tb_brand where id = #{id}; </select>
注意:上述SQL中的 #{id}先这样写,一会我们再详细讲解
、编写测试方法
在
test/java
下的com.
包下的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 = (); //. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(); //4. 执行方法Brand brand = brandMapper.selectById(id);println(brand); //5. 释放资源(); }
执行测试方法结果如下:
4 、参数占位符
查询到的结果很好理解就是id为1的这行数据。而这里我们需要看控制台显示的SQL语句,能看到使用?进行占位。说明我们在映射配置文件中的写的
#{id}
最终会被?进行占位。接下来我们就聊聊映射配置文件中的参数占位符。mybatis提供了两种参数占位符:
#{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是
PreparedStatement
${} :拼接SQL。底层使用的是
Statement
,会存在SQL注入问题。如下图将 映射配置文件中的 #{} 替换成 ${} 来看效果<select id=selectById resultMap=brandResultMap>select *from tb_brand where id = ${id}; </select>
重新运行查看结果如下:
==注意:==从上面两个例子可以看出,以后开发我们使用 #{} 参数占位符。
5 、parameterType使用
对于有参数的mapper接口方法,我们在映射配置文件中应该配置
ParameterType
来指定参数类型。只不过该属性都可以省略。如下图:<select id=selectById parameterType=int resultMap=brandResultMap>select *from tb_brand where id = ${id}; </select>
6 、SQL语句殊字段处理
以后肯定会在SQL语句中写一下特殊字符,比如某一个字段大于某个值,如下图
可以看出报错了,因为映射配置文件是xml类型的问题,而 > < 等这些字符在xml中有特殊含义,所以此时我们需要将这些符号进行转义,可以使用以下两种方式进行转义
转义字符
下图的
<
就是<
的转义字符。
<![CDATA[内容]]>
.、查询-条件查询
多条件查询
我们经常会遇到如上图所示的多条件查询,将多条件查询的结果展示在下方的数据列表中。而我们做这个功能需要分析最终的SQL语句应该是什么样,思考两个问题
条件表达式
如何连接
条件字段
企业名称
和品牌名称
需要进行模糊查询,所以条件应该是:简单的分析后,我们来看功能实现的步骤:
编写接口方法
参数:所有查询条件
结果:List<Brand>
在映射配置文件中编写SQL语句
编写测试方法并执行
1、 编写接口方法
在
BrandMapper
接口中定义多条件查询的方法。而该功能有三个参数,我们就需要考虑定义接口时,参数应该如何定义。Mybatis针对多参数有多种实现
使用
@Param(参数名称)
标记每一个参数,在映射配置文件中就需要使用#{参数名称}
进行占位List<Brand> selectByCondition(@Param(status) int status, @Param(companyame) String companyame,@Param(brandame) String brandame);
将多个参数封装成一个 实体对象 ,将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用
#{内容}
时,里面的内容必须和实体类属性名保持一致。List<Brand> selectByCondition(Brand brand);
将多个参数封装到map集合中,将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用
#{内容}
时,里面的内容必须和map集合中键的名称一致。List<Brand> selectByCondition(Map map);
2 、编写SQL语句
在
BrandMapper.xml
映射配置文件中编写statement
,使用resultMap
而不是使用resultType
<select id=selectByCondition resultMap=brandResultMap>select *from tb_brandwhere status = #{status}and company_name like #{companyame}and brand_name like #{brandame} </select>
、 编写测试方法
在
test/java
下的com.
包下的MybatisTest类中
定义测试方法@Test public void testSelectByCondition() throws IOException {//接收参数int status = 1;String companyame = 华为;String brandame = 华为; // 处理参数companyame = % companyame %;brandame = % brandame %; //1. 获取SqlSessionFactoryString resource = mybatis-config.xml;InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = ();//. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper(); //4. 执行方法//方式一 :接口方法参数使用 @Param 方式调用的方法//List<Brand> brands = brandMapper.selectByCondition(status, companyame, brandame);//方式二 :接口方法参数是 实体类对象 方式调用的方法//封装对象/* Brand brand = new Brand();brand.setStatus(status);brand.setCompanyame(companyame);brand.setBrandame(brandame);*///List<Brand> brands = brandMapper.selectByCondition(brand);//方式三 :接口方法参数是 map集合对象 方式调用的方法Map map = new HashMap();map.put(status , status);map.put(companyame, companyame);map.put(brandame , brandame);List<Brand> brands = brandMapper.selectByCondition(map);println(brands); //5. 释放资源(); }
.4、查询-动态条件查询
动态SQL
上述功能实现存在很大的问题。用户在输入条件时,肯定不会所有的条件都填写,这个时候我们的SQL语句就不能那样写的
例如用户只输入 当前状态 时,SQL语句就是
select * from tb_brand where status = #{status}
而用户如果只输入企业名称时,SQL语句就是
select * from tb_brand where company_name like #{companame}
而用户如果输入了
当前状态
和企业名称
时,SQL语句又不一样select * from tb_brand where status = #{status} and company_name like #{companame}
针对上述的需要,Mybatis对动态SQL有很强大的支撑:
if
choose (when, otherwise)
trim (where, set)
foreach
我们先学习 if 标签和 where 标签:
if 标签:条件判断
test 属性:逻辑表达式
<select id=selectByCondition resultMap=brandResultMap>select *from tb_brandwhere<if test=status != null>and status = #{status}</if><if test=companyame != null and companyame != >and company_name like #{companyame}</if><if test=brandame != null and brandame != >and brand_name like #{brandame}</if> </select>
如上的这种SQL语句就会根据传递的参数值进行动态的拼接。如果此时status和companyame有值那么就会值拼接这两个条件。
执行结果如下:
但是它也存在问题,如果此时给的参数值是
Map map = new HashMap(); // map.put(status , status); map.put(companyame, companyame); map.put(brandame , brandame);
拼接的SQL语句就变成了
select * from tb_brand where and company_name like ? and brand_name like ?
而上面的语句中 where 关键后直接跟 and 关键字,这就是一条错误的SQL语句。这个就可以使用 where 标签解决,
where 标签
作用:
替换where关键字
会动态的去掉第一个条件前的 and
如果所有的参数没有值则不加where关键字
<select id=selectByCondition resultMap=brandResultMap>select *from tb_brand<where><if test=status != null>and status = #{status}</if><if test=companyame != null and companyame != >and company_name like #{companyame}</if><if test=brandame != null and brandame != >and brand_name like #{brandame}</if></where> </select>
注意:需要给每个条件前都加上 and 关键字。
单个条件(动态SQL)
如上图所示,在查询时只能选择
品牌名称
、当前状态
、企业名称
这三个条件中的一个,但是用户到底选择哪儿一个,我们并不能确定。这种就属于单个条件的动态SQL语句。这种需求需要使用到
choose(when,otherwise)标签
实现, 而choose
标签类似于Java 中的switch语句。通过一个案例来使用这些标签
1、编写接口方法
在
BrandMapper
接口中定义单条件查询的方法。/*** 单条件动态查询* @param brand* @return*/ List<Brand> selectByConditionSingle(Brand brand);
2 、编写SQL语句
在
BrandMapper.xml
映射配置文件中编写statement
,使用resultMap
而不是使用resultType
<select id=selectByConditionSingle resultMap=brandResultMap>select *from tb_brand<where><choose><!--相当于switch--><when test=status != null><!--相当于case-->status = #{status}</when><when test=companyame != null and companyame != ><!--相当于case-->company_name like #{companyame}</when><when test=brandame != null and brandame != ><!--相当于case-->brand_name like #{brandame}</when></choose></where> </select>
、 编写测试方法
在
test/java
下的com.
包下的MybatisTest类中
定义测试方法@Test public void testSelectByConditionSingle() throws IOException {//接收参数int status = 1;String companyame = 华为;String brandame = 华为; // 处理参数companyame = % companyame %;brandame = % brandame %; //封装对象Brand brand = new Brand();//brand.setStatus(status);brand.setCompanyame(companyame);//brand.setBrandame(brandame); //1. 获取SqlSessionFactoryString resource = mybatis-config.xml;InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//2. 获取SqlSession对象SqlSession sqlSession = ();//. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper();//4. 执行方法List<Brand> brands = brandMapper.selectByConditionSingle(brand);println(brands); //5. 释放资源(); }
执行测试方法结果如下:
.5、添加&修改功能
添加数据
如上图是我们平时在添加数据时展示的页面,而我们在该页面输入想要的数据后添加
提交
按钮,就会将这些数据添加到数据库中。接下来我们就来实现添加数据的操作。
编写接口方法
参数:除了id之外的所有的数据。id对应的是表中主键值,而主键我们是 ==自动增长== 生成的。
编写SQL语句
编写测试方法并执行
明确了该功能实现的步骤后,接下来我们进行具体的操作。
1 、编写接口方法
在
BrandMapper
接口中定义添加方法。/*** 添加*/ void add(Brand brand);
2 、编写SQL语句
在
BrandMapper.xml
映射配置文件中编写添加数据的statement
<insert id=add>insert into tb_brand (brand_name, company_name, ordered, description, status)values (#{brandame}, #{companyame}, #{ordered}, #{description}, #{status}); </insert>
、 编写测试方法
在
test/java
下的com.
包下的MybatisTest类中
定义测试方法@Test public void testAdd() throws IOException {//接收参数int status = 1;String companyame = 波导手机;String brandame = 波导;String description = 手机中的战斗机;int ordered = 100; //封装对象Brand brand = new Brand();brand.setStatus(status);brand.setCompanyame(companyame);brand.setBrandame(brandame);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 = ();//SqlSession sqlSession = (true); //设置自动提交事务,这种情况不需要手动提交事务了//. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper();//4. 执行方法brandMapper.add(brand);//提交事务sqlSessionmit();//5. 释放资源(); }
执行结果如下:
4 、添加-主键返回
在数据添加成功后,有时候需要获取插入数据库数据的主键(主键是自增长)。
比如:添加订单和订单项,如下图就是京东上的订单
订单数据存储在订单表中,订单项存储在订单项表中。
添加订单数据
添加订单项数据,订单项中需要设置所属订单的id
明白了什么时候
主键返回
。接下来我们简单模拟一下,在添加完数据后打印id属性值,能打印出来说明已经获取到了。我们将上面添加品牌数据的案例中映射配置文件里
statement
进行修改,如下<insert id=add useGeneratedKeys=true keyProperty=id>insert into tb_brand (brand_name, company_name, ordered, description, status)values (#{brandame}, #{companyame}, #{ordered}, #{description}, #{status}); </insert>
在 insert 标签上添加如下属性:
useGeneratedKeys:是够获取自动增长的主键值。true表示获取
keyProperty :指定将获取到的主键值封装到哪儿个属性里
修改
如图所示是修改页面,用户在该页面书写需要修改的数据,点击
提交
按钮,就会将数据库中对应的数据进行修改。注意一点,如果哪儿个输入框没有输入内容,我们是将表中数据对应字段值替换为空白还是保留字段之前的值?答案肯定是保留之前的数据。接下来我们就具体来实现
1、 编写接口方法
在
BrandMapper
接口中定义修改方法。/*** 修改*/ void update(Brand brand);
上述方法参数 Brand 就是封装了需要修改的数据,而id肯定是有数据的,这也是和添加方法的区别。
2、 编写SQL语句
在
BrandMapper.xml
映射配置文件中编写修改数据的statement
。<update id=update>update tb_brand<set><if test=brandame != null and brandame != >brand_name = #{brandame},</if><if test=companyame != null and companyame != >company_name = #{companyame},</if><if test=ordered != null>ordered = #{ordered},</if><if test=description != null and description != >description = #{description},</if><if test=status != null>status = #{status}</if></set>where id = #{id}; </update>
set 标签可以用于动态包含需要更新的列,忽略其它不更新的列。
、 编写测试方法
在
test/java
下的com.
包下的MybatisTest类中
定义测试方法@Test public void testUpdate() throws IOException {//接收参数int status = 0;String companyame = 波导手机;String brandame = 波导;String description = 波导手机,手机中的战斗机;int ordered = 200;int id = 6; //封装对象Brand brand = new Brand();brand.setStatus(status);// brand.setCompanyame(companyame);// brand.setBrandame(brandame);// 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 = ();//SqlSession sqlSession = (true);//. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper();//4. 执行方法int count = brandMapper.update(brand);println(count);//提交事务sqlSessionmit();//5. 释放资源(); }
执行测试方法结果如下:
从结果中SQL语句可以看出,只修改了
status
字段值,因为我们给的数据中只给Brand实体对象的status
属性设置值了。这就是set
标签的作用。
.6、删除功能
删除一行数据
如上图所示,每行数据后面都有一个
删除
按钮,当用户点击了该按钮,就会将改行数据删除掉。那我们就需要思考,这种删除是根据什么进行删除呢?是通过主键id删除,因为id是表中数据的唯一标识。接下来就来实现该功能。
1 、编写接口方法
在
BrandMapper
接口中定义根据id删除方法。/*** 根据id删除*/ void deleteById(int id);
2 、编写SQL语句
在
BrandMapper.xml
映射配置文件中编写删除一行数据的statement
<delete id=deleteById>delete from tb_brand where id = #{id}; </delete>
、 编写测试方法
在
test/java
下的com.
包下的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 = ();//SqlSession sqlSession = (true);//. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper();//4. 执行方法brandMapper.deleteById(id);//提交事务sqlSessionmit();//5. 释放资源(); }
运行过程只要没报错,直接到数据库查询数据是否还存在。
批量删除
如上图所示,用户可以选择多条数据,然后点击上面的
删除
按钮,就会删除数据库中对应的多行数据。1 、编写接口方法
在
BrandMapper
接口中定义删除多行数据的方法。/*** 批量删除*/ void deleteByIds(int[] ids);
参数是一个数组,数组中存储的是多条数据的id
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 id=deleteByIds>delete from tb_brand where idin<foreach collection=array item=id separator=, open=( close=)>#{id}</foreach>; </delete>
假如数组中的id数据是{1,2,},那么拼接后的sql语句就是:
delete from tb_brand where id in (1,2,);
、编写测试方法
在
test/java
下的com.
包下的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 = ();//SqlSession sqlSession = (true);//. 获取Mapper接口的代理对象BrandMapper brandMapper = sqlSession.getMapper();//4. 执行方法brandMapper.deleteByIds(ids);//提交事务sqlSessionmit();//5. 释放资源(); }
.7、Mybatis 参数传递
Mybatis 接口方法中可以接收各种各样的参数,如下:
多个参数
单个参数:单个参数又可以是如下类型
POJO 类型
Map 集合类型
Collection 集合类型
List 集合类型
Array 类型
其他类型
1、 多个参数
如下面的代码,就是接收两个参数,而接收多个参数需要使用
@Param
注解,那么为什么要加该注解呢?这个问题要弄明白就必须来研究Mybatis 底层对于这些参数是如何处理的。User select(@Param(username) String username,@Param(password) String password);
<select id=select resultType=user>select *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 id=select resultType=user>select *from tb_userwhere username=#{arg0}and password=#{arg1} </select>
或者
<select id=select resultType=user>select *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 id=select resultType=user>select *from tb_userwhere username=#{username}and password=#{param2} </select>
运行程序结果没有报错。而如果将
#{}
中的username
还是写成arg0
<select id=select resultType=user>select *from tb_userwhere username=#{arg0}and password=#{param2} </select>
运行程序则可以看到错误
Mybatis底层对于这些参数进行不同的封装处理方式 Mybatis提供了ParamameResolver类来进行参数封装
结论:以后接口参数是多个时,在每个参数上都使用
@Param
注解。这样代码的可读性更高。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类型,
参数占位符名称
叫什么都可以。尽量做到见名知意
.8、注解开发
使用注解开发会比配置文件开发更加方便。如下就是使用注解进行开发
@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语句融到了一块,使得代码的可读性大幅度降低。
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
上一篇:Dns执行流程和流量劫持
下一篇:淘宝仓库宝贝如何一键上架到店铺?
推荐阅读
留言与评论(共有 15 条评论) |
本站网友 maxi247 | 26分钟前 发表 |
conf目录 :存放Maven的配置文件 | |
本站网友 劲草 | 23分钟前 发表 |
测试环境 | |
本站网友 新思考网 | 7分钟前 发表 |
2 | |
本站网友 umax | 3分钟前 发表 |
接下来我们简单模拟一下,在添加完数据后打印id属性值,能打印出来说明已经获取到了 | |
本站网友 中国种业网 | 8分钟前 发表 |
我们的项目如果被其他的项目依赖时,也是需要坐标来引入的 | |
本站网友 常熟二手房网 | 26分钟前 发表 |
编写SQL语句 在 BrandMapper.xml 映射配置文件中编写 statement,使用 resultMap 而不是使用 resultType <select id=selectById resultMap=brandResultMap>select *from tb_brand where id = #{id}; </select> 注意:上述SQL中的 #{id}先这样写,一会我们再详细讲解 | |
本站网友 补充矿物质 | 16分钟前 发表 |
每个家庭 | |
本站网友 龙邦快递 | 16分钟前 发表 |
批量删除 如上图所示,用户可以选择多条数据,然后点击上面的 删除 按钮,就会删除数据库中对应的多行数据 | |
本站网友 网站背景图片 | 18分钟前 发表 |
这种需求需要使用到 choose(when,otherwise)标签 实现, 而 choose 标签类似于Java 中的switch语句 | |
本站网友 玉米须的副作用 | 30分钟前 发表 |
而id以后是由页面传递过来 | |
本站网友 首席信息官 | 27分钟前 发表 |
clean生命周期 pre-clean 执行一些需要在clean之前完成的工作 clean 移除所有上一次构建生成的文件 post-clean 执行一些需要在clean之后立刻完成的工作 site生命周期 pre-site 执行一些需要在生成站点文档之前完成的工作 site 生成项目的站点文档 post-site 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备 site-deploy 将生成的站点文档部署到特定的服务器上 default构建生命周期 同一套生命周期内,执行后边的命令,前面的所有命令会自动执行 | |
本站网友 商标注册流程 | 23分钟前 发表 |
接下来我们就使用Mybatis完成品牌数据的增删改查操作 | |
本站网友 浮肿 | 13分钟前 发表 |
接下来我们先对里面的一些配置进行讲解 | |
本站网友 雍景湾 | 0秒前 发表 |
在映射配置文件中使用resultMap定义 字段 和 属性 的映射关系 <resultMap id=brandResultMap type=brand><!--id:完成主键字段的映射column:表的列名property:实体类的属性名result:完成一般字段的映射column:表的列名property:实体类的属性名--><result column=brand_name property=brandame/><result column=company_name property=companyame/> </resultMap> 注意:在上面只需要定义 字段名 和 属性名 不一样的映射,而一样的则不需要专门定义出来 |