栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaWeb基础3——Maven&MyBatis

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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团队维护的全球唯一的仓库

    • 地址: Central Repository:

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

当项目中使用坐标引入对应依赖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.6conf/settings.xml 中的 为一个指定目录(例如D:apache-maven-3.8.6mvn_resp)作为本地仓库,用来存储jar包。

4.配置阿里云私服:

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

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

  
    alimaven  
    aliyun maven  
    http://maven.aliyun.com/nexus/content/groups/public/
    central          

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 project-maven-next

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

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

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

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

配置 Maven-Helper 插件

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

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

 依赖管理

引入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等。

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

 

注意:

  • 具体的坐标我们可以到如下网站进行搜索

  • https://mvnrepository.com/

设置自动刷新:

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【根标签】

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

示例:







    
        
    

    

    


        





            







            
                
                
                
                
                
            
        
    
    
        




        
    

properties【属性标签】

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

示例:


    
    
    
    
        
            
            
            
            
                
                
                
                

            
        
    

settings【设置标签】

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

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

示例代码


        
        

typeAliases【类型别名】

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


  
  
  
  
  
  

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



    
        
    

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







    
        select * from tb_user;
    

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 上下文的数据源引用。

示例:

    

    


        





            







            
                
                
                
                
                
            
        
    

databaseIdProvider(数据库厂商标识)

mappers 【映射器】


作用:加载映射文件
 

    
        
        
    

Mybatis入门案例

步骤

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

1.创建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(30)
);
​
INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');

2.创建模块,导入坐标

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


    
    
        org.mybatis
        mybatis
        3.5.5
    

    
    
        mysql
        mysql-connector-java
        5.1.46
    

    
    
        junit
        junit
        4.13
        test
    

    
    
        org.slf4j
        slf4j-api
        1.7.20
    
    
    
        ch.qos.logback
        logback-classic
        1.2.3
    
    
    
        ch.qos.logback
        logback-core
        1.2.3
    

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



    
    
        
            [%level]  %cyan([%thread]) %boldGreen(%logger{15}) - %msg %n
        
    

    
        
    


    
    
        
    

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,内容如下:







    
        
    

    

    


        





            







            
                
                
                
                
                
            
        
    
    
        

        
    

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

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






    
        select * from tb_user;
    

根标签【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对象。

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

public class User {
    private int id;
    private String username;
    private String password;
    private String gender;
    private String addr;

    //省略了 setter 和 getter

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + ''' +
                ", password='" + password + ''' +
                ", gender='" + gender + ''' +
                ", addr='" + addr + ''' +
                '}';
    }
}

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

步骤:

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

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

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

示例:

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

List users=userMapper.selectAll();

package package1;
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 package1.pojo.User;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class Demo {

    public static void main(String[] args) throws IOException {
        //1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //3. 执行sql
        //参数是一个字符串,该字符串必须是映射配置文件的namespace.id
        List users = sqlSession.selectList("test.selectAll");
        System.out.println(users);
        //4. 释放资源
        sqlSession.close();
    }
}

对比一下jdbc:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
 

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

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接口全限定名:






    
        select * from tb_user where id=#{id};
    

 特殊字符处理:

1.转义字符

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

2.CDATA区

    
        select *
        from tb_brand;
    

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

单条件查询

UserMapper.java 

User selectById(int id);

UserMapper.xml


    
    select *
    from tb_brand
    where status = #{status}
    and company_name like #{companyName}
    and brand_name like #{brandName}
//Demo.java
List brands = brandMapper.selectByCondition(status, companyName, brandName);

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

//BrandMapper.java
List selectByCondition(Brand brand);


    select *
    from tb_brand
    where status = #{status}
    and company_name like #{companyName}
    and brand_name like #{brandName}

//Demo.java
    Map map = new HashMap();
    map.put("status" , status);
    map.put("companyName", companyName);
    map.put("brandName" , brandName);
    List brands = brandMapper.selectByCondition(map);
    System.out.println(brands);

BrandMapper.xml都是一样的  



    select *
    from tb_brand

    where 1=1
        
            and status = #{status}
        
        
            and company_name like #{companyName}
        
        
            and brand_name like #{brandName}
        

where 标签作用:

  • 替换where关键字

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

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

​​​​​​​示例:

    
    select *
    from tb_brand
    
        
            
                status = #{status}
            
            
                company_name like #{companyName}
            
            
                brand_name like #{brandName}
            
        
    
//BrandMapper.java
List selectByConditionSingle(Brand brand);
//Demo.java
@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. 获取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 brandMapper = sqlSession.getMapper(BrandMapper.class);
    //4. 执行方法
    List brands = brandMapper.selectByConditionSingle(brand);
    System.out.println(brands);

    //5. 释放资源
    sqlSession.close();
}

添加数据
//BrandMapper.java
 
int add(Brand brand);


    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
//测试类
@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. 获取SqlSessionFactory
    String 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. 执行方法
    
    System.out.println(brandMapper.add(brand));
    //要手动提交,不然会回滚事务。如果前面sqlSessionFactory.openSession(true),就不用再提交事务了
    sqlSession.commit();
    //5. 释放资源
    sqlSession.close();
}

Mybatis事务:

 返回主键

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

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

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


    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});

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

修改全部字段

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

BrandMapper 接口

 
void update(Brand brand);

BrandMapper.xml


    update tb_brand
    
        
            brand_name = #{brandName},
        
        
            company_name = #{companyName},
        
        
            ordered = #{ordered},
        
        
            description = #{description},
        
        
            status = #{status}
        
    
    where id = #{id};

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. 获取SqlSessionFactory
    String 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();
}

修改动态字段

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

删除一行数据

BrandMapper 接口

void deleteById(int id);

BrandMapper.xml


    delete from tb_brand where id = #{id};

MybatisTest类

 @Test
public void testDeleteById() throws IOException {
    //接收参数
    int id = 6;

    //1. 获取SqlSessionFactory
    String 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();
}

批量删除

编写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 接口

void deleteByIds(int[] ids);

BrandMapper.xml


    delete from tb_brand where id
    in
    
        #{id}
    
    ;

MybatisTest类

@Test
public void testDeleteByIds() throws IOException {
    //接收参数
    int[] ids = {5,7,8};

    //1. 获取SqlSessionFactory
    String 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();
}

Mybatis参数传递

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

  • 多个参数

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

    • POJO 类型

    • Map 集合类型

    • Collection 集合类型

    • List 集合类型

    • Array 类型

    • 其他类型

1.10.1 多个参数

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

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

    select *
    from tb_user
    where 
        username=#{arg0}
        and password=#{arg1}

或者


    select *
    from tb_user
    where 
        username=#{username}
        and password=#{param2}
  • 运行程序结果没有报错。而如果将 #{} 中的 username 还是写成 arg0