MyBatis实现查询的操作

MyBatis实现查询的操作

这里引入了Idea插件 MyBatisX ,方便进行跳转生成操作

查询所有数据

接口

映射文件

image-20220814143641005

测试案例

]

这里查询结果有一个问题。

brandName金额companyName查询出来的结果为NUll。原因是实体类里属性命名为驼峰,数据库里是下划线。

解决方法为:

  1. 起别名(对不一样的列名起别名,让别名和实体类的属性名一样

    <!--    起别名-->
        <select id="selectAll" resultType="org.example.pojo.Brand">
            select id, brand_name as brandName, company_name as companyName, ordered, description, status
            from tb_brand
        </select>
    
  2. sql片段(定义一个片段,每次查询都引用这个片段)

    <!--    sql片段-->
    <sql id="brand_colume">
        id, brand_name as brandName, company_name as companyName, ordered, description, status
    </sql>
    
    <select id="selectAll" resultType="org.example.pojo.Brand">
        select
        <include refid="brand_colume"/>
        from tb_brand
    </select>
    
  3. ResultMap

    <resultMap id="brandResultMap" type="org.example.pojo.Brand">
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>
    
    <select id="selectAll" resultMap="brandResultMap">
        select *
        from tb_brand
    </select>
    

查询某一个的详情

整体流程与上面的一样

接口

/**
 * 通过id查询详情
 */
public Brand selectById(int id);

SQL映射

<select id="selectById" resultMap="brandResultMap">
    select *
    from tb_brand
    where id = #{id}
</select>

test

]

注意

参数占位符

  1. #{}:会将其替换为?,为了防止SQL注入

  2. ${}:拼sql。会存在SQL注入的问题

  3. 使用时机:

    • 参数传递的时候:#{}
    • 表名后者列名不固定的情况下:${} 会存在SQL注入问题

特殊字符

  1. 转义字符

  2. CDATA区

    <![CDATA[
    
    ]]>
    

条件查询

为了方便演示接口接收参数的格式,先去书写SQL映射

<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    where status = #{status}
      and company_name like #{companyName}
      and brand_name like #{brandName}
</select>

条件查询

参数接收

  1. 散装参数:如果方法中有多个参数,需要使用@Param(“SQl参数占位符名称”)
  2. 对象参数
  3. map集合参数

方式一 散装参数

/**
 * 条件查询 方式一
 */
List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);

==注意:==这里的参数 @Param(“参数”),要和sql映射文件里的参数一致 #{参数}

测试

    @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. 执行方法
        List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
        System.out.println(brands);
//        5. 释放资源
        sqlSession.close();
    }

这里处理参数是为了模糊查询,所以在字符串前后都加上"%",进行模糊查询

]

方式二 对象参数

注意对象的属性名称要和参数占位符名称一致

只需要修改接口

接口

/**
 * 条件查询 方式二
 */
List<Brand> selectByCondition(Brand brand);

测试

    @Test
    public void testSelectByCondition() throws IOException {
    
    
//        接收参数
        int status = 1;
        String companyName = "华为";
        String brandName = "华为";
//        处理参数
        companyName = "%" + companyName + "%";
        brandName = "%" + brandName + "%";
//        封装对象
        Brand brand=new Brand();
        brand.setStatus(status);
        brand.setCompanyName(companyName);
        brand.setBrandName(brandName);

//    1.获取SQLSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//        2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
//        3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//        4. 执行方法
        List<Brand> brands = brandMapper.selectByCondition(brand);
        System.out.println(brands);
//        5. 释放资源
        sqlSession.close();
    }

]

方式三 map集合参数

这里map键的名称要和sql映射文件里的参数一样

这里依然是只修改接口即可

接口

/**
 * 条件查询 方式三
 */
List<Brand> selectByCondition(Map map);

测试

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

image-20220815102529341

动态条件查询

SQL语句会随着用户的输入或外部条件的变化而变化,称为动态SQL

官方文档点击跳转

1 多条件动态查询

sql语句

这里先使用if标签,里面有一个test属性,test里写表达式

因为companyName和brandName是字符串类型,除了判断是空对象以外还要判断是否为空字符串

<!--    动态条件查询-->
<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand where
    <if test="status != null">
        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>
</select>

接口

/**
 * 条件查询 方式三
 */
List<Brand> selectByCondition(Map map);

测试

这个测试案例只输入了status和companyName。

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

成功查询

image-20220815110307373

但是这个方法存在一个bug

如果只查询companyName就会报错

因为它的sql语句就会变成 select * from tb_brand where and company_name like #{companyName}

这句SQL就多了一个and

解决办法

给if标签里的都加上and

然后在where后面使用一个恒等式 1=1

<select id="selectByCondition" resultMap="brandResultMap">
    select *
    from tb_brand
    where 1 = 1
    <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>
</select>

但是这样还是很麻烦,于是MyBatis提供了一个新的标签(使用较为普遍的方法

使用标签就可以省略自己书写恒等式

<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>

2 单条件动态查询

接口

/**
 * 单条件动态查询
 */
List<Brand> selectByConditionSingle(Brand brand);

sql映射

<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    where
    <choose>
        <when test="status != null">
            status = #{status}
        </when>
        <when test="companyName != null and companyName != ''">
            company_name like #{companyName}
        </when>
        <when test="brandName != null and brandName != ''">
            brand_name like #{brandName}
        </when>
    </choose>
</select>

这里的choose相当于 Switch

when 相当于 case

测试

    @Test
    public void testSelectByConditionSingle() throws IOException {
    
    
//        接收参数
        int status = 1;
        String companyName = "华为";
        String brandName = "华为";
//        处理参数
        companyName = "%" + companyName + "%";
        brandName = "%" + brandName + "%";
//        封装对象
        Brand brand = new Brand();
        brand.setStatus(status);
//        brand.setCompanyName(companyName);
//        brand.setBrandName(brandName);

//    1.获取SQLSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//        2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
//        3. 获取Mapper接口的代理对象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
//        4. 执行方法
        List<Brand> brands = brandMapper.selectByConditionSingle(brand);
        System.out.println(brands);
//        5. 释放资源
        sqlSession.close();
    }

]

这个查询还有一个bug,就是如果三个条件都是null就会报错

所以加上一个标签

里面使用恒等式1=1

<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    where
    <choose>
        <when test="status != null">
            status = #{status}
        </when>
        <when test="companyName != null and companyName != ''">
            company_name like #{companyName}
        </when>
        <when test="brandName != null and brandName != ''">
            brand_name like #{brandName}
        </when>
        <otherwise>
            1=1
        </otherwise>
    </choose>
</select>

还有一个方法,使用 标签 效果是一样的

<select id="selectByConditionSingle" resultMap="brandResultMap">
    select *
    from tb_brand
    <where>
        <choose>
            <when test="status != null">
                status = #{status}
            </when>
            <when test="companyName != null and companyName != ''">
                company_name like #{companyName}
            </when>
            <when test="brandName != null and brandName != ''">
                brand_name like #{brandName}
            </when>
        </choose>
    </where>
</select>

猜你喜欢

转载自blog.csdn.net/qq_45842943/article/details/126356794