【MyBatis精讲】从入门到精通的详细指南:简化Java持久层操作的艺术

news2024/11/15 18:17:40

文章目录

  • 【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的一种实现方式,简单来说就是将数据库中查询出的数据映射到对应的实体中。
数据库层框架

  1. com.zhaoli.servlet或者com.zhaoli.controller--------控制层 springmvc
  2. com.zhaoli.service—业务逻辑层
  3. com.zhaoli.dao----数据库访问层 hibernate或者mybatis、jpa
  4. 数据库连接相关配置
  5. 编写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创建步骤

  1. 引入mybatis相关依赖
  2. mybatis-config.xml(该配置文件名称是可以改) 存放就是我们数据库相关连接信息
  3. 定义mapper ----编写我们mybatis 相关 sql语句,每个表对应一个mapper
  4. 定义java对象–需要注意下类中的成员属性与数据库表中字段需要做映射,默认类中的成员属性数据库表中字段名称对应的。
  5. 使用 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代理开发模式

  1. mapper接口方式开发整合就必须是对应的mapper接口的全限定类名
  2. 接口中的方法与映射文件中的SQL语句的ID
  3. 需要在mybatis-config.xml 新增 加载该userMaaper
    <mappers>
        <mapper resource="mybatis/userMapper.xml"/>
    </mappers>
  1. 定义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();
}
  1. 相关代码
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&amp;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语句 发现 有两个?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2139260.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML标签优先级

HTML&#xff08;HyperText Markup Language&#xff09;标签的位置对于页面的结构、性能以及可维护性至关重要。合理安排标签的位置不仅有助于提高网页的加载速度&#xff0c;还能使得代码更加清晰易懂。以下是一些关于HTML标签放置的基本规则和建议&#xff1a; 1. 文档类型…

web安卓逆向之必学HTML基础知识

文章目录 HTML基础知识一、HTML的介绍1. HTML定义2. HTML 的作用1. 定义网页的结构2. 实现超文本链接3. 支持多媒体内容4. 提供表单交互5. 提高网页的可访问性和 SEO 3. 小结 二、html的基本结构1. HTML 基本结构2. HTML 基本结构的详细介绍3. 教学案例4. 补充知识5. 小结 三、…

【网络通信基础与实践第三讲】传输层协议概述包括UDP协议和TCP协议

一、进程间的通信 通信的两端应当是两个主机中的应用进程&#xff0c;也就是说&#xff0c;端到端的通信是应用进程之间的通信 运输层有一个很重要的功能就是复用和分用&#xff0c;复用是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据&#xff0c;分用是指接…

C++前后缀分解

相关知识点 C算法与数据结构 打开打包代码的方法兼述单元测试 这个算法很容易想到&#xff0c;学习了本文后&#xff0c;可以更快得想到。 前后缀分解 分治法的一种&#xff0c;将数组和字符串&#xff0c;拆分成前缀和后缀。字符串(数组&#xff09;的前缀是字符串的前i个元…

QT模型视图结构2

文章目录 Qt 模型视图结构——模型类(二)1.基本概念1.1.模型的基本结构1.2.模型索引1.3.行号和列号1.4.父项1.5.项的角色 Qt 模型视图结构——模型类(二) ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模型存储数据&#xff0c;视图组件显示模型中的数据&#…

ChatGPT提示词-中文版(awesome-chatgpt-prompts中文版)

原是Github上110.6K星的项目&#xff1a;GitHub - f/awesome-chatgpt-prompts: This repo includes ChatGPT prompt curation to use ChatGPT better. 我翻译成了中文需要自提 我用夸克网盘分享了「Chat GPT提示词.csv」&#xff0c;点击链接即可保存。打开「夸克APP」在线查看…

Windows11 WSL2的ubuntu 22.04中拉取镜像报错

问题描述 在windows11 WSL2的ubuntu 22.04中拉取镜像报错。错误为&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting header…

深度学习的关键数据结构——张量解释

参考英文文章: https://deeplizard.com/learn/video/Csa5R12jYRghttps://deeplizard.com/learn/video/Csa5R12jYRg 什么是张量&#xff08;Tensor&#xff09; 神经网络中的输入、输出和变换都是用张量表示的&#xff0c;因此&#xff0c;神经网络编程大量使用张量。张量的概念…

【资料分析】特殊考点——拉动增长、贡献率、容斥问题

拉动增长和增量贡献率 第X产业增加值 是一个整体名称&#xff0c;例如张狗剩这是一个整体的名字 增量贡献率 部分增量/ 整体增量&#xff0c;已知增量贡献率80.6%,对应的部分增量可以求得&#xff08;现期2632&#xff0c;增长率10.3%&#xff0c;可用假设分配&#xff09;&a…

