文章目录
- 【MyBatis精讲】从入门到精通的详细指南:简化Java持久层操作的艺术
- 1.mybatis快速入门
- 1.1创建步骤
- 1.2mapper代理开发模式
 
- 2.mybatis增删改查
- 2.1查询所有数据
- 2.2 id查询数据
- 2.3插入数据
- 2.4修改数据
- 2.5删除数据
- 2.6 mybatis多条件查询
- 2.7 mybatis动态条件查询
 
- 3.MyBatis - 映射文件标签
- 3.1映射文件的顶级元素
- 3.2 select 标签的属性信息
- 3.3 resultMap 标签的属性信息
- 3.4 insert 标签的属性信息
- 3.5重用 sql 标签和完全限定名使用别名替代
 
- 4. 常见问题
 
【MyBatis精讲】从入门到精通的详细指南:简化Java持久层操作的艺术
什么是mybatis
 MyBatis是一个优秀的Java持久层框架,它使用ORM实现了结果集的封装,它通过XML或注解的方式,将SQL语句和Java代码进行映射,以实现数据库操作。MyBatis提供了强大的SQL映射能力和灵活的查询功能,可以方便地进行数据持久化操作。
ORM是Object Relational Mapping 对象关系映射。简单来说,就是把数据库表和实体类及实体类的属性对应起来,让开发者操作实体类就实现操作数据库表,它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等复杂过程。
ORM:Object-Relation-Mapping,也就是对象关系映射,是一种程序设计思想,mybatis就是ORM的一种实现方式,简单来说就是将数据库中查询出的数据映射到对应的实体中。
 数据库层框架
- com.zhaoli.servlet或者com.zhaoli.controller--------控制层 springmvc
- com.zhaoli.service—业务逻辑层
- com.zhaoli.dao----数据库访问层 hibernate或者mybatis、jpa
- 数据库连接相关配置
- 编写sql语句 jdbc 查询操作 单独取出每个值 在赋值给我们对象
mybatis、springmvc、springboot
 使用mybatis orm java中 对象与数据库中表中 字段 对应
 底层通过反射机制自动赋值
 sql语句 自动形式得出对象
 前提 orm映射
1.mybatis快速入门
数据库表结构
CREATE TABLE `dome01_users` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
`age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb3;
1.1创建步骤
- 引入mybatis相关依赖
- mybatis-config.xml(该配置文件名称是可以改) 存放就是我们数据库相关连接信息
- 定义mapper ----编写我们mybatis 相关 sql语句,每个表对应一个mapper
- 定义java对象–需要注意下类中的成员属性与数据库表中字段需要做映射,默认类中的成员属性数据库表中字段名称对应的。
- 使用 mybatis api开始执行该 sql语句即可 得到结果
maven依赖
<dependencies>
    <!-- mybatis 依赖 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <!-- mysql 驱动依赖 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.18</version>
    </dependency>
</dependencies>
定义xml配置文件
 在D:\java\MyJavaMybatis_01\MybatisDome01\src\main\resources下创建mybatis-config.xml
 存放数据库连接信息mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 数据库相关的配置 -->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/数据库名?serverTimezone=GMT%2B8"/>
                <property name="username" value="mysql账号"/>
                <property name="password" value="mysql密码"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/userMaaper.xml"/>
    </mappers>
</configuration>

Maaper文件
 在D:\java\MyJavaMybatis_01\MybatisDome01\src\main\resources 下创建一个 mapper 包
 mapper 中是编写我们mybatis 相关 sql语句,每个表对应一个mapper
 之后在在mapper 包下创建一个 userMapper.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="userMapper">
    <select id="getByUsers" resultType="com.zhaoli.entity.UsersEntity">
        select * from dome01_users
    </select>
</mapper>

测试代码
import com.zhaoli.entity.UsersEntity;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Test01 {
    public static void main(String[] args) throws IOException {
        String resource="mybatis-config.xml";
        //解析 mybatis-config.xml 得到数据库相关的配置信息
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建得到一个 sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取到 sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<UsersEntity> usersEntityList = sqlSession.selectList("getByUsersAll", UsersEntity.class);
        System.out.printf(usersEntityList.toString());
        sqlSession.close();
    }
}

1.2mapper代理开发模式
- mapper接口方式开发整合就必须是对应的mapper接口的全限定类名
- 接口中的方法与映射文件中的SQL语句的ID
- 需要在mybatis-config.xml新增 加载该userMaaper
    <mappers>
        <mapper resource="mybatis/userMapper.xml"/>
    </mappers>
- 定义mapper 接口 需要考虑方法的名称与userMapper.xml的 sql id名称保持一致。
import com.zhaoli.entity.UserEntity;
import java.util.List;
public interface UserMapper {
    /**
     * 调用到 userMapper.getByUsers 方法时 自动查找 userMapper.xml 中的 getByUsers 方法 执行 sql 语句
     * sql 语句的 id 值与接口的方法名称对应
     */
    List<UserEntity> getByUsers();
}
- 相关代码
import com.zhaoli.entity.UserEntity;
import com.zhaoli.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Test02 {
    //面向接口编程的方式
    public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        //解析 mybatis-config.xml 得到数据库相关的配置信息
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建得到一个 sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取到 sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<UserEntity> userEntityList = userMapper.getByUsers();
        System.out.println(userEntityList);
        sqlSession.close();
    }
}
userMapper.xml 的变化 namespace=”接口的完整路径地址”
<?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.zhaoli.mapper.UserMapper">
    <!-- namespace+id(全局唯一不允许重复) userMapper.getByUsers -->
    <select id="getByUsers" resultType="com.zhaoli.entity.UserEntity">
        SElECT * FROM dome01_users;
    </select>
</mapper>
2.mybatis增删改查
数据库
CREATE TABLE `mayikt_flight` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT 'id列',
  `flight_id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '航号',
  `company` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '航空公司',
  `departure_airport` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '出发机场',
  `arrive_airport` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '达到机场',
  `departure_time` datetime DEFAULT NULL COMMENT '出发时间',
  `arrive_time` datetime DEFAULT NULL COMMENT '到达时间',
  `model` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '机型',
  `is_delete` int DEFAULT NULL COMMENT '是否隐藏0显示 1隐藏',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb3;
