mybatis_1基础知识点梳理

一级目录

二级目录

三级目录

目标

  • 能够了解什么是框架
  • 掌握Mybatis框架开发快速入门
  • 掌握Mybatis框架的基本CRUD操作
  • 掌握SqlMapConfig.xml配置文件
  • 掌握Mybatis的parameterType的配置
  • 掌握Mybatis的resultType的配置
  • 了解Mybatis连接池与事务操作
  • 掌握Mybatis动态SQL
1 jdbc 问题分析
  1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
  2. Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大, sql 变动需要改变java 代码。
  3. 使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。
  4. 对结果集解析存在硬编码(查询列名), sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成 pojo 对象解析比较方便
2 MyBatis框架概述

​ mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。

​ mybatis 通过xml 或注解的方式将要执行的各种statement 配置起来,并通过java 对象和statement 中sql的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql并将结果映射为 java 对象并返回。

​ 采用 ORM 思想解决了实体和数据库映射的问题,对jdbc 进行了封装,屏蔽了jdbc api 底层访问细节,使我们不用与 jdbc api打交道,就可以完成对数据库的持久化操作。

​ 官网: http://www.mybatis.org/mybatis-3/

小结

  1. MyBatis: 持久层的一个框架, 封装了JDBC. 操作数据库
  2. 为什么要学习MyBatis?
    • JDBC和DBUtils都有一些很明显的缺点, JDBC和DBUtils不适合做项目
    • MyBatis是工作里面的主流的持久层框架, 使用几率特别大

1.需求

  • 使用MyBatis查询所有的用户, 封装到List集合

2.分析

  1. 创建Maven工程(jar), 添加坐标
  2. 创建pojo
  3. 创建UserDao接口
  4. 创建UserDao映射文件
  5. 创建MyBatis核心配置文件SqlMapConfig.xml
  6. 编写java代码测试
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <!--引入lombok的依赖-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.10</version>
      <scope>provided</scope>
    </dependency>
    <!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
    <!--mybatis的依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.3</version>
    </dependency>
  </dependencies>
1.2 创建 UserDao 接口
  • UserDao 接口就是我们的持久层接口(也可以写成 UserMapper) .我们就写成UserDao ,具体代码如下:
public interface UserDao {
    public List<User> findAll();
}
1.3 创建 UserDao.xml 映射文件

注意:

  1. 映射配置文件存储的路径在resources里面,要和对应的Dao接口的路径保持一致
  2. 映射配置文件的文件名必须和Dao接口名保持一致
  3. 一定要引入约束文件
    mapper.xml格式如下
    1.mapper文件的文件名和dao的名字一样,存放在resources下面的时候前文件名最好一致。mapper也可直接在src下面存放,和dao文件存放挨着,但不建议那样子做。2.resources下面是文件夹的形式,是以/为开始的,不是以.
<?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,一个映射配置文件,就对应一个dao接口
    根标签的namespace属性的值就对应dao接口的全限定名
-->
<mapper namespace="com.weijisheng.dao.UserDao">

    <!--
        根标签的每一个子标签就对应dao接口的每一个方法:
            select标签就对应查询方法

        标签的id的值对应方法的名字
        标签的resultType的值就对应封装结果的类型,如果封装结果的类型是List就对应其泛型的类型
        标签体的内容就是要执行的SQL语句
    -->
    <select id="findAll" resultType="com.weijisheng.dao.UserDao">
        select * from t_user
    </select>
</mapper>

#####1.4.创建 SqlMapConfig.xml 配置文件(核心配置文件)
注意事项

  1. 存放路径必须是resources的根路径
  2. 配置文件的名字,随便写
  3. 一定要引入约束文件
