MyBatis

一、MyBatis概述

1.1、MyBatis概念

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

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

JavaEE三层架构:表现层、业务层、持久层。以后开发我们会将操作数据库的Java代码作为持久层。而Mybatis就是对jdbc代码进行了封装。

框架:就是一个半成品软件,用来解决一类问题的一套可重用的、通用的、软件基础代码模型,在框架的基础之上构建软件编写更加高效、规范、通用、可扩展。

        如下图所示有一个石膏娃娃,这个就是一个半成品。你可以在这个半成品的基础上进行不同颜色的涂鸦形成不同的产品。

1.2、JDBC的缺点

硬编码:

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

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

操作繁琐:

        手动设置参数

        手动封装结果集,对查询到的数据进行封装的这部分代码是没有什么技术含量的,而且特别耗费时间的。

而使用MyBatis,硬编码可以配置到配置文件;操作繁琐的地方mybatis都可以自动完成。

二、MyBatis快速入门

IDEA 中配置 MySQL 数据库连接,创建user 表,添加数据
1.创建数据表
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)
);
INSERTINTO tb_user VALUES(1,'zhangsan','123','男','北京');
INSERTINTO tb_user VALUES(2,'李四','234','女','天津');
INSERTINTO tb_user VALUES(3,'王五','11','男','西安');

2.建立模型类,用于数据库数据的映射
public class User{
    private int id;
    private String username;  
    private String password;  
    private String gender;
    private String addr;
//省略了setter和getter
}
3.pom.xml 配置文件中添加依赖的坐标
<dependencies>
  <!--mybatis依赖-->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>    
	<version>3.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.13</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.3</version>
  </dependency>
  <!--添加logback-core依赖--> 
  <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId> 
    <version>1.2.3</version>
  </dependency>
</dependencies>
注意需要在项目的 resources 目录下创建logback的配置文件(略)
4.编写 SQL 映射文件 --> 统一管理sql语句,解决硬编码问题
在模块下的 resources 目录下创建配置文件UserMapper.xml内容如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC"-//mybatis.org//DTDMapper3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
    <select id="selectAll" resultType="com.itheima.pojo.User">
        select * from tb_user;
    </select>
</mapper>
5.编写 MyBatis 核心配置文件 -- > 替换连接信息解决硬编码问题
在模块下的 resources 目录下创建mybatis的配置文件mybatis-config.xml内容如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE configuration
    PUBLIC"-//mybatis.org//DTDConfig3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--别名,用来简化映射配置文件中属性值的编写-->
    <typeAliases>
       <typeAlias alias="User" type="com.example.domain.User"/>
       <!-- 包扫描方式,自动注册该包下所有类的别名 -->
       <!--MyBatis会自动为指定包下的所有类注册别名,别名默认为类名-->
       <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="com.mysql.jdbc.Driver"/> 
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/> 
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>   
        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
            <!--数据库连接信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatisuseSSL=false"/>        
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
       <!--加载sql映射文件-->
       <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>
6.编写 MybatisDemo 测试类 
public class MyBatisDemo{
    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
        List<User> users=sqlSession.selectList("test.selectAll");
        //参数是一个字符串,该字符串必须是映射配置文件的namespace.id
        System.out.println(users);
        //4.释放资源
        sqlSession.close();
    }
}

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


产生的原因:Idea和数据库没有建立连接,不识别表信息。但它并不影响程序的执行。
解决方式:在Idea中配置MySQL数据库连接。

三、Mapper代理开发

3.1、Mapper代理开发概述

之前我们写的代码是基本使用方式,它也存在硬编码的问题,如下:

这里调用selectList()方法传递的参数是映射配置文件中的 namespace.id值。这样写也不便于后期的维护。如果使用Mapper 代理方式(如下图)则不存在硬编码问题。

Mapper 代理方式的目的:解决原生方式中的硬编码;简化后期执行SQL。

Mybatis 官网也是推荐使用 Mapper 代理的方式。下图是截止官网的图片

3.2、使用Mapper代理要求

使用Mapper代理方式,必须满足以下要求:

        1.定义与SQL映射文件同名的Mapper接口,并将Mapper接口和SQL映射文件放置在同一目录

      

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

        

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

3.3、代码实现

1.在com.itheima.mapper包下创建 UserMapper接口,代码如下:

public interface UserMapper{  
    List<User> selectAll();
    User selectById(int id);
}
2.在resources下创建com/itheima/mapper目录,并在该目录下创建 UserMapper.xml 映射配置文件
<!--
  namespace:名称空间。必须是对应接口的全限定名
