MyBatis_03 分页、一对一、延迟加载

一、#与$的区别

  • #{}:使用了预编译处理,底层就是使用PreparentStatment,安全。
  • ${}:没有使用预编译处理,底层就是Statment,有SQL注入风险。
-- #{}的作用主要是替换预编译语句(PrepareStatement)中的占位符?:
-- 对于 : 
INSERT INTO user (name) VALUES (#{name}); 
-- 相当于
INSERT INTO user (name) VALUES (?);

-- ${} 符号的作用是直接进行字符串替换:
-- 对于 : 
INSERT INTO user (name) VALUES ('${name}');
-- 相当于
INSERT INTO user (name) VALUES ('zhangsan');

二、ResultMap(自定义结果映射)

常情况下,我们可能表字段和实体类的属性不一致,或者多表查询,都需要我们来配置一个返 回类型

1、在映射配置文件中配置:

<resultMap id="studentMapping" type="Student">
    <!-- id:主键字段,底层会有优化 -->
    <id column="id" property="id"/>
    <!-- result:普通字段 -->
    <result column="name" property="name"/>
    <!-- 其它不指定列会自动匹配,通常把所有字段都写上 -->
    <result column="age" property="age"/>
    <result column="email" property="email"/>
</resultMap>

2、使用:

<select id="listMapping" resultMap="studentMapping">
    select * from student
</select>

注意:resultType和resultMap不要同时使用。

3、Mybatis中javaType和jdbcType对应关系

jdbcTypeJavaType
CHARString
VARCHARString
LONGVARCHARString
NUMERICjava.math.BigDecimal
DECIMALjava.math.BigDecimal
BITboolean
BOOLEANboolean
TINYINTbyte
SMALLINTshort
INTEGERint
BIGINTlong
REALfloat
FLOATdouble
DOUBLEdouble
BINARYbyte[]
VARBINARYbyte[]
LONGVARBINARYbyte[]
DATEjava.sql.Date
TIMEjava.sql.Time
TIMESTAMPjava.sql.Timestamp
CLOBClob
BLOBBlob
ARRAYArray
DISTINCTmapping of underlying type
STRUCTStruct
REFRef
DATALINKjava.net.URL

4、RestulType和ResultMap的区别?

  • RestulType使用我们已经存在的实体类型(Pojo),使用RestulType的
    前期是字段名和属性名要一致。
  • RestulType不能用在关联查询上。
  • ResultMap是我们自定义的一个结果映射,用法更加灵活,我们可以自己
    来指定字段名和属性名的对应关系。
  • ResultMap还可以来配置MyBatis中的关联查询。

三、分页查询

1、使用SQL的方式

Mapper接口中:

@Select("select * from student limit #{pageNum},#{pageSize}")
List<Student> listByPage(@Param("pageNum") int pageNum, @Param("pageSize") int pageSize);

测试类:

@Test
public void testListByPage(){
    //打开会话
    SqlSession session = sqlSessionFactory.openSession();
    //查询Mapper(xxxMapper接口的类类型),返回的mapper就是接口的实现类(通过代理模式实现)
    StudentMapper mapper = session.getMapper(StudentMapper.class);
    //调用对象的方法
    //当前页码
    int pageNum=2;
    //每页显示的数量
    int pageSize=2;
    List<Student> stus = mapper.listByPage((pageNum-1)*pageSize,pageSize);
    //测试打印
    System.out.println(stus);
    //关闭会话
    session.close();
}

2、使用MyBatis的方式

Mapper配置文件中:

<select id="listByPage2" resultMap="studentMapping">
    select * from student
</select>

测试类:

@Test
public void testListPager2() {
	int pagerNow = 2;//当前页
	int pagerSize = 3;//每页显示几条
	SqlSession session = MyBatisUtil.openSession();
	RowBounds rowBounds = new RowBounds((pagerNow-1)*pagerSize, pagerSize);
	List<Student> listPager = session.selectList("pagerList2",
	null, rowBounds);
	for (Student stu : listPager) {
	System.out.println(stu);
	}
	session.close();
}

三、一对一关联

1、关联关系(association)

一对一: 人和身份证、丈夫和妻子…

2、MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:

  • property:对象属性的名称
  • javaType:对象属性的类型
  • column:所对应的外键字段名称
  • select:使用另一个查询封装的结果

3、创建表和数据

-- 添加老师表
CREATE TABLE `teacher` (
 `id` int(10) NOT NULL AUTO_INCREMENT,
 `name` varchar(50) NOT NULL,
 PRIMARY KEY (`id`)
) 
-- 修改学生表,添加tid字段
ALTER TABLE student
ADD COLUMN tid INT(10);
-- 修改学生表,添加外键约束
ALTER TABLE student
ADD FOREIGN KEY(tid)
REFERENCES teacher(id);

4、创建Teacher实体类

package org.example.entity;

/**
 * 教师实体类
 */
public class Teacher {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

5、修改Student实体类

package org.example.entity;

/**
 * @description: 学生实体类
 */
public class Student {
    //添加teacher属性,并生成getter()setter()方法
    private Teacher teacher;
	...
}

6、创建Mapper接口

1)TeacherMapper

public interface TeacherMapper {
    //根据id查询教师
    Teacher findById(int id);
}

2)StudentMapper