<?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
-->
<configuration>
    <!--
        配置数据库的环境信息:
        environments: 表示里面可以配置多个环境,default表示使用哪个环境
            environment: 每一个environment表示一种环境
        为什么要配置多个环境: 因为我们有多个环境(开发环境、生产环境(真正项目之后运行的环境)、测试环境)
    -->
    <environments default="dev">
        <!--开发环境-->
        <environment id="dev">
            <!--
                事务管理者,type为JDBC表示使用JDBC的事务管理者(了解)
            -->
            <transactionManager type="JDBC"></transactionManager>
            <!--
                dataSource表示数据源,1. POOLED表示使用自带连接池  2. UNPOOLED表示不使用连接池  3. JNDI表示使用JNDI的连接池
            -->
            <dataSource type="POOLED">
                <!--连接池的配置信息-->
                <property name="username" value="root"/>
                <property name="password" value=""/>
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value=""/>
            </dataSource>
        </environment>
        <!--生产环境-->
        <environment id="pro">
            <transactionManager type=""></transactionManager>
            <dataSource type=""></dataSource>
        </environment>
        <!--测试环境-->
        <environment id="test">
            <transactionManager type=""></transactionManager>
            <dataSource type=""></dataSource>
        </environment>
    </environments>

    <!--
        指定加载哪些映射配置文件: mappers
            mapper标签: 每一个mapper标签负责加载一个映射配置文件;resource指定要加载的映射配置文件的路径
    -->
    <mappers>
        <mapper resource="com/weijisheng/dao/UserDao.xml"></mapper>
    </mappers>
</configuration>
1.5测试
package com.weijisheng;

import com.weijisheng.dao.UserDao;
import com.weijisheng.pojo.User;
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 org.junit.Test;

import java.io.IOException;
import java.util.List;
import java.io.InputStream;
public class TestMybatis {
  public class TestMybatis {
    @Test
    public void testFindAll() throws Exception {
        //1. 让mybatis框架去加载主配置文件
        //1.1 将主配置文件SqlMapConfig.xml转换成字节输入流
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //1.2 创建一个SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        //1.3 使用factoryBuilder对象加载字节输入流,创建SqlSessionFactory对象
        SqlSessionFactory sessionFactory = factoryBuilder.build(is); //使用了构建者模式
        //1.4 使用sessionFactory对象创建出sqlSession对象
        SqlSession sqlSession = sessionFactory.openSession(); //使用了工厂模式

        //2. 使用sqlSession对象创建出UserDao接口的代理对象
        UserDao userDao = sqlSession.getMapper(UserDao.class); //使用了动态代理

        //3. 调用userDao代理对象的findAll()方法进行查询
        List<User> userList = userDao.findAll();
        for (User user : userList) {
            System.out.println(user);
        }

        //4. 关闭资源
        sqlSession.close();
        is.close();
}

小结

步骤

​ 1. 创建maven工程(javase)

2. 引入依赖:mysql、mybatis、Junit、lombok
3. 创建POJO类、创建Dao接口
4. 创建Dao接口对应的映射配置文件
      	1. 路径要在resources里面和Dao接口的路径一致,而且在resources目录中创建目录的时候要使用"/"而不是"."
      	2. 映射配置文件的文件名要和对应的Dao接口的名字一致
5. 创建mybatis的核心配置文件
6. 编写mybatis的测试代码进行测试 

properties(引入外部properties文件)

settings(全局配置参数)

typeAliases(类型别名)

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

​ environment(环境子属性对象)

​ transactionManager(事务管理)

​ dataSource(数据源)

mappers(映射器)

3.2.properties
  • jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=
jdbc.user=root
jdbc.password=
  • 引入到核心配置文件
<configuration>
   <properties resource="jdbc.properties">
    </properties>
    <!--数据源配置-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="UNPOOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    ....
</configuration>
3.3.typeAliases(类型别名)
3.3.1定义单个别名
  • 核心配置文件
<typeAliases>
      <typeAlias type="com.weijisheng.bean.User" alias="user"></typeAlias>
 </typeAliases>
  • 修改UserDao.xml
<select id="findAll" resultType="user">
    SELECT  * FROM  user
</select>
3.3.2批量定义别名

使用package定义的别名:就是pojo的类名,大小写都可以