-->
<mapper namespace="com.itheima.mapper.UserMapper">
    <select id="selectAll" resultType="com.itheima.pojo.User">
        select * from tb_user;
    </select>
</mapper>
3.在com.itheima包下创建 MybatisDemo2 测试类,代码如下:
public class MyBatisDemo2{
    public static void main(String[] args)throws IOException{
        //1.加载mybatis的核心配置文件,获取SqlSessionFactory
        Stringresource="mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);    
        SqlSessionFactorysqlSessionFactory =
            new SqlSessionFactoryBuilder().build(inputStream);
        //2.获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //3.执行sql
        //3.1获取UserMapper接口的代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    
        List<User> users = userMapper.selectAll();
        System.out.println(users);    
        //4.释放资源
        sqlSession.close();
    }
}
如果 Mapper 接口名称和 SQL 映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化 SQL 映射文件的加载。也就是将核心配置文件的加载映射配置文件的配置修改为:
<mappers>
       <!--加载sql映射文件-->
       <mapperresource="UserMapper.xml"/>
</mappers>
改为:
<mappers>
  <!--加载sql映射文件-->
  <!--<mapper resource="com/itheima/mapper/UserMapper.xml"/>-->  <!--Mapper代理方式-->
  <packagename="com.itheima.mapper"/>
</mappers>

四、MyBatis案例练习

4.1 配置文件实现CURD

环境准备:

1.数据库表(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);

2.创建实体类
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。自己补全这部分代码
 }

安装MyBatisX插件:可以自动生成对应接口方法的映射文件statement

3.编写接口方法
public interface BrandMapper { 
/*** 查询所有 */ 
List<Brand> selectAll(); 
}

4. 创建名 BrandMapper.xml 映射配置文件
<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE mapper 
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "
    http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
<mapper namespace="com.itheima.mapper.BrandMapper">
    <!--statement--> 
    <select id="selectAll" resultType="brand"> 
        select * from tb_brand; 
    </select> 
</mapper>

5.创建核心配置文件mybatis-config.xml(略)
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE configuration
    PUBLIC"-//mybatis.org//DTDConfig3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
       <package name="com.itheima.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/> 
            <dataSource type="POOLED">
                <!--数据库连接信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/> 
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/> 
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>   
    </environments>
    <mappers>
       <mapper namespace="com.itheima.mapper.BrandMapper"></package>
    </mappers>
</configuration>

6.编写测试方法
@Test 
public void testSelectAll() throws IOException { 
    //1. 获取SqlSessionFactory 
    String resource = "mybatis-config.xml"; 
    InputStream inputStream = Resources.getResourceAsStream(resource); 
    SqlSessionFactory sqlSessionFactory = 
new SqlSessionFactoryBuilder().build(inputStream);
    //2. 获取SqlSession对象 
    SqlSession sqlSession = sqlSessionFactory.openSession(); 
    //3. 获取Mapper接口的代理对象 
    BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); 
    //4. 执行方法 
    List<Brand> brands = brandMapper.selectAll(); 
    System.out.println(brands);
    //5. 释放资源 
    sqlSession.close();
    }
}

如图,运行以上程序发现brandName,companyName是空值没有封装成功,为什么?

因为数据库表字段 和 实体类的属性名称不一样,则不能自动封装数据,解决方法:

1.起别名:不一样的列名起别名,让别名和实体类属性名一样(每个查询都要写一次,麻烦)
<select id="selectAll" resultType="brand"> 
    select id, brand_name as brandName, company_name as companyName, 
    ordered, description, status from tb_brand; 
</select>
              
2.sql片段(不灵活)
<sql id="brand_column"> 
    id, brand_name as brandName, company_name as companyName, ordered, 
    description, status 
</sql>
<select id="selectAll" resultType="brand"> 
    select <include refid="brand_column" /> from tb_brand; 
</select>

3.resultMap
<resultMap id="brandResultMap" type="brand"> 
    <!--id:完成主键字段的映射 column:表的列名 
        property:实体类的属性名 result:完成一般字段的映射 
         --> 
    <result column="brand_name" property="brandName"/> 
    <result column="company_name" property="companyName"/> 
</resultMap>
<select id="selectAll" resultMap="brandResultMap"> 
    select * from tb_brand; 
</select>
注意:在上面只需要定义 字段名 和 属性名 不一样的映射,而一样的则不需要专门定义出来。

4.1.1 查询详情

1.在 BrandMapper 接口中定义根据id查询数据的方法
/*** 查看详情:根据Id查询 */ 
Brand selectById(int id);

2.在映射配置文件中编写 statement ,使用 resultMap
<select id="selectById" resultMap="brandResultMap"> 
    select * from tb_brand where id = #{id}; 