2.1查询所有数据
com/zhaoli/entity/FlightEntity.java
package com.zhaoli.entity;
import java.util.Date;
public class FlightEntity {
    private Integer id;//id列
    private String flightId;//航号
    private String company;//航空公司
    private String departureAirport;//出发机场
    private String arriveAirport;//达到机场
    private Date departureTime;//出发时间
    private Date arriveTime;//到达时间
    private String model;//机型
    private Integer isDelete;//是否隐藏0显示 1隐藏
    public FlightEntity() {
    }
    public FlightEntity(Integer id, String flightId, String company, String departureAirport, String arriveAirport, Date departureTime, Date arriveTime, String model, Integer isDelete) {
        this.id = id;
        this.flightId = flightId;
        this.company = company;
        this.departureAirport = departureAirport;
        this.arriveAirport = arriveAirport;
        this.departureTime = departureTime;
        this.arriveTime = arriveTime;
        this.model = model;
        this.isDelete = isDelete;
    }
//此处省略get()和set()
    @Override
    public String toString() {
        return "FlightEntity{" +
                "id=" + id +
                ", flightId='" + flightId + '\'' +
                ", company='" + company + '\'' +
                ", departureAirport='" + departureAirport + '\'' +
                ", arriveAirport='" + arriveAirport + '\'' +
                ", departureTime=" + departureTime +
                ", arriveTime=" + arriveTime +
                ", model='" + model + '\'' +
                ", isDelete=" + isDelete +
                '}';
    }
}
com/zhaoli/mapper/FlightMapper.java
package com.zhaoli.mapper;
import com.zhaoli.entity.FlightEntity;
import java.util.List;
public interface FlightMapper {
    /**
     * 查询
     * 1.查询所有
     * 2.根据条件查询
     * 3.动态查询方式
     */
    List<FlightEntity> getByFlightAll();
}
com/zhaoli/service/FlightService.java
package com.zhaoli.service;
import com.zhaoli.entity.FlightEntity;
import com.zhaoli.mapper.FlightMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class FlightService {
    private FlightMapper flightMapper;
    /**
     * 通过无参构造方法 初始化 mybatis 得到 flightMapper
     */
    public FlightService() throws IOException {
        String resource = "mybatis-config.xml";
        //解析 mybatis-config.xml 得到数据库相关的配置信息
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //创建得到一个 sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取到 sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        flightMapper = sqlSession.getMapper(FlightMapper.class);
//        sqlSession.close();
    }
    public List<FlightEntity> getByFlightAll(){
        return flightMapper.getByFlightAll();
    }
}
com/zhaoli/test/Test01.java
package com.zhaoli.test;
import com.zhaoli.entity.FlightEntity;
import com.zhaoli.service.FlightService;
import java.io.IOException;
import java.util.List;
public class Test01 {
    /**
     * 查询所有航班信息
     */
    public static void main(String[] args) throws IOException {
        FlightService flightService = new FlightService();
        List<FlightEntity> flightEntityList = flightService.getByFlightAll();
        System.out.println(flightEntityList);
    }
}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 数据库相关的配置 -->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis_01?serverTimezone=GMT%2B8&useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="20020806"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mybatis/flightMapper.xml"/>
    </mappers>