  • 核心配置文件
<typeAliases>
    <package name="com.weijisheng.bean"/>
</typeAliases>
  • 修改UserDao.xml
<select id="findAll" resultType="user">
         SELECT  * FROM  user
</select>
3.4.Mapper
3.4.1方式一:引入映射文件路径
<mappers>
     <mapper resource="com/weijisheng/dao/UserDao.xml"/>
 </mappers>
3.4.2方式二:扫描接口
  • 配置单个接口
<mappers>
 	<mapper class="com.weijisheng.dao.UserDao"></mapper>
</mappers>
  • 批量配置
<mappers>
   <package name="com.weijisheng.dao"></package>
</mappers>

4.小结

  1. 核心配置文件的顺序

  2. properties 引入properties文件的

    • 创建properties文件
    • 使用 <properties resource="文件的路径"/>
    • 使用 ${key}
  3. typeAliases(类型别名) 在Dao映射文件里面 直接写类(pojo)的名字, 不需要写类全限定名了

<typeAliases>
    <package name="com.weijisheng.bean"/>
</typeAliases>
  1. Mapper 引入Dao映射文件的
<mappers>
   <package name="com.weijisheng.dao"></package>
</mappers>

MyBatis进阶

知识点-日志的使用(会用)

1.目标

​ 我们在使用MyBatis的时候, 其实MyBatis框架会打印一些必要的日志信息, 在开发阶段这些日志信息对我们分析问题,理解代码的执行是特别有帮助的; 包括项目上线之后,我们也可以收集项目的错误日志到文件里面去; 所有我们采用专门的日志系统来处理.

2.步骤

  1. 导入坐标
  2. 拷贝日志配置文件到项目

3.讲解

  • 导入坐标
<!-- log start -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.6.6</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.6</version>
</dependency>
<!-- log end -->
  • 拷贝log4j.properties到resources目录
log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#[%-5p] %t %l %d %rms:%m%n
#%d{yyyy-MM-dd HH:mm:ss,SSS\} %-5p [%t] {%c}-%m%n
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %t %l %d %rms:%m%n
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=D:\\idea_project\\wei_mm_backend.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS\} %-5p [%t] {%c}-%m%n

级别:error > warn > info>debug>trace

mybatis之增删改查

注意:除了select均没有resultType
目录结构
在这里插入图片描述

1.增加联系人