</select>

3.测试方法中添加
//接收参数,该id以后需要传递过来 
int id = 1;
// 执行方法 
Brand brand = brandMapper.selectById(id);

4.运行程序


(1)parameterType使用
对于有参数的mapper接口方法,我们在映射配置文件中应该配置 ParameterType 来指定参数类型。
只不过该属性都可以省略。
<select id="selectById" parameterType="int" resultMap="brandResultMap"> 
    select * from tb_brand where id = ${id}; 
</select>

(2)SQL语句中特殊字段处理
以后肯定会在SQL语句中写一下特殊字符,比如某一个字段大于某个值
 > < 等这些字符在xml中有特殊含义,所以此时我们需要将这些符号进行转义

<select id="selectById" parameterType="int" resultMap="brandResultMap"> 
    select * from tb_brand where id &lt #{id}; 
</select>

        控制台显示的SQL语句,能看到使用?进行占位说明我们在映射配置文件中的写的 #{id} 最终会被?进行占位。

mybatis提供了两种参数占位符:(JDBC中PreparedStatement

        #{} :执行SQL时,会将 #{} 占位符替换为?,将来自动设置参数值。从上述例子可以看出使用#{} 底层使用的是PreparedStatement(开发中使用此占位符)

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

4.1.2 多条件查询

1.在 BrandMapper 接口中定义多条件查询的方法

方法一:使用 @Param("参数名称") 标记每一个参数,
在映射配置文件中就需要使用 #{参数名称} 进行占位
List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") 
String companyName,@Param("brandName") String brandName);

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

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

2.编写SQL语句
<select id="selectByCondition" resultMap="brandResultMap"> 
    select * 
    from tb_brand 
    where status = #{status} 
    and company_name like #{companyName} 
    and brand_name like #{brandName} 
</select>

3.编写测试方法
@Test 
public void testSelectByCondition() throws IOException { 
    //接收参数 int status = 1; 
    String companyName = "华为"; 
    String brandName = "华为"; 
    // 处理参数 
    companyName = "%" + companyName + "%"; 
    brandName = "%" + 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. 执行方法 
    //方式一 :接口方法参数使用 @Param 方式调用的方法 
    //List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName); 
    //方式二 :接口方法参数是 实体类对象 方式调用的方法 
    //封装对象 
    /* Brand brand = new Brand(); 
    brand.setStatus(status); 
    brand.setCompanyName(companyName); 
    brand.setBrandName(brandName);*/
    //List<Brand> brands = brandMapper.selectByCondition(brand);
    //方式三 :接口方法参数是 map集合对象 方式调用的方法 
    Map map = new HashMap(); 
    map.put("status" , status); 
    map.put("companyName", companyName); 
    map.put("brandName" , brandName); 
    List<Brand> brands = brandMapper.selectByCondition(map); 
    System.out.println(brands); 
    //5. 释放资源 
    sqlSession.close(); 
}

4.1.3 动态多条件查询

        上述功能实现存在很大的问题。用户在输入条件时,肯定不会所有的条件都填写。如果条件没有填完整程序运行会出问题。我们需要灵活的输入条件查询。针对上述的需要,Mybatis对动态SQL有很强大的支撑:

//test 属性:逻辑表达式;if 标签:条件判断
<select id="selectByCondition" resultMap="brandResultMap"> 
    select * 
    from tb_brand 
    <where>
        <if test="status != null">
            and status = #{status} 
        </if> 
        <if test="companyName != null and companyName != '' "> 
            and company_name like #{companyName} 
        </if> 
        <if test="brandName != null and brandName != '' "> 
            and brand_name like #{brandName} 
        </if> 
    </where>
</select>

这种SQL语句就会根据传递的参数值进行动态的拼接。哪个属性有值那么就会值拼接哪个条件。

4.1.4 单个条件动态查询

如上图所示,在查询时只能选择 品牌名称 、 当前状态 、 企业名称 这三个条件中的一个,但是用户到底选择哪儿一个,我们并不能确定。这种就属于单个条件的动态SQL语句。

1.编写接口方法
/**
    * 单条件动态查询 
    * @param brand 
    * @return 
*/ 
List<Brand> selectByConditionSingle(Brand brand);

2.映射配置文件中编写 statement
<select id="selectByConditionSingle" resultMap="brandResultMap"> 
    select * 
    from tb_brand 
    <where> 
        <choose><!--相当于switch--> 
            <when test="status != null"><!--相当于case--> 
                status = #{status} 
            </when> 
            <when test="companyName != null and companyName != '' "><!--相当于case--> 
                company_name like #{companyName} 
            </when> 
            <when test="brandName != null and brandName != ''"><!--相当于case--> 
                brand_name like #{brandName} 
            </when> 
        </choose> 
    </where> 
