Mybatis复习——day04_特殊SQL的执行and自定义映射resultMap

 

目录

1、特殊SQL的执行

1.1、模胡查询

1.2、批量删除

1.3、动态设置表名

1.4、添加功能获取自增主键

2、自定义映射resultMap

2.1、resultMap处理资源和属性的映射关系

2.2、多对一映射处理

2.2.1、级联方式处理映射关系

2.2.2、使用association处理映射关系

2.2.3、分步查询

2.3、一对多映射处理

2.3.1、collection

2.3.2、分步查询

 


1、特殊SQL的执行

1.1、模胡查询

    /**
     * 通过用户名模胡查询用户信息
     * @param mohu
     * @return
     */
    List<User> getUserByLike(@Param("mohu")String mohu);
<!--    List<User> getUserByLike(@Param("mohu")String mohu);-->
<!--            select * from t_user where username like '%${mohu}%';-->
<!--            select * from t_user where username like concat('%',#{mohu},'%');-->
    <select id="getUserByLike" resultType="user">
        select * from t_user where username like "%"#{mohu}"%";
    </select>

测试

    @Test
    public void testGetUserByLike(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        List<User> a = mapper.getUserByLike("a");
        System.out.println(a);
    }

测试结果

DEBUG 08-26 17:49:40,116==>  Preparing: select * from t_user where username like "%"?"%"; (BaseJdbcLogger.java:137) 
DEBUG 08-26 17:49:40,132==> Parameters: a(String) (BaseJdbcLogger.java:137) 
DEBUG 08-26 17:49:40,148<==      Total: 7 (BaseJdbcLogger.java:137) 
[User{id=2, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'}, 
User{id=5, username='a', password='111', age=11, gender='男', email='123466@qq.com'}, 
User{id=9, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'}, 
User{id=10, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'}, 
User{id=11, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'}, 
User{id=12, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'}, 
User{id=13, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'}]

1.2、批量删除

   /**
     * 批量删除
     * @param ids
     */
    void deleteMoreUser(@Param("ids") String ids);
<!--    void deleteMoreUser(@Param("ids") String ids);-->
    <delete id="deleteMoreUser">
        delete from t_user where id in(${ids});
    </delete>

测试

    @Test
    public void testDeleteMoreUser(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        mapper.deleteMoreUser("7,6");
    }

1.3、动态设置表名

    /**
     * 动态设置表名,查询用户信息
     * @param tableName
     * @return
     */
    List<User> getUserList(@Param("tableName") String tableName);
<!--    List<User> getUserList(@Param("tableName") String tableName);-->
    <select id="getUserList" resultType="user">
        select * from ${tableName};
    </select>

测试

    @Test
    public void testGetUserList(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        List<User> t_user = mapper.getUserList("t_user");
        t_user.forEach(new Consumer<User>() {
            @Override
            public void accept(User user) {
                System.out.println(user.toString());
            }
        });
    }

1.4、添加功能获取自增主键

场景模拟:

t_clazz(clazz_id,clazz_name)

t_student(student_id,student_name,clazz_id)

1、添加班级信息

2、获取新添加的班级的id

3、为班级分配学生,即将某学的班级id修改为新添加的班级的id

    /**
     * 添加用户信息并获取自增的主键
     * @param user
     */
    void insertUser(User user);
<!--    void insertUser(User user);-->
<!--
        useGeneratedKeys:表示当前添加功能使用自增的主键
        keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
-->
    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email});
    </insert>

测试

    @Test
    public void testInsertUser(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        User user = new User(null,"小红","123456",23,"男","23930@qq.com");
        mapper.insertUser(user);
        System.out.println(user);
    }
DEBUG 08-26 17:55:20,653==>  Preparing: insert into t_user values(null,?,?,?,?,?); (BaseJdbcLogger.java:137) 
DEBUG 08-26 17:55:20,668==> Parameters: 小红(String), 123456(String), 23(Integer), 男(String), 23930@qq.com(String) (BaseJdbcLogger.java:137) 
DEBUG 08-26 17:55:20,700<==    Updates: 1 (BaseJdbcLogger.java:137) 
User{id=19, username='小红', password='123456', age=23, gender='男', email='23930@qq.com'}

开始时,传入的User的id为空,在执行插入方法后,User的id会被赋值,从而得到自增的主键

2、自定义映射resultMap

前期准备:

t_dept表(部门表)

create table t_dept
(
    dept_id   int auto_increment primary key,
    dept_name varchar(20) null
);

t_emp表(员工表,部门对员工,一对多,一个部门对应多个员工)

create table t_emp
(
    emp_id   int auto_increment primary key,
    emp_name varchar(20) null,
    age      int         null,
    gender   char        null,
    dept_id  int         null
);

实体类

Dept类

public class Dept {

    private Integer deptId;

    private String deptName;

    private List<Emp> emps;

    public Dept() {
    }

    public Dept(Integer deptId, String deptName) {
        this.deptId = deptId;
        this.deptName = deptName;
    }

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public List<Emp> getEmps() {
        return emps;
    }

    public void setEmps(List<Emp> emps) {
        this.emps = emps;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                ", emps=" + emps +
                '}';
    }
}

Emp类

public class Emp {

    private Integer empId;

    private String empName;

    private Integer age;

    private String gender;

    private Dept  dept;

    public Emp() {
    }

    public Emp(Integer empId, String empName, Integer age, String gender) {
        this.empId = empId;
        this.empName = empName;
        this.age = age;
        this.gender = gender;
    }

    public Emp(Integer empId, String empName, Integer age, String gender, Dept dept) {
        this.empId = empId;
        this.empName = empName;
        this.age = age;
        this.gender = gender;
        this.dept = dept;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", dept=" + dept +
                '}';
    }
}

SqlSessionUtil工具类

public class SqlSessionUtil {
    public static SqlSession getSqlSession(){
        SqlSession sqlSession =null;
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
            sqlSession = sqlSessionFactory.openSession(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sqlSession;
    }
}

2.1、resultMap处理资源和属性的映射关系

字段名和属性名不一致的情况,如何处理映射关系
        1、为查询的字段设置别名,和属性名保持一致
        2、当字段符合MySql的要求使用,而属性符合java的要求使用驼峰
        此时可以在MyBatis的核心配置文件中设置一个全局配置mapUnderscoreToCamelCase,可以自动将下划线映射为驼峰。例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为 userName

<settings>
    <!--    将下划线映射为驼峰-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>


        3.使用resultMap自定义映射处理
            resultMap:设置自定义的映射关系
                id:唯一标识
                type:处理映射关系的实体类的类型
                    常用标签
                        id:处理主键和实体类中属性的映射关系
                        result:处理普通字段和实体类中的属性的映射关系
                        association:处理多对一的映射关系(处理实体类类型的属性)
                        column:设置映射关系中的字段名,必须是sql查询出的某个字段
                        property:设置映射关系中的属性的属性名,必须是处理实体类类型中的属性名

   /**
     * 根据id查询员工信息
     * @param empId
     * @return
     */
    Emp getEmpById(@Param("empId") Integer empId);
   <resultMap id="empResultMap" type="Emp">
        <id column="emp_id" property="empId"/>
        <result column="emp_name" property="empName"/>
        <result column="age" property="age"/>
        <result column="gender" property="gender"/>
    </resultMap>
<!--    Emp getEmpById(@Param("empId") Integer empId);-->
    <select id="getEmpById" resultMap="empResultMap">
        select * from t_emp where emp_id = #{empId};
    </select>

2.2、多对一映射处理

场景模拟:

查询员工信息以及员工所对应的部门信息

2.2.1、级联方式处理映射关系

    /**
     * 查询员工信息以及员工所对应的部门信息
     * @param empId
     * @return
     */
    Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);
    <resultMap id="empAndDeptResultMapOne" type="Emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <result column="dept_id" property="dept.deptId"></result>
        <result column="dept_name" property="dept.deptName"></result>
    </resultMap>

<!--    Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
    <select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMapOne">
        select
            t_emp.*,t_dept.*
        from
             t_emp
                 left join
                 t_dept
                     on t_emp.dept_id = t_dept.dept_id
        where t_emp.emp_id = #{empId};
        
    </select>

2.2.2、使用association处理映射关系

    /**
     * 查询员工信息以及员工所对应的部门信息
     * @param empId
     * @return
     */
    Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);
    <resultMap id="empAndDeptResultMap" type="emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <!--
            association:处理多对一的映射关系(处理实体类类型的属性)
            property:设置需要处理映射关系的属性的属性名
            javaType:设置要处理的属性的类型
        -->
        <association property="dept" javaType="Dept">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
        </association>
    </resultMap>

<!--    Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
    <select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
        select
            t_emp.*,t_dept.*
        from
             t_emp
                 left join
                 t_dept
                     on t_emp.dept_id = t_dept.dept_id
        where t_emp.emp_id = #{empId};
        
    </select>

2.2.3、分步查询

1、查询与员工信息

   /**
     * 查询员工以及对应的部门信息的第一步
     * @param empId
     * @return
     */
    Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);
<!--    Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
    
    <resultMap id="empAndDeptByStepResultMap" type="Emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
            <!--
            property:设置需要处理映射关系的属性的属性名
            select:设置分步查询的sql的唯一标识
            column:将查询出的某个字段作为分步查询的sql的条件
            fetchType:在开启了延迟加载的环境中,通过该属性设置当前的分步查询是否使用延迟加载
                fetchType="eager(立即加载)| lazy(延迟加载)"
            -->
        <association property="dept" fetchType="eager"
                     select="com.itwpf.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                     column="dept_id">
        </association>
    </resultMap>
    <select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
        select * from t_emp where emp_id = #{empId};
    </select>

2.根据员工信息所对应的部门id查询部门信息

    /**
     * 查询员工以及对应的部门信息的第二步
     * @return
     */
    Dept getEmpAndDeptByStepTwo(@Param("deptId")Integer deptId);
    <!--    Dept getEmpAndDeptByStepTwo(@Param("deptId")Integer deptId);-->
    <select id="getEmpAndDeptByStepTwo" resultType="dept">
        select * from t_dept where dept_id = #{deptId};
    </select>

2.3、一对多映射处理

2.3.1、collection

    /**
     * 查询部门以及部门的员工信息
     * @param deptId
     * @return
     */
    Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);
    <resultMap id="getDeptAndEmpResultMap" type="dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
        <collection property="emps" ofType="emp">
<!--            ofType:设置集合类型属性中存储的数据的类型-->
            <id column="emp_id" property="empId"/>
            <result column="emp_name" property="empName"/>
            <result column="age" property="age"/>
            <result column="gender" property="gender"/>
        </collection>
    </resultMap>
<!--    Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);-->
    <select id="getDeptAndEmpByDeptId" resultMap="getDeptAndEmpResultMap">
        select t_dept.*,t_emp.*
        from t_dept
        left join t_emp
        on t_dept.dept_id = t_emp.dept_id
        where t_dept.dept_id = #{deptId};
    </select>

2.3.2、分步查询

1、查询部门信息

    /**
     * 通过分步查询部门以及部门中员工信息的第一步
     * @param deptId
     * @return
     */
    Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);
    <resultMap id="deptAndEmpResultMapByStep" type="dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
        <collection property="emps"
                    select="com.itwpf.mapper.EmpMapper.getDeptAndEmpByStepTwo"
                    column="dept_id"/>
    </resultMap>
<!--    Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);-->
    <select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpResultMapByStep">
        select *
        from t_dept
        where dept_id = #{deptId};
    </select>

2.根据部门id查询部门中的所有员工

    /**
     *通过分步查询部门以及部门中员工信息的第二步
     * @param deptId
     * @return
     */
    List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);
<!--    List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);-->
    <select id="getDeptAndEmpByStepTwo" resultType="emp">
        select * from t_emp where dept_id = #{deptId};
    </select>

分步查询的优点:可以实现延迟加载 但是必须在核心配置文件中设置全局配置信息:

<settings>
        <!--    开启延时加载    -->
        <setting name="lazyLoadingEnabled" value="true"/>

        <!--        按需加载 如果为true,不管有没有开启延时加载,都会执行全部sql-->
<!--        <setting name="aggressiveLazyLoading" value="false"/>-->
</settings>
    

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载

aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属 性会按需加载 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。

此时可通过association和 collection中的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType="lazy(延迟加 载)|eager(立即加载)"

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值