Mybatis学习教程②

本文档详细介绍了Mybatis的高级查询,包括ResutlMap属性、多条件查询和模糊查询。接着深入探讨了Mybatis映射文件,讲解了返回主键、动态SQL以及SQL片段。此外,还对Mybatis核心配置文件进行了剖析,涉及typeHandlers和plugins标签。最后,详细阐述了Mybatis的多表查询,涵盖了一对一、一对多和多对多关系的查询实现,以及嵌套查询的应用。
摘要由CSDN通过智能技术生成

复杂映射&配置文件深入

一 Mybatis高级查询

1.1 ResutlMap属性

  • 建立对象关系映射
* resultType
	如果实体的属性名与表中字段名一致,将查询结果自动封装到实体类中
* ResutlMap
	如果实体的属性名与表中字段名不一致,可以使用ResutlMap实现手动封装到实体类中

1) 编写UserMapper接口

package com.myProject.mapper;

import com.myProject.domain.User;

import java.util.List;

public interface UserMapper {
   
    /**
     * 根据id查询用户
     */
    public User findUserById(int id);

    /**
     * 查询所有用户
     * @return
     */
    public List<User> findAllResultMap();
}

2) 编写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="com.myProject.mapper.UserMapper">
    <!--根据id查询用户-->
    <select id="findUserById" parameterType="int" resultMap="userResultMap">
        select * from user where id = #{id}
    </select>

    <!--id:标签的唯一标识
        type: 封装后实体类型
    -->
    <resultMap id="userResultMap" type="com.myProject.domain.User">
        <!--手动配置映射关系-->
        <!--id: 用来配置主键-->
        <id property="id" column="id"></id>
        <!--result: 表中普通字段的封装-->
        <result property="usernameabc" column="username"></result>
        <result property="birthdayabc" column="birthday"></result>
        <result property="sexabc" column="sex"></result>
        <result property="addressabc" column="address"></result>
    </resultMap>

    <!--查询所有用户-->
    <!--resultMap:手动配置实体属性与表中字段的映射关系,完成手动封装-->
    <select id="findAllResultMap" resultMap="userResultMap">
        select * from user
    </select>
</mapper>

3)代码测试

package com.myProject.test;

import com.myProject.domain.User;
import com.myProject.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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MybatisTest {
   
    /**
     * mybatis的Dao层mapper代理方法测试
     */
    @Test
    public void test1() throws IOException {
   
        // 加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

        // 获得SqlSessionFactory工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        // 获得SqlSession会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.findUserById(1);
        System.out.println(user);

        // 释放资源
        sqlSession.close();
    }

    @Test
    public void test2() throws IOException {
   
        // 加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

        // 获得SqlSessionFactory工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        // 获得SqlSession会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.findAllResultMap();
        users.forEach(System.out::println);

        // 释放资源
        sqlSession.close();
    }
}

1.2 多条件查询(三种)

需求

  • 根据id和username查询user表

1)方式一

使用 #{arg0}-#{argn} 或者 #{param1}-#{paramn}获取参数

  • UserMapper接口
package com.myProject.mapper;

import com.myProject.domain.User;

import java.util.List;

public interface UserMapper {
   
    /**
     * 多条件查询:方式一
     */
    public List<User> findByIdAndUsername1(int id, String username);
}

  • 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="com.myProject.mapper.UserMapper">
    <!--id:标签的唯一标识
        type: 封装后实体类型
    -->
    <resultMap id="userResultMap" type="com.myProject.domain.User">
        <!--手动配置映射关系-->
        <!--id: 用来配置主键-->
        <id property="id" column="id"></id>
        <!--result: 表中普通字段的封装-->
        <result property="usernameabc" column="username"></result>
        <result property="birthdayabc" column="birthday"></result>
        <result property="sexabc" column="sex"></result>
        <result property="addressabc" column="address"></result>
    </resultMap>

    <!--多条件查询:方式一-->
    <select id="findByIdAndUsername1" resultMap="userResultMap">
        <!--使用arg作为参数传递,是从0开始-->
        <!--select * from user where id = #{arg0} and username = #{arg1}-->

        <!--使用param作为参数传递,是从1开始-->
        select * from user where id = #{param1} and username = #{param2}
    </select>
</mapper>
  • 测试