</select>

3.编写测试方法
@Test 
public void testSelectByCondition() throws IOException { 
    //接收参数 int status = 1; 
    String companyName = "华为"; 
    String brandName = "华为"; 
    // 处理参数 
    companyName = "%" + companyName + "%"; 
    brandName = "%" + 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. 执行方法 
    //封装对象 
    Brand brand = new Brand(); 
    //brand.setStatus(status); 
    brand.setCompanyName(companyName); 
    //brand.setBrandName(brandName);
    List<Brand> brands = brandMapper.selectByCondition(brand);
    System.out.println(brands); 
    //5. 释放资源 
    sqlSession.close(); 
}

4.1.5 添加数据

1.添加接口方法
void add(Brand brand);

2.映射配置文件中编写添加数据的 statement
<insert id="add"> 
    insert into tb_brand (brand_name, company_name, ordered, description, status) 
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status}); 
</insert>

3.编写测试方法(多条件查询改一下)
//接收参数 
int status = 1; 
String companyName = "波导手机"; S
tring brandName = "波导"; 
String description = "手机中的战斗机"; 
int ordered = 100;
//4. 执行方法 
brandMapper.add(brand);
Integer id = brand.getId();
System.out.println(id);//打印出null,无法获取主键id
//提交事务 
sqlSession.commit();

添加-主键返回:在数据添加成功后,获取插入数据库数据的主键(主键是自增长)。
<insert id="add" useGeneratedKeys="true" keyProperty="id"> 
    insert into tb_brand (brand_name, company_name, ordered, description, status) 
    values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status}); 
</insert>
在 insert 标签上添加如下属性:
    useGeneratedKeys:是够获取自动增长的主键值。true表示获取
    keyProperty :指定将获取到的主键值封装到哪儿个属性里

此时再在测试方法里面打印获取主键id,可以打印出来
brandMapper.add(brand);
Integer id = brand.getId();
System.out.println(id);

4.1.6 修改数据

1.在 BrandMapper 接口中定义修改方法。
void update(Brand brand);

2.在 BrandMapper.xml 映射配置文件中添加修改数据的 statement 。
//set 标签可以用于动态包含需要更新的列,忽略其它不更新的列。
<update id="update"> 
    update tb_brand 
    <set>
        <if test="brandName != null and brandName != ''"> 
            brand_name = #{brandName}, 
        </if> 
        <if test="companyName != null and companyName != ''"> 
            company_name = #{companyName}, 
        </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>

3.编写测试方法
//接收参数 
int status = 0; 
String companyName = "波导手机"; 
String brandName = "波导"; 
String description = "波导手机,手机中的战斗机"; 
int ordered = 200; 
int id = 6;
Brand brand = new Brand(); 
brand.setStatus(status);
brand.setId(id);
int count = brandMapper.update(brand); 
System.out.println(count);
//提交事务 
sqlSession.commit();

4.1.7 删除一行数据

1.在 BrandMapper 接口中定义根据id删除方法。
void deleteById(int id);

2.在 BrandMapper.xml 映射配置文件中编写删除一行数据的 statement
<delete id="deleteById"> 
    delete from tb_brand where id = #{id}; 
</delete>

3.编写测试方法
int id = 6;
// 执行方法 
brandMapper.deleteById(id); 
//提交事务 
sqlSession.commit();

4.1.8 批量删除

1.在 BrandMapper 接口中定义删除多行数据的方法。
void deleteByIds(int[] ids);

2.在 BrandMapper.xml 映射配置文件中编写删除多条数据的 statement 。
//foreach 标签:用来迭代任何可迭代的对象
<delete id="deleteByIds"> 
    delete from tb_brand where id 
    in
    <foreach collection="array" item="id" separator="," open="(" close=")"> 
        #{id} 
    </foreach> 
    ; 
</delete>
collection 属性:mybatis会将数组参数,封装为一个Map集合。
item 属性:本次迭代获取到的元素。
separator 属性:集合项迭代之间的分隔符。
foreach 标签不会错误地添加多余的分隔符;也就是最后一次迭代不会加分隔符
open 属性:该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次
lose 属性:该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次

3.编写测试方法
//接收参数
int[] ids = {5,7,8};
//执行方法
brandMapper.deleteByIds(ids);

4.2 MyBatis参数封装

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

<select id="select" resultType="user"> 
    select * from tb_user 
    where 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);