  • UserDao中添加新增方法
public interface UserDao {
    /**
     * 添加用户
     * @param user 要添加进数据库的数据
     * @return 受到影响的行数
     */
    int addUser(User user);
}
  • 在 UserDao.xml 文件中加入新增配置
    <insert id="insertUser" parameterType="User">
        insert into t_user (username,sex,birthday,address) values (#{username},#{sex},#{birthday},#{address})
    </insert>

	<!--我们可以发现, 这个 sql 语句中使用#{}字符, #{}代表占位符,我们可以理解是原来 jdbc 部分所学的?,它们都是代表占位符, 具体的值是由 User 类的 username 属性来决定的。
	parameterType 属性:代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的
全名称。-->
  • 添加测试类中的测试方法
public class TestMybatis {

    private UserDao userDao;
    private SqlSession sqlSession;
    private InputStream is;

    @Before
    public void init() throws Exception {
        //1. 让mybatis框架去加载主配置文件
        //1.1 将主配置文件SqlMapConfig.xml转换成字节输入流
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //1.2 创建一个SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        //1.3 使用factoryBuilder对象加载字节输入流,创建SqlSessionFactory对象
        SqlSessionFactory sessionFactory = factoryBuilder.build(is); //使用了构建者模式
        //1.4 使用sessionFactory对象创建出sqlSession对象
        //使用了工厂模式
        sqlSession = sessionFactory.openSession();

        //2. 使用sqlSession对象创建出UserDao接口的代理对象
        //使用了动态代理
        userDao = sqlSession.getMapper(UserDao.class);
    }
 @Test
    public void testinsert() throws IOException, ParseException {
        String date="1997-04-02";
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = dateFormat.parse(date);
        User user = new User(null,"王菲","女",parse,"地球");
        int insertUser = mapper.insertUser(user);
        //重点获取uid,详情见如下mapper.xml文件
        System.out.println(user.getUid());
        System.out.println(insertUser);
    }
    @After
    public void destroy() throws IOException {
        //提交事务
        sqlSession.commit();

        //4. 关闭资源
        sqlSession.close();
        is.close();
    }
}

2 新增用户 id 的返回值

​ 新增用户后, 同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长 auto_increment 的值返回。

  • SelectKey获取主键
属性描述
keyPropertyselectKey 语句结果应该被设置的目标属性。
resultType结果的类型。MyBatis 通常可以算出来,但是写上也没有问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。
order这可以被设置为 BEFORE 或 AFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素-这和如 Oracle 数据库相似,可以在插入语句中嵌入序列调用。

UserDao.xml

	<!--
        resultType只有select标签才有

        我们需要在标签体的SQL语句中,获取pojo类型的参数的属性: #{属性名}


        selectKey标签: 查询主键
            keyColumn 表示要查询的列名
            keyProperty 表示要赋值的属性名
            resultType 表示查询出来的结果的类型
            order 表示在前或者在后执行
        select last_insert_id() 查询最后一个自增长的id的值
    -->
<insert id="insertUser" parameterType="User">
    <selectKey resultType="int" order="AFTER" keyProperty="uid" keyColumn="uid">
        select last_insert_id()
    </selectKey>
    insert into t_user (username,sex,birthday,address) values (#{username},#{sex},#{birthday},#{address})
</insert>

3 模糊查询的写法

  • UserDao 中添加新增方法
/**
     * 根据用户名进行模糊查询
     */
    List<User> searchByUsername(String username);
  • 在 UserMapper.xml 文件中加入新增配置
 <select id="searchByUsername" resultType="User" parameterType="String">
          select * from t_user where username like "%"#{username}"%"
    </select>

concat是mybatis中连接字符串的,所以上述语句可以写成

select *from t_user where username like concat("%",#{username},"%");

还有一种是${}的,代码如下:

select * from t_user where username like '%${value}%'

#{}与${}的区别【面试】

  1. #{}一定不能写在引号里面,${}一定要写在引号里面
  2. 如果是pojo、map类型的参数,无论是#{}还是${}里面都是些属性名
  3. 如果是简单类型的参数,#{}里面可以写任意字符串,但是${}里面只能写value(以前的版本)
  4. 如果使用#{}引入参数的话,其实是先使用?占位符,然后再设置参数;而使用${}引入参数的话,是直接拼接SQL语句

mybatis工具类的封装

SqlSessionFactoryUtil.java

package com.weijisheng.util;

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;

public class SqlSessionFactoryUtil {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            //1 将主配置文件SqlMapConfig.xml转换成字节输入流
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2 创建一个SqlSessionFactoryBuilder
            SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
            //3 使用factoryBuilder对象加载字节输入流,创建SqlSessionFactory对象
            sqlSessionFactory = factoryBuilder.build(is); //使用了构建者模式
            System.out.println(sqlSessionFactory);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建SqlSession对象
     * @return
     */
    public static SqlSession openSqlSession(){
        System.out.println(sqlSessionFactory.openSession());
        return sqlSessionFactory.openSession();
    }

    /**
     * 提交事务并且关闭sqlSession
     * @param sqlSession
     */
    public static void commitAndClose(SqlSession sqlSession){
        sqlSession.commit();
        sqlSession.close();
    }

    /**
     * 回滚事务并且关闭sqlSession
     * @param sqlSession
     */
    public static void rollbackAndClose(SqlSession sqlSession){
        sqlSession.rollback();
        sqlSession.close();
    }
}

mybatis的映射配置文件的parameterType参数类型(important):

  1. 单个参数,方法就以简单类型传入即可,那么在映射配置文件中的parameterType的值就是这个简单类型的别名
    在SQL语句中引入简单类型的参数#{任意字符串}

  2. 多个参数:

  3. 传入多个简单类型的参数(不太提倡)我们需要通过Param注解给每个参数取名,那么在映射配置文件中就不写parameterType
    在SQL语句中引入参数#{Param注解的值}

  4. 将多个参数封装到一个POJO中,那么在映射配置文件中parameterType的值就是这个POJO的全限定名或者别名
    在SQL语句中引入参数#{POJO的属性名}或者’${POJO的属性名}’

  5. 将多个参数封装到一个Map中(要封装的参数没有对应的POJO),那么在映射配置文件中parameterType的值是map,
    在SQL语句中引入参数#{map的key}或者’${map的key}’

  6. 将多个参数封装到一个POJO的包装对象中
    什么是POJO的包装对象,也就是说POJO中的属性类型又是一个其他的POJO类型, 那么我们在映射配置文件中的parameterType的值就是包装类型的别名
    在SQL语句中引入参数#{属性名.属性名}
    第四个代码演示如下:
    QueryVo.java

package com.weijisheng.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author weijisheng
 * @create 2021-12-04 18:32
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class QueryVo {
    /**
     * 不需要最后一个属性做参数
     * @param currentPage
     * @param pageSize
     * @param queryCondition
     */
    public QueryVo(Long currentPage, Integer pageSize, User queryCondition) {
        this.currentPage = currentPage;
        this.pageSize = pageSize;
        this.queryCondition = queryCondition;
    }

    private Long currentPage;
    private Integer pageSize;
    /**
     * 查询条件,多个pojo
     */
    private User queryCondition;

    private Long offset;

    /**
     * 下面这个是为了limit的第一个参数,要跳过的。
     * @return
     */
    public Long getOffset() {
        return (currentPage - 1)*pageSize;
    }
}

UserDao.java

package com.weijisheng.dao;

import com.weijisheng.pojo.QueryVo;
import com.weijisheng.pojo.User;

import java.util.List;

/**
 * @author weijisheng
 * @create 2021-12-04 18:09
 */
public interface UserDao {
    List<User> findAll();

    /**
     * 传入pojo
     * @param queryVo
     * @return
     */
    List<User> findPage(QueryVo queryVo);
}

UserDao.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.weijisheng.dao.UserDao">
    <select id="findAll" resultType="User">
        select *from t_user;
    </select>
    <select id="findPage" parameterType="QueryVo" resultType="User">
      select *from t_user where sex=#{queryCondition.sex} and address=#{queryCondition.address}
      limit #{offset},#{pageSize}
     </select>
</mapper>

Test.java

 @Test
    public void findPage(){
        SqlSession sqlSession = SqlFactoryUtils.openSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User user = new User();
        user.setSex("女");
        user.setAddress("武汉");
        QueryVo queryVo = new QueryVo(1l, 3, user);
        List<User> page = mapper.findPage(queryVo);
        for (User u :
                page) {
            System.out.println(u);
        }
        SqlFactoryUtils.commitAndClose(sqlSession);
    }

mybatis的映射配置文件的参数结果类型的深入(important):

1. 输出简单类型

2. 输出pojo对象

3. 输出pojo列表

4. resultMap结果类型

3.1输出简单类型

查询的结果是单个数据, 映射配置文件中的resultType属性的值就是这个数据的类型

/**
  * 查询用户的总个数
  * @return
  */
Long findTotal();
<select id="findTotal" resultType="long">
    select count(*) from t_user
</select>
3.2输出pojo对象(一个pojo对象就对应一行数据)或者一个Map

查询的结果是一行数据:

  • 将这一行数据存储到POJO对象中, 映射配置文件的resultType的值就是POJO的全限定名或者别名,此时就要求查询结果的字段名和类型 要和POJO的属性名和类型一致
  • 将这一行数据存储到Map对象,映射配置文件的resultType的值就是map,那么此时查询结果中的字段名就是map的key,字段值就是map的value
/**
  * 根据id查询一条数据
  * @param id
  * @return
  */
User findById(int id);

/**
  * 根据用户名查询用户
  * @param username
  * @return
  */
Map findByUsername(String username);
<select id="findById" parameterType="int" resultType="User">
    select * from t_user where uid=#{id}
</select>

<select id="findByUsername" parameterType="string" resultType="map">
    select * from t_user where username=#{username}
</select>
3.3输出pojo列表(一个pojo列表就对应多行数据)或者Map的列表

查询的结果是多行数据:

  • 将多条数据存储到List中,映射配置文件的resultType的值就是POJO的别名

  • 将多条数据存储到List中,映射配置文件的resultType的值就是map

3.4 resultMap结果类型
   resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

   如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

	resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。 (详见第二段笔记)

​ 那我们今天就来看返回的列名与实体类的属性不一致时的情况. 下次再接着研究复杂的封装(多表查询) , 将查询到的t_user表的信息封装到UserInfo对象中

  • UserInfo.java
package com.weijisheng.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;


@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo implements Serializable {
    private Integer userId;
    private String username;
    private String userSex;
    private String userBirthday;
    private String userAddress;
}

  • UserDao.java
public interface UserDao {
    /**
     * 查询所有用户信息,封装到UserInfo对象
     * @return
     */
    List<UserInfo> findAllUserInfo();
}
  • UserDao.xml
<!--
        resultType属性会进行自动映射: 根据结果集的字段名和POJO的属性名的对应关系进行映射

        resultMap属性: 结果集映射(手动映射),我们要先使用resultMap标签编写一个手动映射规则,然后使用这个映射规则
    -->
<!--
        id就是这个映射规则的唯一标识
        type就是要进行手动映射的类型:UserInfo

        autoMapping="true" 表示能自动映射的就会进行自动映射,不能自动映射的属性,才进行手动映射
    -->
<resultMap id="userInfoMap" type="UserInfo" autoMapping="true">
    <!--
            id标签表示对主键进行映射
                column属性是要进行映射的主键的字段名(列名)
                property是要进行映射的POJO的属性名
        -->
    <id column="uid" property="userId"></id>
    <!--
            result标签就是对其它的非主键进行映射
        -->
    <result column="sex" property="userSex"></result>
    <result column="birthday" property="userBirthday"></result>
    <result column="address" property="userAddress"></result>
</resultMap>

<select id="findAllUserInfo" resultMap="userInfoMap">
    select * from t_user
</select>

小结

  1. 输出简单类型 直接写 java类型名 eg: int
  2. 输出pojo对象 直接写 pojo类型名 eg: User
  3. 输出pojo列表类型 写 列表里面的泛型的类型 eg: List 写User
  4. ResultMap
    • 解决查询出来的结果的列名和javaBean属性不一致的请求
    • 复杂的pojo复杂(明天讲)

Mybatis 映射文件的 SQL 深入 (important----->动态sql):

Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。

知识点-动态 SQL 之 if标签

1.目标

​ 我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。

​ 比如在 id 如果不为空时可以根据 id查询,如果 username 不为空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

2.讲解

  • UserDao.java
package com.weijisheng.dao;

import com.weijisheng.pojo.QueryVo;
import com.weijisheng.pojo.User;
import com.weijisheng.pojo.UserInfo;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**
 * @author weijisheng
 * @create 2021-12-04 18:09
 */
public interface UserDao {
    /**
     * 查询所有用户,根据动态sql片段
     * @return
     */
    List<User> findUsers();
    /**
     * 根据用户地址和性别查询
     * @param address
     * @param sex
     * @return
     */
    List<User> findUserListByAddressAndSex(@Param("addr") String address, @Param("sex") String sex);

    /**
     * 根据id批量删除,类似于购物车那种
     * @param ids
     */
    void deleteByIds(List<Integer> ids);
}

  • UserDao.xml
<!--
            加入一个判断,判断传入的address是否为空,使用if标签进行判断,该标签中的test属性就编写判断条件
        -->
  <select id="findUserListByAddress" parameterType="string" resultType="User">
        select * from t_user
        <!--
            加入一个判断,判断传入的address是否为空,使用if标签进行判断,该标签中的test属性就编写判断条件
        -->
        <if test="address != null">
            where address=#{address}
        </if>
    </select>

    <select id="findUserListByAddressAndSex" parameterType="User" resultType="User">
        select * from t_user
        where 1=1
        <if test="address != null">
            and address=#{address}
        </if>

        <if test="sex != null">
            and sex=#{sex}
        </if>
    </select>

知识点-动态 SQL 之where标签

1.目标

​ 为了简化上面 where 1=1 的条件拼装,我们可以采用标签来简化开发。

2.讲解

修改 UserDao.xml 映射文件如下:

注意: 可以自动处理第一个 and

<select id="findUserListByAddressAndSex" parameterType="User" resultType="User">
    <include refid="select_all"/>

    <!--
            where标签的作用:
                1. 可以在条件之前添加where关键字
                2. 可以去掉第一个条件前的and
        -->
    <where>
        <if test="address != null">
            and address=#{address}
        </if>

        <if test="sex != null">
            and sex=#{sex}
        </if>
    </where>
</select>

3.小结

  1. where标签用在自己写sql语句的时候 where关键字不好处理的情况,代替where ‘1’ = ‘1’
  2. 可以自动处理第一个 and , 建议全部加上and

知识点-动态标签之foreach标签

1.目标

  • 掌握foreach标签的使用
2.1需求
  • 批量删除: 根据id的集合删除所有元素
2.2 LinkManDao代码
/**
  * 批量删除
  * @param ids
  */
void deleteByIds(List<Integer> ids);
2.3 LinkManDao映射配置文件
<delete id="deleteByIds" parameterType="int">
    delete from t_user

    <!--
            将传入的集合中的数据遍历出来,放到()里面
            使用foreach标签遍历
                collection属性:要遍历的集合,如果要遍历的是一个List则写成list
                item属性: 遍历出来的每一个元素
                separator属性: 遍历出来的每一个元素之间的分隔符
                index属性: 遍历出来的每一个元素的索引
                open属性: 在遍历出来的第一个元素之前拼接字符串
                close属性: 在遍历出来的最后一个元素之后拼接字符串
        -->
    <foreach collection="list" item="id" separator="," open="where uid in(" close=")">
        #{id}
    </foreach>

</delete>

知识点-动态标签之Sql片段

1.目标

​ Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。我们先到 UserDao.xml 文件中使用标签,定义出公共部分.

2.讲解

  • 使用sql标签抽取
<!--
    使用sql标签将重复的sql语句部分封装起来

    在需要使用这个sql片段的地方,就用include标签引入就行了
 -->
<sql id="select_all">
    select uid,username,sex,address,birthday from t_user
</sql>
  • 使用include标签引入使用
<select id="findUserListByAddress" parameterType="string" resultType="User">
    <include refid="select_all"/>
    <!--
            加入一个判断,判断传入的address是否为空,使用if标签进行判断,该标签中的test属性就编写判断条件
        -->
    <if test="address != null">
        where address=#{address}
    </if>
</select>

<select id="findUserListByAddressAndSex" parameterType="User" resultType="User">
    <include refid="select_all"/>

    <!--
            where标签的作用:
                1. 可以在条件之前添加where关键字
                2. 可以去掉第一个条件前的and
        -->
    <where>
        <if test="address != null">
            and address=#{address}
        </if>

        <if test="sex != null">
            and sex=#{sex}
        </if>
    </where>
</select>

3.小结

  1. sql标签可以把公共的sql语句进行抽取, 再使用include标签引入. 好处:好维护, 提示效率
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值