/**
* 多条件查询:方式一
*/
@Test
public void test() throws IOException {
   
    // 加载核心配置文件
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

    // 获得SqlSessionFactory工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

    // 获得SqlSession会话对象
    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> users = mapper.findByIdAndUsername1(1, "子慕");
    users.forEach(System.out::println);

    // 释放资源
    sqlSession.close();
}

2)方式二

使用注解,引入 @Param()注解获取参数

  • UserMapper接口
package com.myProject.mapper;

import com.myProject.domain.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper {
   
    /**
     * 多条件查询: 方式二
     *      @Param传入的参数要见名知意,所以要与findByIdAndUsername2()形式参数保持一致
     */
    public List<User> findByIdAndUsername2(@Param("id") int id, @Param("username") String username);
}
  • 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="com.myProject.mapper.UserMapper">
    <!--id:标签的唯一标识
        type: 封装后实体类型
    -->
    <resultMap id="userResultMap" type="com.myProject.domain.User">
        <!--手动配置映射关系-->
        <!--id: 用来配置主键-->
        <id property="id" column="id"></id>
        <!--result: 表中普通字段的封装-->
        <result property="usernameabc" column="username"></result>
        <result property="birthdayabc" column="birthday"></result>
        <result property="sexabc" column="sex"></result>
        <result property="addressabc" column="address"></result>
    </resultMap>

    <!--多条件查询:方式二-->
    <select id="findByIdAndUsername2" resultMap="userResultMap">
        select * from user where id = #{id} and username = #{username}
    </select>
</mapper>
  • 测试
/**
* 多条件查询:方式二
*/
@Test
public void test() throws IOException {
   
    // 加载核心配置文件
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

    // 获得SqlSessionFactory工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

    // 获得SqlSession会话对象
    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> users = mapper.findByIdAndUsername2(1, "子慕");
    users.forEach(System.out::println);

    // 释放资源
    sqlSession.close();
}

3)方式三(推荐)

使用pojo(实体)对象传递参数

  • UserMapper接口
package com.myProject.mapper;

import com.myProject.domain.User;

import java.util.List;

public interface UserMapper {
   
    /**
     * 多条件查询:方式三
     */
    public List<User> findByIdAndUsername3(User user);
}
  • 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="com.myProject.mapper.UserMapper">
    <!--id:标签的唯一标识
        type: 封装后实体类型
    -->
    <resultMap id="userResultMap" type="com.myProject.domain.User">
        <!--手动配置映射关系-->
        <!--id: 用来配置主键-->
        <id property="id" column="id"></id>
        <!--result: 表中普通字段的封装-->
        <result property="usernameabc" column="username"></result>
        <result property="birthdayabc" column="birthday"></result>
        <result property="sexabc" column="sex"></result>
        <result property="addressabc" column="address"></result>
    </resultMap>

    <!--多条件查询:方式三-->
    <select id="findByIdAndUsername3" resultMap="userResultMap" parameterType="com.myProject.domain.User">
        select * from user where id = #{id} and username = #{usernameabc}
    </select>
</mapper>
  • 测试
/**
* 多条件查询:方式三
*/
@Test
public void test() throws IOException {
   
    // 加载核心配置文件
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

    // 获得SqlSessionFactory工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

    // 获得SqlSession会话对象
    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = new User();
    user.setId(1);
    user.setUsernameabc("子慕");
    List<User> users = mapper.findByIdAndUsername3(user);
    users.forEach(System.out::println);

    // 释放资源
    sqlSession.close();
}

1.3 模糊查询

需求

1)方式一

  • UserMapper接口
package com.myProject.mapper;

import com.myProject.domain.User;

import java.util.List;

public interface UserMapper {
   
    /**
     * 模糊查询:方式一
     */
    public List<User> findByUsername(String username);
}
  • 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="com.myProject.mapper.UserMapper">
    <!--id:标签的唯一标识
        type: 封装后实体类型
    -->
    <resultMap id="userResultMap" type="com.myProject.domain.User">
        <!--手动配置映射关系-->
        <!--id: 用来配置主键-->
        <id property="id" column="id"></id>
        <!--result: 表中普通字段的封装-->
        <result property="usernameabc" column="username"></result>
        <result property="birthdayabc" column="birthday"></result>
        <result property="sexabc" column="sex"></result>
        <result property="addressabc" column="address"></result>
    </resultMap>

    <!--模糊查询:方式一-->
    <select id="findByUsername" resultMap="userResultMap" parameterType="string">
        <!--#{}:在mybatis中是占位符,引用参数值得时候会自动添加单引号
            #{}:如果只有一个参数时,参数可自定义,但要见名知意
        -->
        select * from user where username like #{username}
    </select>
