MyBatis学习笔记【四】

MyBatis高级特性详解:映射、参数处理、类型别名与延迟加载

映射文件中的查询语句中一定要写返回类型,那么resultType和resultMap有什么区别?

前面学习中,我们知道POJO类中的属性名一定要与数据库表中的字段名一致(一对一进行映射),那么如果不一致时,则可以使用resultMap

MyBatis多个参数输入

案例:根据用户名和密码找到用户

首先我们想到的是@param注解,底层map映射是以注解的值为键参数为值

@Select("select * from user where name=#{name} and pwd=#{pwd}")
    User getUser(@Param("name") String name,@Param("pwd") String pwd);

如果不使用注解,直接输入参数的话

@Select("select * from user where name=#{name} and pwd=#{pwd}")
    User getUser(String name,String pwd);

 结果报错,提示说name找不到,可以使用arg和param解决

@Select("select * from user where name=#{arg0} and pwd=#{arg1}")
    User getUser(String name,String pwd);

@Select("select * from user where name=#{param1} and pwd=#{param2}")
    User getUser(String name,String pwd);

最终结果都输出成功,那么arg0、param1和arg1、param2分别代表的就是参数一和参数二,当然也可以组合一起使用

MyBatis常用的类型都设置了类型别名

例如:java.lang.Integer —— int || integer

   int —— _int || _integer

      Map——map

      List ——list

MyBatis批量删除

Sql语句:delete from user where id in (1,2,3);

所以xml的sql语句应该使用${}传参(不会自动加单引号)

MyBatis获取添加功能自增的主键

@Test
    public void addUser(){
        User user = new User(null,"name","123132");
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.addUser(user);
        sqlSession.commit();
        System.out.println(user);
    }

 

UseGeneratedKeys即是否返回主键,keyProperty表示主键返回到属性上,上述例子中,创建的user对象id为null,但是最后输出id为7,是因为keyProperty将主键值赋给了User的id.

MyBatis驼峰命名映射

一般在数据库中字段名使用‘_’连接

但是实体类使用的是驼峰命名,这样查询的结果无法映射进实体类中

针对以上问题,可以在MyBatis的配置文件中设置setting标签将驼峰转化设为true,默认为false

<settings>

<setting name=mapUnderscoreToCamelCase value=true/>

</settings>

而在SpringBoot项目中没有其配置文件,在application.properties中加入:

Mybatis.configuration.mapUnderscoreToCamelCase=true

通过resultMap解决字段名和属性名的映射

resultMap

<resultMap id="teacherMap" type="com.wang.pojo.Teacher">
        <id property="id" column="id"></id>
        <result property="TName" column="t_name"></result>
        <result property="schoolId" column="schoolId"></result>
</resultMap>

resultMap中,id标签代表主键,result代表其他的

property属性即实体类的属性,column即数据库字段

多对一关系映射

例子:学校表和老师表,老师表和学校表进行左连接,按照学校唯一标识ID查找老师的信息

 那么我们可以在老师实体类中加入,学校类属性

select teacher.id,t_name,schoolId,school.id as s_id,s_name from teacher left join school on teacher.schoolId = school.id where school.id=#{id};

要注意的是两表的主键都为id,where后面的id写明具体表的id,否则报错,得到的字段取别名以便分辨(学校id为s_id)

public class Teacher {
    private Integer id;
    private String TName;
    private Integer SchoolId;
    private School school;

    public School getSchool() {
        return school;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", TName='" + TName + '\'' +
                ", SchoolId=" + SchoolId +
                ", school=" + school +
                '}';
    }

    public Integer getSchoolId() {
        return SchoolId;
    }

    public void setSchoolId(Integer schoolId) {
        SchoolId = schoolId;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTName() {
        return TName;
    }

    public void setTName(String TName) {
        this.TName = TName;
    }
}

 方法一:级联属性赋值

    <resultMap id="teacherSchoolMap" type="com.wang.pojo.Teacher">
        <id property="id" column="id"></id>
        <result property="TName" column="t_name"></result>
        <result property="schoolId" column="schoolId"></result>
        <result property="school.id" column="s_id"></result>
        <result property="school.sName" column="s_name"></result>
    </resultMap>

老师实体类的学校类属性的具体属性和表名一一对应

方法二:associate

    <resultMap id="teacherSchoolMap2" type="com.wang.pojo.Teacher">
        <id property="id" column="id"></id>
        <result property="TName" column="t_name"></result>
        <result property="schoolId" column="schoolId"></result>
        <association property="school">
            <id property="id" column="s_id"></id>
            <id property="sName" column="s_name"></id>
        </association>
    </resultMap>

方法三:分步查询

即执行两条sql语句分两步:先查出老师信息,再根据老师信息中的学校ID去学校表中查询信息

SchoolMapper

public interface SchoolMapper {
    public List<School> getAll();
    public School getOneById(int id);
    public School getSchoolAndTeacherById(int id);
}
    <select id="getOneById" resultType="School">
        select * from school where id=#{id}
    </select>

结果如下:

延迟加载(懒加载)

表示按需加载,当前要访问的信息执行相对应的sql语句,如果当前不访问则不执行。(主要由分布查询来实现)

例子:根据老师的id查询所有信息(包括对应学校的信息)

    <select id="getTeacherById" resultMap="getTeacherById">
        select * from teacher where id=#{id}
    </select>
    <resultMap id="getTeacherById" type="Teacher">
        <id property="id" column="id"></id>
        <result property="TName" column="t_name"></result>
        <result property="schoolId" column="schoolId"></result>
        <association property="school" select="com.wang.dao.SchoolMapper.getOneById" column="schoolId" fetchType="lazy"></association>
    </resultMap>

首先分两步走,根据老师的唯一标识查询老师的所有信息,然后老师类中的学校属性根据association执行SchoolMapper的getOneById方法根据返回的schoolId查询学校信息。即:

select * from teacher where id=1 //设id为1,查出schoolId=1,传入第二条sql

select * from school where id=1 //将信息与学校类一一映射,作为老师类的学校信息属性

懒加载即如果只需要查询老师的信息,不涉及学校,只执行第一条sql语句,需要用到学校信息时才进行第二条sql。例如:

此时不设为懒加载,输出如下:

懒加载配置:

lazyLoadingEnabled:实现延迟加载,在核心配置文件设置,默认为false

aggressiveLazyLoading:任何方法调用都会加载该对象的所有属性,默认flase

所以开启懒加载,lazyLoadingEnabled开启true   aggressiveLazyLoading保持false

则,全局的分步式都可以延迟加载

如果有的功能无需设置延迟加载,将fetchType设置立即加载或延迟加载

开启懒加载测试结果如下:

开始只需要老师的信息,根据按需加载不会执行第二条sql语句,当需要学校的信息时,再次按需加载第二条sql语句

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值