【Linux 20】进程控制

文章目录 &#x1f308; 一、创建线程⭐ 1. 线程创建函数⭐ 3. 给线程传参⭐ 4. 创建多线程⭐ 5. 获取线程 ID &#x1f308; 二、终止线程⭐1. 使用 return 终止线程⭐ 2. 使用 pthread_exit 函数终止线程⭐ 3. 使用 pthread_cancel 函数终止线程 &#x1f308; 三、等待线程⭐…

如何查看串口被哪个程序占用?截止目前最方便的方法

痛点&#xff1a;串口因为某种原因被占用&#xff0c;如何找到罪魁祸首&#xff1f; 做开发的小伙伴们&#xff0c;经常会遇到这样的问题&#xff1a;串口因为某种原因被占用&#xff0c;导致无法通讯&#xff0c;但是又找不到被哪个程序占用。只有重启电脑&#xff0c;才能解…

Python计算机视觉 第10章-OpenCV

Python计算机视觉 第10章-OpenCV OpenCV 是一个C 库&#xff0c;用于&#xff08;实时&#xff09;处理计算视觉问题。实时处理计算机视觉的 C 库&#xff0c;最初由英特尔公司开发&#xff0c;现由 Willow Garage 维护。OpenCV 是在 BSD 许可下发布的开源库&#xff0c;这意味…

[产品管理-20]:NPDP新产品开发 - 18 - 产品设计与开发工具 - 初始设计与规格定义

目录 前言&#xff1a; 一、什么是初始设计规格 二、初始设计与规格定义的工具 2.1 用户 - 功能性设计 1、定义与目的 2、主要内容 3、重要性 4、注意事项 2.2 用户 - 可用性设计 1、定义与目的 2、主要原则 3、实施步骤 4、重要性 2.3 生产 - 可生产性设计 1、…

Linux FTP服务问题排查

一、问题描述 最近linux虚拟机重启之后发现&#xff0c;FTP服务总是不正常&#xff0c;工具无法连接。 二、排查及处理过程 1、检查ftp服务是否正常安装&#xff1a;yes rpm -qa|grep vsftpd 2、检查ftp服务是否正常启动&#xff1a; systemctl status vsftpd 启动vsftpd sys…

Lnux-gcc/g++使用

目录 1.gcc/g介绍 1.什么是 gcc / g 2.gcc/g指令格式 2. gcc / g 实现程序翻译的过程 1.预处理(进行宏替换) 2.编译(生成汇编&#xff09; 3.汇编&#xff08;生成机器可识别代码&#xff09; 4.连接&#xff08;生成可执行文件或库文件&#xff09; 1.gcc/g介绍 1.什么…

浪潮信息首推3秒智能控温!告别服务器开机噪音

在当前的数据中心运维实践中&#xff0c;运维人员在部署服务器时常被“飞机起飞”般的开机噪音所困扰。服务器刚刚接通电源&#xff0c;其内部元件尚处于预热待命状态&#xff0c;而风扇却已全速运转&#xff0c;这不仅加剧了噪音污染&#xff0c;还拖慢了启动速度&#xff0c;…

电子电气架构 --- 基于ISO 26262的车载电子软件开发流程

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

kettle从入门到精通 第八十五课 ETL之kettle kettle中javascript步骤调用外部javascript/js文件

场景&#xff1a;交流学习群里面有小伙伴咨询kettle中的javascript代码步骤如何调用外部js文件中的函数&#xff0c;觉得有点意思的&#xff0c;于是就抽时间整理了一下。 1、外部js文件为test.js&#xff0c;代码如下&#xff1a; function test(param){return "接收到了…

2024CSP-J初赛全真模拟卷选择题篇(原创,难度偏简单)

注意&#xff0c;本卷由再临TSC原创&#xff0c;禁止转载&#xff01; 本卷难度偏简单&#xff0c;若想要通过初赛本卷应拿80分左右 查看答案的方法&#xff1a; if(设备"PC") { 把光标移到答案上面&#xff0c;选中答案&#xff0c;就会显示()&#xff1b; } …

计算机的错误计算(九十四)

摘要 探讨 的计算精度问题。 正如其它许多函数或运算一样&#xff0c;以2为底的对数运算&#xff0c;也包含在 IEEE 754-2019 的列表中[1]。 例1. 已知 计算 不妨用Go代码计算&#xff1a; package mainimport ("fmt""math" )func main() {x : 0.…