</mapper>
  • 测试
package com.myProject.test;

import com.myProject.domain.User;
import com.myProject.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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MybatisTest {
   
    /**
     * 模糊查询:方式一
     */
    @Test
    public void test() throws IOException {
   
        // 加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

        // 获得SqlSessionFactory工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        // 获得SqlSession会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> users = mapper.findByUsername("自动提交%");
        users.forEach(System.out::println);

        // 释放资源
        sqlSession.close();
    }
}

2)方式二

  • UserMapper接口
package com.myProject.mapper;

import com.myProject.domain.User;

import java.util.List;

public interface UserMapper {
   
    /**
     * 模糊查询:方式二
     */
    public List<User> findByUsername2(String username);
}
  • 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="com.myProject.mapper.UserMapper">
    <!--id:标签的唯一标识
        type: 封装后实体类型
    -->
    <resultMap id="userResultMap" type="com.myProject.domain.User">
        <!--手动配置映射关系-->
        <!--id: 用来配置主键-->
        <id property="id" column="id"></id>
        <!--result: 表中普通字段的封装-->
        <result property="usernameabc" column="username"></result>
        <result property="birthdayabc" column="birthday"></result>
        <result property="sexabc" column="sex"></result>
        <result property="addressabc" column="address"></result>
    </resultMap>

    <!--模糊查询:方式二-->
    <select id="findByUsername2" resultMap="userResultMap" parameterType="string">
        <!--parameterType是基本数据类型或者String的时候,${}里面的值只能写value
            ${}:sql语句原样拼接,不会自动添加单引号
        -->
        select * from user where username like '${value}'
    </select>
</mapper>
  • 测试
package com.myProject.test;

import com.myProject.domain.User;
import com.myProject.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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MybatisTest {
   
    /**
     * 模糊查询:方式二
     */
    @Test
    public void test() throws IOException {
   
        // 加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

        // 获得SqlSessionFactory工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        // 获得SqlSession会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> users = mapper.findByUsername2("自动提交%");
        users.forEach(System.out::println);

        // 释放资源
        sqlSession.close();
    }
}

3) ${}#{}区别

  • #{}:表示一个占位符号
    • 通过 #{} 可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。
    • #{} 可以接收简单类型值或pojo属性值。
    • 如果parameterType传输单个简单类型值, #{} 括号中名称随便写。
  • ${}:表示拼接sql串
    • 通过 ${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,会出现sql注入问题。
    • ${}可以接收简单类型值或pojo属性值。
    • 如果parameterType传输单个简单类型值, ${}括号中只能是value。

二 Mybatis映射文件深入

2.1 返回主键

应用场景

  • 我们很多时候有这种需求,向数据库插入一条记录后,希望能立即拿到这条记录在数据库中的主键值。

2.1.1 useGeneratedKeys

  • UserMapper接口
package com.myProject.mapper;

import com.myProject.domain.User;

public interface UserMapper {
   
    /**
     * 添加用户同时获取主键:方式一
     */
    public void saveUser(User user);
}
  • 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="com.myProject.mapper.UserMapper">
    <!--添加用户同时获取主键:方式一-->
    <!--useGeneratedKeys: 声明返回主键
        keyProperty:把返回主键的值,封装到实体中的那个属性上
    -->
    <insert id="saveUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
        insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address})
    </insert>
</mapper>
  • 测试
package com.myProject.test;

import com.myProject.domain.User;
import com.myProject.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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

public class MybatisTest {
   
    /**
     * 添加用户同时返回主键:方式一
     */
    @Test
    public void test() throws IOException {
   
        // 加载核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

        // 获得SqlSessionFactory工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        // 获得SqlSession会话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 当前返回的其实就是基于UserMapper所产生的代理对象mapper;底层:JDK动态代理 实际类型:proxy
        UserMapper mapper = sqlSession
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值