User select(String username,String password);

<select id="select" resultType="user"> 
    select * from tb_user 
    where username=#{arg0} 
    and password=#{arg1} 
</select>
或
<select id="select" resultType="user"> 
    select * from tb_user 
    where username=#{param1} 
    and password=#{param2} 
</select>
 
User select(@Param("username") String username, String password);
Mybatis 在封装 Map 集合时,键名就会变成如下:(agr0被替代了)
map.put("username",参数值1);
map.put("arg1",参数值2);
map.put("param1",参数值1);
map.put("param2",参数值2);

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

4.3 注解实现CURD

        注解是用来替换映射配置文件方式配置的,所以使用了注解,就不需要再映射配置文件中书写对应的 statement;注解完成简单功能,配置文件完成复杂功能。

1.创建数据库表
create database spring_db character set utf8; 
use spring_db; 
create table tbl_account( 
    id int primary key auto_increment, 
    name varchar(35), 
    money double 
);

2.导入pom.xml相关依赖(略)

3.根据表创建模型类
public class Account implements Serializable { 
    private Integer id; 
    private String name; 
    private Double money; 
    //setter...getter...toString...方法略 
}

4.创建Dao接口(Mybatis注解方式)
public interface AccountDao { 
    @Insert("insert into tbl_account(name,money)values(#{name},#{money})") 
    void save(Account account); 
    @Delete("delete from tbl_account where id = #{id} ") 
    void delete(Integer id); 
    @Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ")
    void update(Account account); 
    @Select("select * from tbl_account") 
    List<Account> findAll(); 
    @Select("select * from tbl_account where id = #{id} ") 
    Account findById(Integer id); 
}

5.创建Service接口和实现类
public interface AccountService { 
    void save(Account account); 
    void delete(Integer id); 
    void update(Account account); 
    List<Account> findAll(); 
    Account findById(Integer id); 
}

@Service 
public class AccountServiceImpl implements AccountService { 
    @Autowired 
    private AccountDao accountDao; 
    public void save(Account account) { 
        accountDao.save(account); 
    }
    public void update(Account account){ 
        accountDao.update(account); 
    }
    public void delete(Integer id) { 
        accountDao.delete(id); 
    }
    public Account findById(Integer id) { 
        return accountDao.findById(id); 
    }
    public List<Account> findAll() { 
        return accountDao.findAll(); 
    } 
}

6.添加jdbc.properties文件:resources目录下添加,用于配置数据库连接四要素
//useSSL:关闭MySQL的SSL连接
jdbc.driver=com.mysql.jdbc.Driver 
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false 
jdbc.username=root 
jdbc.password=root

7.添加Mybatis核心配置文件
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE configuration
    PUBLIC"-//mybatis.org//DTDConfig3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--读取外部properties配置文件--> 
    <properties resource="jdbc.properties"></properties> 
    <typeAliases> 
        <!-- 包扫描方式,自动注册该包下所有类的别名 -->
        <!--MyBatis会自动为指定包下的所有类注册别名,别名默认为类名-->
        <package name="com.itheima.domain"/> 
    </typeAliases>
    <!--数据源--> 
    <environments default="mysql"> 
        <environment id="mysql"> 
            <transactionManager type="JDBC"></transactionManager> 
            <dataSource type="POOLED"> 
                <property name="driver" value="${jdbc.driver}"></property> 
                <property name="url" value="${jdbc.url}"></property> 
                <property name="username" value="${jdbc.username}"></property> 
                <property name="password" value="${jdbc.password}"></property> 
            </dataSource> 
        </environment> 
    </environments>
    <!--映射文件扫描包路径-->
    <mappers>
       <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

8.编写应用程序
public class App { 
    public static void main(String[] args) throws IOException { 
        // 1. 创建SqlSessionFactoryBuilder对象 
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = 
new SqlSessionFactoryBuilder(); 
        // 2. 加载SqlMapConfig.xml配置文件(核心配置文件)
        InputStream inputStream = 
Resources.getResourceAsStream("SqlMapConfig.xml"); 
        // 3. 创建SqlSessionFactory对象 
        SqlSessionFactory sqlSessionFactory = 
sqlSessionFactoryBuilder.build(inputStream); 
        // 4. 获取SqlSession 
        SqlSession sqlSession = sqlSessionFactory.openSession(); 
        // 5. 执行SqlSession对象执行查询,获取结果User 
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class); 
        Account ac = accountDao.findById(1); 
        System.out.println(ac); 
        // 6. 释放资源 
        sqlSession.close(); 
    } 
}

9.运行程序
Account{id=1, name='Tom',money=1000.0}

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值