</configuration>
mybatis/flightMapper.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.zhaoli.mapper.FlightMapper">
    <!-- namespace+id(全局唯一不允许重复) userMapper.getByUsers -->
    <select id="getByFlightAll" resultType="com.zhaoli.entity.FlightEntity">
        SElECT * FROM dome02_flight;
    </select>
</mapper>
解决数据库与类中成员属性不一致性
 方式1:
 使用 sql语句 as的方法,代码会非常重复。
<?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.zhaoli.mapper.FlightMapper">
    <!-- namespace+id(全局唯一不允许重复) userMapper.getByUsers -->
    <select id="getByFlightAll" resultType="com.zhaoli.entity.FlightEntity">
        SElECT id                as id
             , flight_id         as flightId
             , company           as company
             , departure_airport as departureAirport
             , arrive_airport    as arriveAirport
             , departure_time    as departureTime
             , arrive_time       as arriveTime
             , model             as model
             , is_delete         as isDelete
        FROM dome02_flight;
    </select>
</mapper>
方式2:
 resultMap 定义数据库表中字段名称与类中成员属性名称 关联映射
 数据库字段:例如flight_id----类中成员名称 flightId
 mybatis/flightMapper.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.zhaoli.mapper.FlightMapper">
    <!-- 定义数据库中字段名与我们类中的成员属性值关联映射 -->
    <resultMap id="flightEntityMap" type="com.zhaoli.entity.FlightEntity">
        <!-- column="" 数据库中字段名称 property="" FlightEntity 类中的成员属性名称 -->
        <id column="id" property="id"></id><!-- id 唯一性 -->
        <result column="flight_id" property="flightId"></result><!-- result 与id相比,对应普通属性 -->
        <result column="departure_airport" property="departureAirport"></result>
        <result column="arrive_airport" property="arriveAirport"></result>
        <result column="departure_time" property="departureTime"></result>
        <result column="arrive_time" property="arriveTime"></result>
        <result column="is_delete" property="isDelete"></result>
</resultMap>
    <select id="getByFlightAll2" resultMap="flightEntityMap">
        SELECT * FROM dome02_flight;
    </select>
</mapper>
2.2 id查询数据
com/zhaoli/mapper/FlightMapper.java
/**
 * 根据主键 id 查找航班信息
 */
FlightEntity getByIdFlight(Integer id);
com/zhaoli/service/FlightService.java
/**
 * 根据主键 id 查找航班信息
 */
public FlightEntity getByIdFlight(Integer id) {
    return flightMapper.getByIdFlight(id);
}
mybatis/flightMapper.xml
<!--  根据主键 id 查找航班信息 parameterType="" 传递参数的类型  -->
<select id="getByIdFlight" parameterType="int" resultMap="flightEntityMap">
    SELECT * FROM dome02_flight WHERE id=#{id};
</select>
com/zhaoli/test/Test01.java
//根据主键 id 查找航班信息        
FlightEntity flightEntity = flightService.getByIdFlight(2);
System.out.println(flightEntity)
2.3插入数据
com/zhaoli/mapper/FlightMapper.java
/**
 * 添加航班信息
 */
int insertFlight(FlightEntity flightEntity);
com/zhaoli/service/FlightService.java
/**
 * 添加航班信息
 */