public interface StudentMapper {
	//根据id查询学生
	Student findById(int id);
}

7、创建Mapper映射配置

1)TeacherMapper

<?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="org.example.mapper.TeacherMapper">
    <select id="findById" resultType="Teacher">
        select * from teacher where id=#{id}
    </select>
</mapper>

2)StudentMapper.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="org.example.mapper.StudentMapper">
    <resultMap id="studentMapping" type="Student">
        <!-- id:主键字段,底层会有优化 -->
        <id column="id" property="id"/>
        <!-- result:普通字段 -->
        <result column="name" property="name"/>
        <!-- 其它不指定列会自动匹配,通常把所有字段都写上 -->
        <result column="age" property="age"/>
        <result column="email" property="email"/>
        <!-- 一对一关联关系:其实就是老师一的那一端
            association:一对一
            property:属性名
            select:调用查询
            column:参数关联哪列字段
        -->
        <association property="teacher" select="org.example.mapper.TeacherMapper.findById"
                     column="tid">
        </association>
    </resultMap>
    <!--根据id查询学生-->
    <select id="findById" resultMap="studentMapping">
        select * from student where id=#{id}
    </select>
</mapper>

8、测试类

1、需求:按id查询学生信息,并且显示老师的名称。

 @Test
public void testFindById(){
    //打开会话
    SqlSession openSession = sqlSessionFactory.openSession();
    //获取mapper
    StudentMapper mapper = openSession.getMapper(StudentMapper.class);
    //调用接口方法
    Student stu = mapper.findById(1);
    //输出学生信息
    System.out.println(stu.getId()+","+stu.getName());
    //输出老师信息
    System.out.println(stu.getTeacher().getName());
}

四、配置延迟加载

在上述演示时,我们会发现不管是要学生信息,还是老师信息,都会去查2次,这样会影响查询 效率,在MyBatis中,可以设置延迟加载。

延迟加载,也可以称为懒加载或者按需加载。
只需要简单增加两个配置即可:

1、通用配置文件mybatis-config.xml增加:

<!--设置选项-->
<settings>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

如果在已有全局配置下,对某个查询不需要延迟加载时,还可以再mapper映射中配置:

  • fetchType:lazy 延迟加载(默认)
  • fetchType:eager 立刻加载

2、配置映射文件设置:

<association property="teacher" select="org.example.mapper.TeacherMapper.findById"
             column="tid" fetchType="lazy">
</association>

完整代码

代码已托管在gitee上面,点击直达

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值