• JavaWeb基础3——Maven&MyBatis


    目录

    构建工具Maven

    概念

    作用

    Maven模型

    仓库

    Maven 坐标详解

     Maven安装配置

    Maven基本使用

    Maven常用命令

    Maven 生命周期

    IDEA使用Maven

    IDEA配置Maven环境

    IDEA 创建 Maven项目

    配置 Maven-Helper 插件

    报错解决

    依赖管理

    引入jar包

    依赖范围

    Mybatis

    Mybatis概述

    Mybatis概念

    Mybatis对比JDBC

    核心配置文件mybatis-config.xml

    configuration【根标签】

    properties【属性标签】

    settings【设置标签】

    typeAliases【类型别名】

    typeHandlers【类型处理器】

    objectFactory【对象工厂】

    plugins(插件)

    environments【数据库环境设置】

    databaseIdProvider(数据库厂商标识)

    mappers 【映射器】

    Mybatis入门案例

    步骤

    IDEA连接数据库 

    Mapper代理开发

    目的

     使用mapper实现查询

    配置文件实现增删改查

    占位符和XML字符处理

    环境准备 

    给列起别名并查询所有

    单条件查询

    多条件查询(三种传多参方法)

    多条件动态查询(动态SQL)

    单条件动态查询(动态SQL)

    添加数据

    修改全部字段

    修改动态字段

    删除一行数据

    批量删除

    Mybatis参数传递

    注解实现增删改查


    构建工具Maven

    概念

    Maven是专门用于管理和构建Java项目的工具。

    作用

    Maven是专门用于管理和构建Java项目的工具,它的主要功能有:

    • 提供了一套标准化的项目结构

    每一个开发工具(IDE)都有自己不同的项目结构,它们互相之间不通用。

    而Maven提供了一套标准化的项目结构,所有的IDE使用Maven构建的项目完全一样,所以IDE创建的Maven项目可以通用。

    • 提供了一套标准化的构建流程(编译,测试,打包,发布……)

    • 提供了一套依赖管理机制

    Maven使用标准的坐标配置来管理各种依赖, 只需要简单的配置就可以完成依赖管理:

    Maven模型

    • 项目对象模型pom (Project Object Model)

    • 依赖管理模型(Dependency)

    • 插件(Plugin)

    项目对象模型pom就是将我们自己抽象成一个对象模型,有自己专属的坐标,是唯一标识。

    项目对象模型pom通过xml格式保存的pom.xml文件。该文件用于管理:源代码、配置文件、开发者的信息和角色、问题追踪系统、组织信息、项目授权、项目的url、项目的依赖关系等等。

    如下图所示是一个Maven项目:

     依赖管理模型则是使用坐标来描述当前项目依赖哪些第三方jar包,如下图所示:

     项目管理模型和依赖管理模型结合起来,体现Maven方便的依赖管理。

    构建生命周期和插件部分用来完成 标准化构建流程

    如我们需要编译,Maven提供了一个编译插件供我们使用。我们需要打包,Maven就提供了一个打包插件提供我们使用等。  

    仓库

    Maven用坐标配置管理依赖。

    依赖jar包则其实存储在本地仓库中,项目运行时从本地仓库中拿需要的依赖jar包。

    • 本地仓库:自己计算机上的一个目录

    • 中央仓库:由Maven团队维护的全球唯一的仓库

    • 远程仓库(私服):一般由公司团队搭建的私有仓库

    当项目中使用坐标引入对应依赖jar包后,首先会查找本地仓库中是否有对应的jar包:

    • 如果有,则在项目直接引用;

    • 如果没有,则去中央仓库中下载对应的jar包到本地仓库。

    如果还可以搭建远程仓库,将来jar包的查找顺序则变为:

    本地仓库 --> 远程仓库--> 中央仓库

    Maven 坐标详解

    什么是坐标?

    • Maven 中的坐标是资源的唯一标识

    • 使用坐标来定义项目或引入项目中需要的依赖

    Maven 坐标主要组成

    • groupId:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima)

    • artifactId:定义当前Maven项目名称(通常是模块名称,例如 order-service、goods-service)

    • version:定义当前项目版本号

    如下图就是使用坐标表示一个项目:

    注意:

    • 上面所说的资源可以是插件、依赖、当前项目。

    • 我们的项目如果被其他的项目依赖时,也是需要坐标来引入的。

     Maven安装配置

    1.下载

    官方下载链接:https://maven.apache.org/download.cgi

    Binary是可执行版本,已经编译好可以直接使用。
    Source是源代码版本,需要自己编译成可执行软件才可使用。

    我们选择已经编译好的windows可执行版本进行安装:选择zip版本(linux选择tar.gz)

    2.配置环境变量:

     3.配置本地仓库

     修改 D:\apache-maven-3.8.6\conf/settings.xml 中的 为一个指定目录(例如D:\apache-maven-3.8.6\mvn_resp)作为本地仓库,用来存储jar包。

    默认使用jdk1.4,太老

    将下面代码加到

    1. <profile>
    2. <id>jdk-11id>
    3. <activation>
    4. <activeByDefault>trueactiveByDefault>
    5. <jdk>11jdk>
    6. activation>
    7. <properties>
    8. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    9. <maven.compiler.source>11maven.compiler.source>
    10. <maven.compiler.target>11maven.compiler.target>
    11. properties>
    12. profile>

    4.配置阿里云私服:

    中央仓库在国外,所以下载jar包速度可能比较慢,而阿里公司提供了一个远程仓库,里面基本也都有开源项目的jar包。

    修改 conf/settings.xml 中的 标签,为其添加如下子标签:

    1. <mirror>  
    2.    <id>alimavenid>  
    3.    <name>aliyun mavenname>  
    4.    <url>http://maven.aliyun.com/nexus/content/groups/public/url>
    5.    <mirrorOf>centralmirrorOf>          
    6. mirror>

    Maven基本使用

    Maven常用命令

    • compile :编译,生成target目录

    • clean:清理,删除target目录

    • test:测试,执行test文件下测试代码

    • package:打包,将当前项目打包成的jar包

    • install:安装,将当前项目打成jar包,并安装到本地仓库

    编译命令演示:

    命令行运行mvn compile。

    首次编译会先从阿里云(之前conf/settings.xml配置了阿里云私服)下载编译需要插件的jar包,在本地仓库(之前conf/settings.xml配置了本地仓库位置)也能看到下载好的插件。

    在项目下会生成一个 target 目录,里面保存编译后的字节码文件。

     

    清理命令演示:

    mvn clean

    执行上述命令可以看到

    • 从阿里云下载清理需要的插件jar包

    • 删除项目下的 target 目录

    Maven 生命周期

    Maven 构建项目生命周期描述的是一次构建过程经历经历了多少个事件

    Maven 对项目构建的生命周期划分为3套:

    • clean :清理工作。

    • default :核心工作,例如编译,测试,打包,安装等。

    • site : 产生报告,发布站点等。这套生命周期一般不会使用。

    同一套生命周期内,执行后边的命令,前面的所有命令会自动执行。

    默认生命周期:

    IDEA使用Maven

    IDEA配置Maven环境

    设置 IDEA 使用本地安装的 Maven,并修改配置文件路径,记得apply: 

    apply再ok。 

    IDEA 创建 Maven项目

    file-new module-选择构建Maven、jdk版本最好大于1.5:

    也可以先创建空项目,在项目内创建Maven模块。

    下面生成器Maven archetype(原型)是创建Maven web的,在下下一篇讲Tomcat时会用到

     

     

    填写模块名称,坐标信息,点击finish,创建完成  

     创建好的项目目录结构如下:

    然后在java文件夹下建包,创建类 

    导入Maven项目:open-双击项目的pom.xml文件即可

    配置 Maven-Helper 插件

    Maven-Helper可以右键Maven项目,直接run Maven和调试。

    File --> Settings--Plugins--搜索 Maven,选择第一个 Maven Helper,点击Install安装,弹出面板中点击Accept--重启

    报错解决

    打包时出现编码错误:

    彻底解决:全部编码设置成utf-8 

     单文件解决: 

     在pom.xml配置如下代码,适用于项目要在不同项目移动:

    1. <properties>
    2. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    3. <maven.compiler.encoding>UTF-8maven.compiler.encoding>
    4. <java.version>11java.version>
    5. <maven.compiler.source>11maven.compiler.source>
    6. <maven.compiler.target>11maven.compiler.target>
    7. properties>

    依赖管理

    引入jar包

    使用坐标引入jar包

    1.在项目的 pom.xml 中编写 标签

    2.在 标签中 使用 引入坐标

    3.定义坐标的 groupId,artifactId,version

    groupId:定义当前Maven项目隶属的实际项目。

    例如org.sonatype.nexus,此id前半部分org.sonatype代表此项目隶属的组织或公司,后部分代表项目的名称。

    如果此项目多模块话开发的话就子模块可以分为org.sonatype.nexus.plugins和org.sonatype.nexus.utils等。

    特别注意的是groupId不应该对应项目隶属的组织或公司,也就是说groupId不能只有org.sonatype而没有nexus。

    artifactId是构件ID,该元素定义实际项目中的一个Maven项目或者是子模块,如上面官方约定中所说,构建名称必须小写字母,没有其他的特殊字符,推荐使用“实际项目名称-模块名称”的方式定义,例如:spirng-mvn、spring-core等。

    点击刷新按钮,使坐标生效

     

    注意:

    设置自动刷新:

    File --> Settings---Build Tools---any changes

    快捷方式引入jar包

    1.在 pom.xml 中 按 alt + insert,选择 Dependency

    2.在弹出的面板中搜索对应坐标,然后双击选中对应坐标

    3.点击刷新按钮,使坐标生效

    依赖范围

    通过设置坐标的依赖范围(scope),可以设置 对应jar包的作用范围:编译环境、测试环境、运行环境。

    如下图所示给 junit 依赖通过 scope 标签指定依赖的作用范围。 那么这个依赖就只能作用在测试环境,其他环境下不能使用。

    依赖范围scope可取值:

    依赖范围编译classpath测试classpath运行classpath例子
    compileYYYlogback
    test-Y-Junit
    providedYY-servlet-api
    runtime-YYjdbc驱动
    systemYY-存储在本地的jar包

    Mybatis

    Mybatis概述

    Mybatis概念

    MyBatis中文网

    • MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发

    • MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github

    • 官网:mybatis – MyBatis 3 | 简介

    持久层:

    • 负责将数据保存到数据库的那一层代码。

      以后开发我们会将操作数据库的Java代码作为持久层。而Mybatis就是对jdbc代码进行了封装

    • JavaEE三层架构:表现层做页面展示、业务层做逻辑处理、持久层对数据持久化

    • 下图是持久层框架的使用占比。

    框架:

    • 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型

    • 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展

    Mybatis对比JDBC

    JDBC 缺点

    下面是 JDBC 代码,我们通过该代码分析都存在什么缺点:

    • 硬编码

      • 注册驱动、获取连接

        上图标1的代码有很多字符串,而这些是连接数据库的四个基本信息,以后如果要将Mysql数据库换成其他的关系型数据库的话,这四个地方都需要修改,如果放在此处就意味着要修改我们的源代码。

      • SQL语句

        上图标2的代码。如果表结构发生变化,SQL语句就要进行更改。这也不方便后期的维护。

    • 操作繁琐

      • 手动设置参数

      • 手动封装结果集

        上图标4的代码是对查询到的数据进行封装,而这部分代码是没有什么技术含量,而且特别耗费时间的。

    Mybatis 优化

    • 硬编码可以配置到配置文件

    • 操作繁琐的地方mybatis都自动完成

    如图所示

    核心配置文件mybatis-config.xml

    核心配置文件标签必须有向后顺序(相比之下,SQL映射配置文件的同级标签没有先后顺序),如下:

    configuration【根标签】

    所有子标签均需书写在当前根标签内部

    示例:

    1. configuration
    2. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    4. <configuration>
    5. <typeAliases>
    6. <package name="package1.pojo"/>
    7. typeAliases>
    8. <environments default="development">
    9. <environment id="development">
    10. <transactionManager type="JDBC"/>
    11. <dataSource type="POOLED">
    12. <property name="driver" value="com.mysql.jdbc.Driver"/>
    13. <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
    14. <property name="username" value="root"/>
    15. <property name="password" value="1234"/>
    16. dataSource>
    17. environment>
    18. environments>
    19. <mappers>
    20. <package name="package1.mapper"/>
    21. mappers>
    22. configuration>

    properties【属性标签】

    作用:将数据库配置属性从dataSource标签内部提取到外部
    属性:
    resource:设置外部属性文件类路径
    url:设置外部属性文件真实路径

    示例:

    1. <properties resource="druid.properties">properties>
    2. <environments default="development">
    3. <environment id="development">
    4. <transactionManager type="JDBC"/>
    5. <dataSource type="POOLED">
    6. <property name="driver" value="${driverClassName}"/>
    7. <property name="url" value="${url}"/>
    8. <property name="username" value="${username}"/>
    9. <property name="password" value="${password}"/>
    10. dataSource>
    11. environment>
    12. environments>

    settings【设置标签】

    作用: 是mybatis中极为重要的调整设置,他们会改变mybatis的运行时行为

    mapUnderscoreToCamelCase:开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
    默认值为false,当设置为true时开启驼峰命名
    注意:只能将a_bc与aBc自动映射,不能将a_b与aBc自动映射

    示例代码

    1. <settings>
    2.        
    3.         <setting name="mapUnderscoreToCamelCase" value="true"/>
    4. settings>

    typeAliases【类型别名】

    alias译为别名
    作用 :类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
    自定义别名

    1. <typeAliases>
    2. <typeAlias alias="Author" type="domain.blog.Author"/>
    3. <typeAlias alias="Blog" type="domain.blog.Blog"/>
    4. <typeAlias alias="Comment" type="domain.blog.Comment"/>
    5. <typeAlias alias="Post" type="domain.blog.Post"/>
    6. <typeAlias alias="Section" type="domain.blog.Section"/>
    7. <typeAlias alias="Tag" type="domain.blog.Tag"/>
    8. typeAliases>

    也可以指定一个包名进行扫描,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

    1. <typeAliases>
    2. <package name="package1.pojo"/>
    3. typeAliases>

    这样sql映射文件就能省略路径package1.pojo:

    1. mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    2. <mapper namespace="package1.mapper.UserMapper">
    3. <select id="selectAll" resultType="package1.pojo.User">
    4. select * from tb_user;
    5. select>
    6. mapper>

    typeHandlers【类型处理器】

    objectFactory【对象工厂】

    plugins(插件)

    environments【数据库环境设置】

    作用:配置数据库连接环境信息。

    • 可以配置多个environment。
    • 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。这样通过default属性切换不同的environment环境
    • 尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

    environments属性default是每个environment默认使用的环境 ID

    environment属性id是指定该 environment 元素定义的环境 ID。

    事务管理器transactionManager属性type有两种:

    JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
    MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。
    数据源dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源,type有三种:
    POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。
    UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。
    JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。

    示例:

    1. <environments default="development">
    2. <environment id="development">
    3. <transactionManager type="JDBC"/>
    4. <dataSource type="POOLED">
    5. <property name="driver" value="com.mysql.jdbc.Driver"/>
    6. <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
    7. <property name="username" value="root"/>
    8. <property name="password" value="1234"/>
    9. dataSource>
    10. environment>
    11. environments>

    databaseIdProvider(数据库厂商标识)

    mappers 【映射器】


    作用:加载映射文件
     

    1. <mappers>
    2. <mapper resource="UserMapper.xml"/>
    3. mappers>

    Mybatis入门案例

    步骤

    需求:查询user表中所有的数据

    1.创建user表,添加数据

    1. create database mybatis;
    2. use mybatis;
    3. drop table if exists tb_user;
    4. create table tb_user(
    5. id int primary key auto_increment,
    6. username varchar(20),
    7. password varchar(20),
    8. gender char(1),
    9. addr varchar(30)
    10. );
    11. INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
    12. INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
    13. INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');

    2.创建模块,导入坐标

    在创建好的模块中的 pom.xml 配置文件中添加依赖的坐标:

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.mybatisgroupId>
    4. <artifactId>mybatisartifactId>
    5. <version>3.5.5version>
    6. dependency>
    7. <dependency>
    8. <groupId>mysqlgroupId>
    9. <artifactId>mysql-connector-javaartifactId>
    10. <version>5.1.46version>
    11. dependency>
    12. <dependency>
    13. <groupId>junitgroupId>
    14. <artifactId>junitartifactId>
    15. <version>4.13version>
    16. <scope>testscope>
    17. dependency>
    18. <dependency>
    19. <groupId>org.slf4jgroupId>
    20. <artifactId>slf4j-apiartifactId>
    21. <version>1.7.20version>
    22. dependency>
    23. <dependency>
    24. <groupId>ch.qos.logbackgroupId>
    25. <artifactId>logback-classicartifactId>
    26. <version>1.2.3version>
    27. dependency>
    28. <dependency>
    29. <groupId>ch.qos.logbackgroupId>
    30. <artifactId>logback-coreartifactId>
    31. <version>1.2.3version>
    32. dependency>
    33. dependencies>

    注意:需要在项目的 resources 目录下创建logback的配置文件

    1. <configuration>
    2. <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
    3. <encoder>
    4. <pattern>[%level] %cyan([%thread]) %boldGreen(%logger{15}) - %msg %npattern>
    5. encoder>
    6. appender>
    7. <logger name="package1" level="DEBUG" additivity="false">
    8. <appender-ref ref="Console"/>
    9. logger>
    10. <root level="DEBUG">
    11. <appender-ref ref="Console"/>
    12. root>
    13. configuration>

    slf4j,simple logging facade for java的缩写,翻译为java的简单日志外观。slf4j是一个开源项目,它提供我们一个一致的API来使用不同的日志框架,比如: java.util.logging,logback,log4j等。slf4j使用户可以在运行时嵌入他们想使用的日志框架。从名字中可以看出,它其实使用的是facade设计模式来实现的。 

    Logback是SpringBoot内置的日志处理框架,你会发现spring-boot-starter其中包含了spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架 logback。官方文档:http://logback.qos.ch/manual/

    3.编写 MyBatis 核心配置文件 -- > 替换连接信息 解决硬编码问题

    在模块下的 resources 目录下创建mybatis的配置文件 mybatis-config.xml,内容如下:

    1. configuration
    2. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    4. <configuration>
    5. <typeAliases>
    6. <package name="package1.pojo"/>
    7. typeAliases>
    8. <environments default="development">
    9. <environment id="development">
    10. <transactionManager type="JDBC"/>
    11. <dataSource type="POOLED">
    12. <property name="driver" value="com.mysql.jdbc.Driver"/>
    13. <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
    14. <property name="username" value="root"/>
    15. <property name="password" value="1234"/>
    16. dataSource>
    17. environment>
    18. environments>
    19. <mappers>
    20. <mapper resource="UserMapper.xml"/>
    21. mappers>
    22. configuration>

    4.编写 SQL 映射文件 --> 统一管理sql语句,解决硬编码问题

    在模块的 resources 目录下创建映射配置文件 UserMapper.xml,内容如下:

    1. mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    2. <mapper namespace="test">
    3. <select id="selectAll" resultType="package1.pojo.User">
    4. select * from tb_user;
    5. select>
    6. mapper>

    另外,可通过resultMap实现对数据库列名起别名,以解决数据库列名和User类属性命名法不对应问题(数据库标识符不区分大小写,采用下划线命名法,java标识符常用驼峰命名法):

    1. <resultMap id="userResultMap" type="user">
    2. <result column="username" property="userName"/>
    3. <result column="password" property="passWord"/>
    4. resultMap>
    5. <select id="selectAll" resultMap="userResultMap">
    6. select * from tb_user;
    7. select>

    根标签【mapper】
    作用:所用子标签均需书写在mapper内部
    namespace与接口全路径类名【类的全限定名】一致

     八大子标签:

    insert:定义增加SQL语句
    delete:定义删除SQL语句
    update:定义修改语句
    select:定义查询SQL语句
    sql:定义SQL语句块
    resultMap:定义结果集映射【resultType解决不了时,使用resultMap】
    cache:定义缓冲类
    cache-ref:定义引用缓存

    5.在package1.pojo包下创建 User类

    POJO(Plain Old Java Objects)译为,简单的Java对象,其实就是没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的,没有遵从特定的Java对象模型、约定或框架(如EJB)的不受任何限制的java对象

    1. package package1.pojo;
    2. //pojo译为,简单的Java对象.其实就是没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的,没有遵从特定的Java对象模型、约定或框架(如EJB)的不受任何限制的java对象。
    3. public class User {
    4. private int id;
    5. private String username;
    6. private String password;
    7. private String gender;
    8. private String addr;
    9. //省略了 setter 和 getter
    10. @Override
    11. public String toString() {
    12. return "User{" +
    13. "id=" + id +
    14. ", username='" + username + '\'' +
    15. ", password='" + password + '\'' +
    16. ", gender='" + gender + '\'' +
    17. ", addr='" + addr + '\'' +
    18. '}';
    19. }
    20. }

    6.在package1包下编写 MybatisDemo 测试类

    步骤:

    1. 加载mybatis的核心配置文件,获取 SqlSessionFactory

    session译为“会话”,factory译为“工厂”。

    2. 获取SqlSession对象,用它来执行sql
    3. 执行sql
    4. 释放资源

    示例:

    不用记,整合Spring后就只剩mapper优化后的执行方法

    List users=userMapper.selectAll();

    1. package package1;
    2. import org.apache.ibatis.io.Resources;
    3. import org.apache.ibatis.session.SqlSession;
    4. import org.apache.ibatis.session.SqlSessionFactory;
    5. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    6. import package1.pojo.User;
    7. import java.io.IOException;
    8. import java.io.InputStream;
    9. import java.util.List;
    10. public class Demo {
    11. public static void main(String[] args) throws IOException {
    12. //1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
    13. String resource = "mybatis-config.xml";
    14. InputStream inputStream = Resources.getResourceAsStream(resource);
    15. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    16. //2. 获取SqlSession对象,用它来执行sql
    17. SqlSession sqlSession = sqlSessionFactory.openSession();
    18. //3. 执行sql
    19. //参数是一个字符串,该字符串必须是映射配置文件的namespace.id
    20. List users = sqlSession.selectList("test.selectAll");
    21. System.out.println(users);
    22. //4. 释放资源
    23. sqlSession.close();
    24. }
    25. }

    对比一下jdbc:

    1. import java.sql.Connection;
    2. import java.sql.DriverManager;
    3. import java.sql.Statement;
    4. /**
    5. * 简单版
    6. */
    7. public class Demo {
    8. public static void main(String[] args) throws Exception {
    9. //1. 注册驱动
    10. //Class.forName("com.mysql.jdbc.Driver");//通过反射获取Driver实现类对象,从而加载驱动,注册驱动语句DriverManager.registerDriver(driver)在Driver的静态代码块里做过了。
    11. //此句仅在mysql可省略,其他数据库不能省略
    12. //2. 获取连接
    13. String url = "jdbc:mysql://127.0.0.1:3306/db1?useSSL=false";
    14. String username = "root";
    15. String password = "1234";
    16. Connection conn = DriverManager.getConnection(url, username, password);
    17. //3. 定义sql
    18. String sql = "update student set age = 80 where name='xiaohua'";
    19. //4. 获取执行sql的对象 Statement
    20. Statement stmt = conn.createStatement();
    21. //5. 执行sql
    22. int count = stmt.executeUpdate(sql);//受影响的行数
    23. //6. 处理结果
    24. System.out.println(count);
    25. //7. 释放资源
    26. stmt.close();
    27. conn.close();
    28. }
    29. }

    IDEA连接数据库 

    解决SQL映射文件的警告提示:

    在入门案例映射配置文件中存在报红的情况。问题如下:

    • 产生的原因:Idea和数据库没有建立连接,不识别表信息。但是大家一定要记住,它并不影响程序的执行。

    • 解决方式:在Idea中配置MySQL数据库连接。

    IDEA中配置MySQL数据库连接

    • 点击IDEA右边框的 Database ,在展开的界面点击 + 选择 Data Source ,再选择 MySQL

    • 在弹出的界面进行基本信息的填写

    • 点击完成后就能看到数据库编译器界面

    • 而此界面就和 navicat 工具一样可以进行数据库的操作。也可以编写SQL语句

    另外,如果发现写表明时候没有提示:

    打开File的settings,把SQL Dialects选项的右边那个None改为你的默认数据库,我这边之前默认的是Generic SQL,然后我把它改回了我使用的mysql,之后就会有提示了。

    Mapper代理开发

    目的

    Mapper 代理方式的目的:

    • 解决原生方式中的硬编码

    • 简化后期执行SQL

     使用mapper实现查询

    1.定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下。如下图放就可以,因为编译Maven后java和resources下的目录和文件都在同一个根目录下。

    注意:在resources下建多层文件夹要用斜杠,例如aa/bb,不能aa.bb。如果直接建aa.bb,则只建了一个名为aa.bb的文件夹,而不是两个。

    2.设置SQL映射文件的namespace属性为Mapper接口全限定名:

    1. mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    2. <mapper namespace="package1.mapper.UserMapper">
    3. <select id="selectAll" resultType="package1.pojo.User">
    4. select * from tb_user;
    5. select>
    6. mapper>

    3.在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致

     4.Mapper代理开发

    1. package package1;
    2. import org.apache.ibatis.io.Resources;
    3. import org.apache.ibatis.session.SqlSession;
    4. import org.apache.ibatis.session.SqlSessionFactory;
    5. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    6. import package1.mapper.UserMapper;
    7. import package1.pojo.User;
    8. import java.io.IOException;
    9. import java.io.InputStream;
    10. import java.util.List;
    11. public class Demo {
    12. public static void main(String[] args) throws IOException {
    13. //1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
    14. String resource = "mybatis-config.xml";
    15. InputStream inputStream = Resources.getResourceAsStream(resource);
    16. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    17. //2. 获取SqlSession对象,用它来执行sql
    18. SqlSession sqlSession = sqlSessionFactory.openSession();
    19. //3. 执行sql
    20. //参数是一个字符串,该字符串必须是映射配置文件的namespace.id
    21. // List users = sqlSession.selectList("test.selectAll");
    22. //3.1获取UserMapper接口的代理对象
    23. UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    24. //3.2调用sql方法
    25. List users = userMapper.selectAll();
    26. System.out.println(users);
    27. //4. 释放资源
    28. sqlSession.close();
    29. }
    30. }

    注意:如果Mapper接口名称和SQL映射文件名称相同,并在同一目录下,则可以使用在核心配置文件mybatis-config.xml中用包扫描的方式简化SQL映射文件的加载。示例:

    1. <mappers>
    2. <mapper resource="package1/mapper/UserMapper.xml"/>
    3. mappers>

     简化成:

    1. <mappers>
    2. <package name="package1.mapper"/>
    3. mappers>

    配置文件实现增删改查

    占位符和XML字符处理

    安装MybatisX插件:

    Setting--Plugins--MybatisX

    作用是通过小鸟图标,方便mapper接口和mapper配置文件之间代码的统一。

    参数占位符:

    参数占位符里的内容为传入的参数名,或者参数的成员变量名,或map的键名。

    mybatis提供了两种参数占位符:

    • #{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。底层使用的是 PreparedStatement

    • ${} :拼接SQL。底层使用的是 Statement,会存在SQL注入问题。  

     示例:

    1. <select id="selectById" resultMap="userResultMap">
    2. select * from tb_user where id=#{id};
    3. select>

     特殊字符处理:

    1.转义字符

    XML中,需要转义的字符有: 
      (1)&   & 
      (2)<   < 
      (3)>   > 
      (4)"   " 
      (5)'   ' 

    2.CDATA区

    1. <select id="selectById" resultMap="userResultMap">
    2. select * from tb_user where id
    3. >
    4. ]]> #{id};
    5. select>

    环境准备 

    • 数据库表(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 brandName;
          // 企业名称
          private String companyName;
          // 排序字段
          private Integer ordered;
          // 描述信息
          private String description;
          // 状态:0:禁用  1:启用
          private Integer status;
          
          //省略 setter and getter。自己写时要补全这部分代码
      }
    • 编写测试用例

      测试代码需要在 test/java 目录下创建包及测试用例。项目结构如下:

    给列起别名并查询所有

    SQL语句下划线命名法的列名和java实体类驼峰命名法的成员变量不同,会导致数据库给成员变量无法赋值的问题。通过resultMap标签给数据库列名起别名,可以解决这个问题。

    接口UserMapper.java定义抽象方法:

    List selectAll();

    UserMapper.xml

    1. mapper
    2. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    4. <mapper namespace="com.itheima.mapper.BrandMapper">
    5. <resultMap id="brandResultMap" type="brand">
    6. <result column="brand_name" property="brandName"/>
    7. <result column="company_name" property="companyName"/>
    8. resultMap>
    9. <select id="selectAll" resultMap="brandResultMap">
    10. select *
    11. from tb_brand;
    12. select>
    13. mapper>

    sql映射配置文件查询成功后通过测试类List brands = brandMapper.selectAll();获得所有对象组成的List列表。

    单条件查询

    UserMapper.java 

    User selectById(int id);

    UserMapper.xml

    1. <select id="selectById" resultMap="userResultMap" >
    2. select * from tb_user where id=#{id};
    3. select>

    多条件查询(三种传多参方法)

    BrandMapper.java

    三种传参方法:

    ①散装参数:使用 @Param("参数名称") 标记每一个参数,在映射配置文件中就需要使用 #{参数名称} 进行占位

    1. //BrandMapper.java
    2. List selectByCondition(@Param("status") int status, @Param("companyName") String companyName,@Param("brandName") String brandName);

    1. <select id="selectByCondition" resultMap="brandResultMap">
    2. select *
    3. from tb_brand
    4. where status = #{status}
    5. and company_name like #{companyName}
    6. and brand_name like #{brandName}
    7. select>
    1. //Demo.java
    2. List brands = brandMapper.selectByCondition(status, companyName, brandName);

    ②实体类封装参数:将多个参数封装成一个 实体对象 ,将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和实体类属性名保持一致

    1. //BrandMapper.java
    2. List selectByCondition(Brand brand);
    1. <select id="selectByCondition" resultMap="brandResultMap">
    2. select *
    3. from tb_brand
    4. where status = #{status}
    5. and company_name like #{companyName}
    6. and brand_name like #{brandName}
    7. select>

    1. //Demo.java
    2. Brand brand = new Brand();
    3. brand.setStatus(status);
    4. brand.setCompanyName(companyName);
    5. brand.setBrandName(brandName);

    ③map集合:将多个参数封装到map集合中,将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和map集合中键的名称一致

    1. //BrandMapper.java
    2. ​​​​​​​List selectByCondition(Map map);
    1. <select id="selectByCondition" resultMap="brandResultMap">
    2. select *
    3. from tb_brand
    4. where status = #{status}
    5. and company_name like #{companyName}
    6. and brand_name like #{brandName}
    7. select>

    1. //Demo.java
    2. Map map = new HashMap();
    3. map.put("status" , status);
    4. map.put("companyName", companyName);
    5. map.put("brandName" , brandName);
    6. List brands = brandMapper.selectByCondition(map);
    7. System.out.println(brands);

    BrandMapper.xml都是一样的  

    1. <select id="selectByCondition" resultMap="brandResultMap">
    2. select *
    3. from tb_brand
    4. where status = #{status}
    5. and company_name like #{companyName}
    6. and brand_name like #{brandName}
    7. select>

    测试类:

    1. @Test
    2. public void Demo() throws IOException {
    3. //接收参数
    4. int status = 1;
    5. String companyName = "华为";
    6. String brandName = "华为";
    7. // 处理参数
    8. companyName = "%" + companyName + "%";
    9. brandName = "%" + brandName + "%";
    10. //1. 获取SqlSessionFactory
    11. String resource = "mybatis-config.xml";
    12. InputStream inputStream = Resources.getResourceAsStream(resource);
    13. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    14. //2. 获取SqlSession对象
    15. SqlSession sqlSession = sqlSessionFactory.openSession();
    16. //3. 获取Mapper接口的代理对象
    17. BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    18. //4. 执行方法
    19. //方式一 :接口方法参数使用 @Param 方式调用的方法
    20. //List brands = brandMapper.selectByCondition(status, companyName, brandName);
    21. //方式二 :接口方法参数是 实体类对象 方式调用的方法
    22. //封装对象
    23. /* Brand brand = new Brand();
    24. brand.setStatus(status);
    25. brand.setCompanyName(companyName);
    26. brand.setBrandName(brandName);*/
    27. //List brands = brandMapper.selectByCondition(brand);
    28. //方式三 :接口方法参数是 map集合对象 方式调用的方法
    29. Map map = new HashMap();
    30. map.put("status" , status);
    31. map.put("companyName", companyName);
    32. map.put("brandName" , brandName);
    33. List brands = brandMapper.selectByCondition(map);
    34. System.out.println(brands);
    35. //5. 释放资源
    36. sqlSession.close();
    37. }

    上述功能实现存在很大的问题。用户在输入条件时,肯定不会所有的条件都填写,这个时候我们的SQL语句就不能那样写,要使用动态SQL。 

    多条件动态查询(动态SQL)

    动态SQL:SQL语句随着用户的输入或外部条件的变化而变化,称为动态SQL。

    Mybatis关于动态SQL的标签

    • if

    • choose (when, otherwise)

    • trim (where, set)

    • foreach

    if标签的test 属性:逻辑表达式

    为了防止出现SQL语句where 后直接跟and的情况,给所有条件加了and,并且where后跟了1=1.

    1. <select id="selectByCondition" resultMap="brandResultMap">
    2. select *
    3. from tb_brand
    4. where 1=1
    5. <if test="status != null">
    6. and status = #{status}
    7. if>
    8. <if test="companyName != null and companyName != '' ">
    9. and company_name like #{companyName}
    10. if>
    11. <if test="brandName != null and brandName != '' ">
    12. and brand_name like #{brandName}
    13. if>
    14. select>

    where 标签作用:

    • 替换where关键字

    • 会动态的去掉第一个条件前的 and

    • 如果所有的参数没有值则不加where关键字

    ​​​​​​​示例:

    1. <select id="selectByCondition" resultMap="brandResultMap">
    2. select *
    3. from tb_brand
    4. <where>
    5. <if test="status != null">
    6. and status = #{status}
    7. if>
    8. <if test="companyName != null and companyName != '' ">
    9. and company_name like #{companyName}
    10. if>
    11. <if test="brandName != null and brandName != '' ">
    12. and brand_name like #{brandName}
    13. if>
    14. where>
    15. select>

    单条件动态查询(动态SQL)

    先选择,再输入查询。

    choose(when,otherwise)标签类似于Java 中的switch语句。  

    代码:

    1. <select id="selectByConditionSingle" resultMap="brandResultMap">
    2. select *
    3. from tb_brand
    4. <where>
    5. <choose>
    6. <when test="status != null">
    7. status = #{status}
    8. when>
    9. <when test="companyName != null and companyName != '' ">
    10. company_name like #{companyName}
    11. when>
    12. <when test="brandName != null and brandName != ''">
    13. brand_name like #{brandName}
    14. when>
    15. choose>
    16. where>
    17. select>
    1. //BrandMapper.java
    2. List selectByConditionSingle(Brand brand);
    1. //Demo.java
    2. @Test
    3. public void testSelectByConditionSingle() throws IOException {
    4. //接收参数
    5. int status = 1;
    6. String companyName = "华为";
    7. String brandName = "华为";
    8. // 处理参数
    9. companyName = "%" + companyName + "%";
    10. brandName = "%" + brandName + "%";
    11. //封装对象
    12. Brand brand = new Brand();
    13. //brand.setStatus(status);
    14. brand.setCompanyName(companyName);
    15. //brand.setBrandName(brandName);
    16. //1. 获取SqlSessionFactory
    17. String resource = "mybatis-config.xml";
    18. InputStream inputStream = Resources.getResourceAsStream(resource);
    19. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    20. //2. 获取SqlSession对象
    21. SqlSession sqlSession = sqlSessionFactory.openSession();
    22. //3. 获取Mapper接口的代理对象
    23. BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    24. //4. 执行方法
    25. List brands = brandMapper.selectByConditionSingle(brand);
    26. System.out.println(brands);
    27. //5. 释放资源
    28. sqlSession.close();
    29. }

    添加数据

    1. //BrandMapper.java
    2. /**
    3. * 添加,如果返回值为int,则返回改变的行数,也可void,通过异常了解添加成功或失败
    4. */
    5. int add(Brand brand);

    1. <insert id="add">
    2. insert into tb_brand (brand_name, company_name, ordered, description, status)
    3. values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
    4. insert>
    1. //测试类
    2. @Test
    3. public void testAdd() throws IOException {
    4. //接收参数
    5. int status = 1;
    6. String companyName = "波导手机";
    7. String brandName = "波导";
    8. String description = "手机中的战斗机";
    9. int ordered = 100;
    10. //封装对象
    11. Brand brand = new Brand();
    12. brand.setStatus(status);
    13. brand.setCompanyName(companyName);
    14. brand.setBrandName(brandName);
    15. brand.setDescription(description);
    16. brand.setOrdered(ordered);
    17. //1. 获取SqlSessionFactory
    18. String resource = "mybatis-config.xml";
    19. InputStream inputStream = Resources.getResourceAsStream(resource);
    20. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    21. //2. 获取SqlSession对象
    22. SqlSession sqlSession = sqlSessionFactory.openSession();
    23. //SqlSession sqlSession = sqlSessionFactory.openSession(true); //设置自动提交事务,这种情况不需要手动提交事务了
    24. //3. 获取Mapper接口的代理对象
    25. BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    26. //4. 执行方法
    27. System.out.println(brandMapper.add(brand));
    28. //要手动提交,不然会回滚事务。如果前面sqlSessionFactory.openSession(true),就不用再提交事务了
    29. sqlSession.commit();
    30. //5. 释放资源
    31. sqlSession.close();
    32. }

    Mybatis事务:

     返回主键

    在 insert 标签上添加如下属性:

    • useGeneratedKeys:是够获取自动增长的主键值。true表示获取

    • keyProperty :指定将获取到的主键值封装到哪儿个属性里  

    1. <insert id="add" useGeneratedKeys="true" keyProperty="id">
    2. insert into tb_brand (brand_name, company_name, ordered, description, status)
    3. values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
    4. insert>

    1. brandMapper.add(brand);
    2. System.out.println(brand.getId());

    修改全部字段

    获取到修改后的数据和id,修改此id对应的一行数据。

    BrandMapper 接口

    1. /**
    2. * 修改
    3. */
    4. void update(Brand brand);

    BrandMapper.xml

    1. <update id="update">
    2. update tb_brand
    3. <set>
    4. <if test="brandName != null and brandName != ''">
    5. brand_name = #{brandName},
    6. if>
    7. <if test="companyName != null and companyName != ''">
    8. company_name = #{companyName},
    9. if>
    10. <if test="ordered != null">
    11. ordered = #{ordered},
    12. if>
    13. <if test="description != null and description != ''">
    14. description = #{description},
    15. if>
    16. <if test="status != null">
    17. status = #{status}
    18. if>
    19. set>
    20. where id = #{id};
    21. update>

    MybatisTest类

    1. @Test
    2. public void testUpdate() throws IOException {
    3. //接收参数
    4. int status = 0;
    5. String companyName = "波导手机";
    6. String brandName = "波导";
    7. String description = "波导手机,手机中的战斗机";
    8. int ordered = 200;
    9. int id = 6;
    10. //封装对象
    11. Brand brand = new Brand();
    12. brand.setStatus(status);
    13. // brand.setCompanyName(companyName);
    14. // brand.setBrandName(brandName);
    15. // brand.setDescription(description);
    16. // brand.setOrdered(ordered);
    17. brand.setId(id);
    18. //1. 获取SqlSessionFactory
    19. String resource = "mybatis-config.xml";
    20. InputStream inputStream = Resources.getResourceAsStream(resource);
    21. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    22. //2. 获取SqlSession对象
    23. SqlSession sqlSession = sqlSessionFactory.openSession();
    24. //SqlSession sqlSession = sqlSessionFactory.openSession(true);
    25. //3. 获取Mapper接口的代理对象
    26. BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    27. //4. 执行方法
    28. int count = brandMapper.update(brand);
    29. System.out.println(count);
    30. //提交事务
    31. sqlSession.commit();
    32. //5. 释放资源
    33. sqlSession.close();
    34. }

    修改动态字段

    在修改界面用户可能只修改部分属性, 所以加条件判断每个属性修改框用户有没有填写,用防止更新语句最后一行有逗号。 

    删除一行数据

    BrandMapper 接口

    1. /**
    2. * 根据id删除
    3. */
    4. void deleteById(int id);

    BrandMapper.xml

    1. <delete id="deleteById">
    2. delete from tb_brand where id = #{id};
    3. delete>

    MybatisTest类

    1. @Test
    2. public void testDeleteById() throws IOException {
    3. //接收参数
    4. int id = 6;
    5. //1. 获取SqlSessionFactory
    6. String resource = "mybatis-config.xml";
    7. InputStream inputStream = Resources.getResourceAsStream(resource);
    8. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    9. //2. 获取SqlSession对象
    10. SqlSession sqlSession = sqlSessionFactory.openSession();
    11. //SqlSession sqlSession = sqlSessionFactory.openSession(true);
    12. //3. 获取Mapper接口的代理对象
    13. BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    14. //4. 执行方法
    15. brandMapper.deleteById(id);
    16. //提交事务
    17. sqlSession.commit();
    18. //5. 释放资源
    19. sqlSession.close();
    20. }

    批量删除

    编写SQL时需要遍历数组来拼接SQL语句。Mybatis 提供了 foreach 标签供我们使用

    foreach 标签

    用来迭代任何可迭代的对象(如数组,集合)。

    • collection 属性:指定遍历的数组

      • mybatis会将数组参数,封装为一个Map集合。

        • 默认:array = 数组,key是array而不是数组名,如collection="array"和void deleteByIds(int[] ids);

        • 可以使用@Param注解改变map集合的默认key的名称为数组名,如collection="ids"和void deleteByIds(@Param("ids") int[] ids);

    • item 属性:本次迭代获取到的元素,如item="id"。

    • separator 属性:集合项迭代之间的分隔符。foreach 标签不会错误地添加多余的分隔符。也就是最后一次迭代不会加分隔符。如separator=","

    • open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次。如open="("

    • close 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次。如close=")"

    BrandMapper 接口

    1. /**
    2. * 批量删除
    3. */
    4. void deleteByIds(int[] ids);

    BrandMapper.xml

    1. <delete id="deleteByIds">
    2. delete from tb_brand where id
    3. in
    4. <foreach collection="array" item="id" separator="," open="(" close=")">
    5. #{id}
    6. foreach>
    7. ;
    8. delete>

    MybatisTest类

    1. @Test
    2. public void testDeleteByIds() throws IOException {
    3. //接收参数
    4. int[] ids = {5,7,8};
    5. //1. 获取SqlSessionFactory
    6. String resource = "mybatis-config.xml";
    7. InputStream inputStream = Resources.getResourceAsStream(resource);
    8. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    9. //2. 获取SqlSession对象
    10. SqlSession sqlSession = sqlSessionFactory.openSession();
    11. //SqlSession sqlSession = sqlSessionFactory.openSession(true);
    12. //3. 获取Mapper接口的代理对象
    13. BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    14. //4. 执行方法
    15. brandMapper.deleteByIds(ids);
    16. //提交事务
    17. sqlSession.commit();
    18. //5. 释放资源
    19. sqlSession.close();
    20. }

    Mybatis参数传递

    Mybatis 接口方法中可以接收各种各样的参数,如下:

    • 多个参数

    • 单个参数:单个参数又可以是如下类型

      • POJO 类型

      • Map 集合类型

      • Collection 集合类型

      • List 集合类型

      • Array 类型

      • 其他类型

    1.10.1 多个参数

    如下面的代码,就是接收两个参数,而接收多个参数需要使用 @Param 注解,那么为什么要加该注解呢?这个问题要弄明白就必须来研究Mybatis 底层对于这些参数是如何处理的。

    User select(@Param("username") String username,@Param("password") String password);

    我们在接口方法中定义多个参数,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

      1. <select id="select" resultType="user">
      2. select *
      3.   from tb_user
      4.   where
      5.   username=#{arg0}
      6.   and password=#{arg1}
      7. select>

      或者

      1. <select id="select" resultType="user">
      2. select *
      3.   from tb_user
      4.   where
      5.   username=#{param1}
      6.   and password=#{param2}
      7. 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

    • 运行程序结果没有报错。而如果将 #{} 中的 username 还是写成 arg0

    • 运行程序则可以看到错误

    结论:以后接口参数是多个时,在每个参数上都使用 @Param 注解。这样代码的可读性更高。

    注解实现增删改查

    使用注解开发会比配置文件开发更加方便。如下就是使用注解进行开发

    1. @Select(value = "select * from tb_user where id = #{id}")
    2. public User select(int id);

    注意:

    • 注解是用来替换映射配置文件方式配置的,所以使用了注解,就不需要再映射配置文件中书写对应的 statement

    Mybatis 针对 CURD 操作都提供了对应的注解,已经做到见名知意。如下:

    • 查询 :@Select

    • 添加 :@Insert

    • 修改 :@Update

    • 删除 :@Delete

    注意:在官方文档中 入门 中有这样的一段话:

    所以,注解完成简单功能,配置文件完成复杂功能。

    而我们之前写的动态 SQL 就是复杂的功能,如果用注解使用的话,就需要使用到 Mybatis 提供的SQL构建器来完成,而对应的代码如下:

    上述代码将java代码和SQL语句融到了一块,使得代码的可读性大幅度降低。

  • 相关阅读:
    绿联搭建rustdesk服务器
    计算机毕业设计之java+javaweb的外婆家网上订餐平台
    Python音乐信息管理库之beets使用详解
    网工内推 | 字节原厂,正式编,网络工程师,最高30K*15薪
    HTTP抓包神器---Fiddler
    Controller返回JSON数据
    关于ETL的两种架构(ETL架构和ELT架构)
    amazon账号注册用什么软件?
    Apache ECharts简介和相关操作
    解除centos下root修改密码被限制
  • 原文地址:https://blog.csdn.net/qq_40991313/article/details/125818307