public int insertFlight(FlightEntity flightEntity) {
    int result = flightMapper.insertFlight(flightEntity);
    //insert 需要手动提交事务
    sqlSession.commit();//提交事务
    return result;
}
mybatis/flightMapper.xml
<!-- 添加航班信息   -->
<insert id="insertFlight" parameterType="com.zhaoli.entity.FlightEntity">
    INSERT INTO dome02_flight VALUES (null,#{flightId},#{company},#{departureAirport},#{arriveAirport},#{departureTime},#{arriveTime},#{model},#{isDelete});
</insert>
com/zhaoli/test/Test01.java
//添加航班信息
FlightEntity flightEntity = new FlightEntity();
flightEntity.setFlightId("setFlightId");
flightEntity.setCompany("setCompany");
flightEntity.setDepartureAirport("setDepartureAirport");
flightEntity.setArriveAirport("setCompany");
flightEntity.setDepartureTime(new Date());
flightEntity.setArriveTime(new Date());
flightEntity.setModel("setModel");
flightEntity.setIsDelete(0);
int result = flightService.insertFlight(flightEntity);
System.out.println(result);
2.4修改数据
com/zhaoli/mapper/FlightMapper.java
/**
 * 根据主键 id 修改航班信息
 */
int updateFlight(FlightEntity flightEntity);
com/zhaoli/service/FlightService.java
 /**
- 根据主键 id 修改航班信息
 */
public int updateFlight(FlightEntity flightEntity) {
   int result = flightMapper.updateFlight(flightEntity);
   //update 需要手动提交事务
   sqlSession.commit();//提交事务
   return result;
}
mybatis/flightMapper.xml
<!--  根据主键 id 修改航班信息  -->
<update id="updateFlight" parameterType="com.zhaoli.entity.FlightEntity">
    UPDATE dome02_flight
    SET id=#{id},
        flight_id=#{flightId},
        company=#{company},
        departure_airport=#{departureAirport},
        arrive_airport=#{arriveAirport},
        departure_time=#{departureTime},
        arrive_time=#{arriveTime},
        model=#{model},
        is_delete=#{isDelete}
    WHERE (id = #{id});
</update>
com/zhaoli/test/Test01.java
//根据主键 id 修改航班信息
FlightEntity flightEntity = new FlightEntity();
flightEntity.setId(19);
flightEntity.setFlightId("setFlightId0");
flightEntity.setCompany("setCompany0");
flightEntity.setDepartureAirport("setDepartureAirport0");
flightEntity.setArriveAirport("setCompany0");
flightEntity.setDepartureTime(new Date());
flightEntity.setArriveTime(new Date());
flightEntity.setModel("setModel0");
flightEntity.setIsDelete(1);
int result = flightService.updateFlight(flightEntity);
System.out.println(result);
2.5删除数据
com/zhaoli/mapper/FlightMapper.java
/**
 * 逻辑删除 本质是将 is_delete 值用 update 语句改为 1
 */
int updateDeleteFlight(Integer id);
com/zhaoli/service/FlightService.java
/**
 * 逻辑删除 本质是将 is_delete 值用 update 语句改为 1
 */
public int updateDeleteFlight(Integer id) {
    int result = flightMapper.updateDeleteFlight(id);
    //update 需要手动提交事务
    sqlSession.commit();//提交事务
    return result;
}
mybatis/flightMapper.xml
<!--  逻辑删除航班信息  -->
<update id="updateDeleteFlight" parameterType="int">
    UPDATE dome02_flight SET is_delete=1 WHERE id=#{id};
</update>
com/zhaoli/test/Test01.java
//逻辑删除
int result = flightService.updateDeleteFlight(10);
System.out.println(result);
2.6 mybatis多条件查询
第一种方法 传递map 型;
 第二种方法:多个参数如果不封装成Map 参数值需要通过,多个参数的时候要使用 @Param 给指定参数,否则会出现找不到参数的错误
List<FlightEntity> getByIdFlightParameter(@Param("company") String company
@Param("departureAirport") String departureAirport,
@Param("arriveAirport") String arriveAirport);
第三种方法:传递pojo ; 非常多参数 sql语句中获取参数值名称 与对象成员属性名称需要保持一致(用的较多)
<select id="getByIdFlightPoJo" parameterType="com.zhaoli.entity.FlightEntity" 
resultMap="flightEntityMap">
         SELECT * from mayikt_flight where company=#{company}
and departure_airport=#{departureAirport} and arrive_airport=#{arriveAirport};
2.7 mybatis动态条件查询
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
● if
● choose (when, otherwise)
● trim (where, set)
● foreach
mysql 加上输出日志(会输出sql 语句)
 在 mybatis-config.xml 中加入
<settings>
    <!-- 打印sql日志 -->
    <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

 <if test="逻辑判断"></if>
<select id="getByIdFlightDynamicParameter"
		 parameterType="com.mayikt.entity.FlightEntity"  resultMap="flightEntityMap">
    SELECT * from mayikt_flight where
    <if test="company!=null and  company!=''">
        company=#{company}
    </if>
    <if test="departureAirport!=null and  departureAirport!=''">
        and departure_airport=#{departureAirport}
    </if>
    <if test="arriveAirport!=null and  arriveAirport!=''">
        and arrive_airport=#{arriveAirport};
    </if>
</select>
缺陷 如果没有传递company 导致sql报错 改进如下
  <select id="getByIdFlightDynamicParameter" parameterType="com.mayikt.entity.FlightEntity"
            resultMap="flightEntityMap">
    SELECT * from mayikt_flight where
    1=1
    <if test="company!=null and  company!=''">
       and  company=#{company}
    </if>
    <if test="departureAirport!=null and  departureAirport!=''">
        and departure_airport=#{departureAirport}
    </if>
    <if test="arriveAirport!=null and  arriveAirport!=''">
        and arrive_airport=#{arriveAirport};
    </if>
</select>
可以使用<where></where> 用的最多
<select id="getByIdFlightDynamicParameter"
		parameterType="com.mayikt.entity.FlightEntity"   resultMap="flightEntityMap">
    SELECT * from mayikt_flight
    <where>
        <if test="company!=null and  company!=''">
            and company=#{company}
        </if>
        <if test="departureAirport!=null and  departureAirport!=''">
            and departure_airport=#{departureAirport}
        </if>
        <if test="arriveAirport!=null and  arriveAirport!=''">
            and arrive_airport=#{arriveAirport};
        </if>
    </where>
</select>
3.MyBatis - 映射文件标签
3.1映射文件的顶级元素
| 顶级元素 | 描述 | 
|---|---|
| select | 映射查询语句。 | 
| insert | 映射插入语句。 | 
| update | 映射更新语句。 | 
| delete | 映射删除语句。 | 
| sql | 可以重用的 SQL 代码块。 | 
| resultMap | 用来描述如何从数据库结果集中加载对象,是最复杂且强大的元素。 | 
| cache | 配置给定命名空间的缓存。 | 
| cache-ref | 从其他命名空间引用缓存配置。 | 
3.2 select 标签的属性信息
<select
  <!-- 
    1. id(必须配置)
    id是命名空间中的唯一标识符,可被用来代表这条语句
    一个命名空间(namespace)对应一个dao接口
    这个id也应该对应dao里面的某个方法(sql相当于方法的实现),因此id应该与方法名一致
   -->
  id="selectUser"
  <!-- 
    2. parapeterType(可选配置,默认由mybatis自动选择处理)
    将要传入语句的参数的完全限定名或别名,如果不配置,mybatis会通过ParamterHandler根据参数类型默认选择合适的typeHandler进行处理
    paramterType 主要指定参数类型,可以是int, short, long, string等类型,也可以是复杂类型(如对象)
   -->
  parapeterType="int"
  <!-- 
    3. resultType(resultType 与 resultMap 二选一配置)
    用来指定返回类型,指定的类型可以是基本类型,也可以是java容器,也可以是javabean
   -->
  resultType="hashmap"
  
  <!-- 
    4. resultMap(resultType 与 resultMap 二选一配置)
    用于引用我们通过 resultMap 标签定义的映射类型,这也是mybatis组件高级复杂映射的关键
   -->
  resultMap="USER_RESULT_MAP"
  
  <!-- 
    5. flushCache(可选配置)
    将其设置为true,任何时候语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false
   -->
  flushCache="false"
  <!-- 
    6. useCache(可选配置)
    将其设置为true,会导致本条语句的结果被二级缓存,默认值:对select元素为true
   -->
  useCache="true"
  <!-- 
    7. timeout(可选配置)
    这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数,默认值为:unset(依赖驱动)
   -->
  timeout="10000"
  <!-- 
    8. fetchSize(可选配置)
    这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为:unset(依赖驱动)
   -->
  fetchSize="256"
  <!-- 
    9. statementType(可选配置)
    STATEMENT, PREPARED或CALLABLE的一种,这会让MyBatis使用选择Statement, PrearedStatement或CallableStatement,默认值:PREPARED
   -->
  statementType="PREPARED"
  <!-- 
    10. resultSetType(可选配置)
    FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为:unset(依赖驱动)
   -->
  resultSetType="FORWORD_ONLY"
></select>
3.3 resultMap 标签的属性信息
<!-- 
  1. type 对应的返回类型,可以是javabean, 也可以是其它
  2. id 必须唯一, 用于标示这个resultMap的唯一性,在使用resultMap的时候,就是通过id引用
  3. extends 继承其他resultMap标签
 -->
<resultMap type="" id="" extends="">  
  <!-- 
    1. id 唯一性,注意啦,这个id用于标示这个javabean对象的唯一性, 不一定会是数据库的主键(不要把它理解为数据库对应表的主键)
    2. property 属性对应javabean的属性名
    3. column 对应数据库表的列名
       (这样,当javabean的属性与数据库对应表的列名不一致的时候,就能通过指定这个保持正常映射了)
   -->
  <id property="" column=""/>
        
  <!-- 
    result 与id相比,对应普通属性
   -->    
  <result property="" column=""/>
        
  <!-- 
    constructor 对应javabean中的构造方法
   -->
  <constructor>
    <!-- idArg 对应构造方法中的id参数 -->
       <idArg column=""/>
       <!-- arg 对应构造方法中的普通参数 -->
       <arg column=""/>
   </constructor>
   
   <!-- 
    collection 为关联关系,是实现一对多的关键 
    1. property 为javabean中容器对应字段名
    2. ofType 指定集合中元素的对象类型
    3. select 使用另一个查询封装的结果
    4. column 为数据库中的列名,与select配合使用
    -->
  <collection property="" column="" ofType="" select="">
    <!-- 
      当使用select属性时,无需下面的配置
     -->
    <id property="" column=""/>
    <result property="" column=""/>
  </collection>
        
  <!-- 
    association 为关联关系,是实现一对一的关键
    1. property 为javabean中容器对应字段名
    2. javaType 指定关联的类型,当使用select属性时,无需指定关联的类型
    3. select 使用另一个select查询封装的结果
    4. column 为数据库中的列名,与select配合使用
   -->
  <association property="" column="" javaType="" select="">
    <!-- 
      使用select属性时,无需下面的配置
     -->
    <id property="" column=""/>
    <result property="" column=""/>
  </association>
</resultMap>
3.4 insert 标签的属性信息
<insert
  <!--
    同 select 标签
   -->
  id="insertProject"
  <!-- 
    同 select 标签
   -->
  paramterType="projectInfo"
  
  <!-- 
    1. useGeneratedKeys(可选配置,与 keyProperty 相配合)
    设置为true,并将 keyProperty 属性设为数据库主键对应的实体对象的属性名称
   --> 
  useGeneratedKeys="true"
  <!-- 
    2. keyProperty(可选配置,与 useGeneratedKeys 相配合)
    用于获取数据库自动生成的主键
   -->
  keyProperty="projectId"
>
3.5重用 sql 标签和完全限定名使用别名替代
重用 sql 标签
 <sql id="userColumns">id,username,password</sql>
完全限定名使用别名替代
 每个 sql 映射文件的要元素中,都需要指定一个名称空间,用以确保每个映射语句的 id 属性不会重复。如<mapper namespace="com.mayikt.mapper.UserMapper">
 在 Java 代码中引用某个 sql 映射时,使用的亦是含有名称空间的全路径。如
 session.update("com.mayikt.mapper.UserMapper.udpateUser", user); 
4. 常见问题
常见问题1
 
 alt+enter 选择第一个
 
常见问题2
 Mapped Statements collection does not contain value for getByUsersAll
 没有找到该getByUsersAll 对应sql语句 没有将Mapped 交给mybatis扫描到
常见问题3
 Could not find resource mybatis/userMapper2.xml
 clean 清除 编译class
常见问题4
 Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for userMapper.getByUsers
 getByUsers 查找sql语句 发现 有两个?












![[产品管理-20]:NPDP新产品开发 - 18 - 产品设计与开发工具 - 初始设计与规格定义](https://i-blog.csdnimg.cn/direct/588c56c3f19f4f84b04f50d2ffcc0430.png)






