Data Access 之 MyBatis(三) - SQL Mapping XML(Part C)(下)

简介: Data Access 之 MyBatis(三) - SQL Mapping XML(Part C)

新建SQL映射文件lock.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.citi.dao.LockDao">
    <select id="getLockById" resultMap="mylock">
        SELECT l.id,l.lockName,k.id kid, k.keyname,k.lockid
            FROM t_lock l
            LEFT JOIN t_key k ON l.id = k.lockid
            WHERE l.id=#{id}
    </select>
    <resultMap id="mylock" type="com.citi.entity.Lock">
        <id property="id" column="id"></id>
        <result property="lockName" column="lockName"></result>
        <collection property="keyList" ofType="com.citi.entity.Key">
            <!--column是起的别名,如果没起别名,就和数据库列字段一致-->
            <id property="id" column="kid"></id>
            <result property="keyName" column="keyName"></result>
        </collection>
    </resultMap>
</mapper>
复制代码
  • collection:复杂类型的集合
  • ofType:指定集合里面元素的类型

将lock.xml注册到MyBatis全局配置文件中

<mappers>
    <mapper resource="mappers/employee.xml"/>
    <mapper resource="mappers/cat.xml"/>
    <mapper resource="mappers/key.xml"/>
    <mapper resource="mappers/lock.xml"/>
</mappers>
复制代码

新建测试类

public class LockDaoTest {
    SqlSessionFactory sqlSessionFactory = null;
    SqlSession openSession = null;
    @Before
    public void setUp() throws Exception {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        openSession = sqlSessionFactory.openSession();
    }
    @Test
    public void getLockById() {
        LockDao lockDao = openSession.getMapper(LockDao.class);
        Lock lock = lockDao.getLockById(3);
        System.out.println(lock);
        List<Key> keyList = lock.getKeyList();
        for (Key key : keyList) {
            System.out.println("Key:" + key);
        }
    }
}
复制代码

执行测试

dd0ed556ef5f416381463267e89b4bc7_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

联合查询较为繁琐,使用分步查询也可以完成;先查出Key,在根据Key的信息到t_lock表中查出锁的信息

分步查询 Key -> Lock

在KeyDao和LockDao中分别增加一个查询方法

Lock getLockByIdSimplely(Integer id);
复制代码
Key getKeyByIdSimplely(Integer id);
复制代码

在lock.xml映射文件中增加SQL语句

<select id="getLockByIdSimplely" resultType="com.citi.entity.Cat">
    select * from t_lock where id = #{id}
</select>
复制代码

在key.xml中完成分步查询

<select id="getKeyByIdSimplely" resultMap="mykeysimplely">
    select * from t_key where id = #{id}
</select>
<resultMap id="mykeysimplely" type="com.citi.entity.Key">
    <id property="id" column="id"></id>
    <result property="keyName" column="keyname"></result>
    <association property="lock"
                 select="com.citi.dao.LockDao.getLockByIdSimplely"
                 column="lockid">
    </association>
</resultMap>
复制代码
  • property:指定封装哪个属性
  • select:指定一个查询SQL的唯一标识,MyBatis自动调用指定的SQL将查询的结果结果封装到指定的属性
  • colume:指定将哪一列数据传递过去

在KeyDaoTest中增加getKeyByIdSimplely方法的测试代码

@Test
public void getKeyByIdSimplely() {
    KeyDao keyDao = openSession.getMapper(KeyDao.class);
    Key key = keyDao.getKeyByIdSimplely(1);
    System.out.println(key);
}
复制代码

执行测试

004e6b40be7947d0877df4e5b96c232b_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

根据控制台打印的信息可以看出分步查询其实就是分别执行了两条SQL,先获取Key,在获取Lock;每次查询Key都要数据库执行两条SQL严重影响性能,而且并不是每次查询Key的时候也需要锁的信息,因此对查询锁信息可以使用按需加载,需要的时候再执行查锁。

在MyBatis全局配置文件中配置开启延迟加载和属性按需加载

<settings>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="true"/>
</settings>
复制代码

将打印key的代码注释(不注释会调用Key的toString方法导致懒加载失效),再次执行测试

858334fe062b411b8bbec9efcd0babcb_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

控制台只会打印出一条SQL语句,也就是后台只执行了一条SQL语句

修改测试代码,获取Lock

@Test
public void getKeyByIdSimplely() {
    KeyDao keyDao = openSession.getMapper(KeyDao.class);
    Key key = keyDao.getKeyByIdSimplely(1);
    // System.out.println(key);
    String lockName = key.getLock().getLockName();
    System.out.println(lockName);
}
复制代码

再次测试

5421111bf6dc4b2892f25dc06e4ff13c_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

覆盖全局的延迟加载配置,在association标签中增加fetchType="eager",注释掉获取锁的代码,再次执行测试

e51efa0850b04f429c4d25f033c26129_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

分步查询 Lock -> Key

分别在LockDao、KeyDao中新增方法

Lock getLockByIdStep(Integer id);
复制代码
List<Key> getKeysByLockId(Integer id);
复制代码

在key.xml中新增查询key的SQL语句

<select id="getKeysByLockId" resultType="com.citi.entity.Key">
    select * from t_key where lockid = #{id}
</select>
复制代码

在lock.xml中新增getLockByIdStep方法的映射

<select id="getLockByIdStep" resultMap="mylockstep">
    select * from t_lock where id = #{id}
</select>
<resultMap id="mylockstep" type="com.citi.entity.Lock">
    <id property="id" column="id"></id>
    <result property="lockName" column="lockName"></result>
    <collection property="keyList"
                select="com.citi.dao.KeyDao.getKeysByLockId"
                column="id">
    </collection>
</resultMap>
复制代码

增加测试方法

@Test
public void getLockByIdStep() {
    LockDao lockDao = openSession.getMapper(LockDao.class);
    Lock lock = lockDao.getLockByIdStep(3);
    System.out.println(lock);
    List<Key> keyList = lock.getKeyList();
    for (Key key : keyList) {
        System.out.println("Key:" + key);
    }
}
复制代码

执行测试

903990ba71ea4da4a7a7b4906df8f706_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

reslutMap标签中的 column属性是用来传递select属性指定的查询方法的参数,如果该查询方法有多个参数则可以使用{key1=value1,key2=value2}的方式来传递数据。

实际应用中更推荐使用连接查询的方式而非分步查询,相比较会减少对数据库的压力


相关文章
|
SQL Java 数据库连接
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
|
SQL Java 数据库连接
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
1880 0
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
1112 0
|
11月前
|
SQL XML Java
通过MyBatis的XML配置实现灵活的动态SQL查询
总结而言,通过MyBatis的XML配置实现灵活的动态SQL查询,可以让开发者以声明式的方式构建SQL语句,既保证了SQL操作的灵活性,又简化了代码的复杂度。这种方式可以显著提高数据库操作的效率和代码的可维护性。
598 18
|
11月前
|
SQL Java 数据库连接
SSM相关问题-1--#{}和${}有什么区别吗?--Mybatis都有哪些动态sql?能简述一下动 态sql的执行原理吗?--Spring支持的几种bean的作用域 Scope
在MyBatis中,`#{}`是预处理占位符,可防止SQL注入,适用于大多数参数传递场景;而`${}`是直接字符串替换,不安全,仅用于动态表名、列名等特殊场景。二者在安全性、性能及使用场景上有显著区别。
503 0
|
SQL XML Java
菜鸟之路Day35一一Mybatis之XML映射与动态SQL
本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`&lt;if&gt;`、`&lt;where&gt;`、`&lt;set&gt;`、`&lt;foreach&gt;`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`&lt;sql&gt;`和`&lt;include&gt;`实现代码复用,优化维护效率。
1303 5
|
XML Java 数据库连接
二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作)
二、搭建MyBatis采用xml方式,验证CRUD(增删改查操作)
469 21
|
SQL Java 数据库连接
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
|
SQL 缓存 Java
框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性
本文详细解构了MyBatis的工作机制,包括解析配置、创建连接、执行SQL、结果封装和关闭连接等步骤。文章还介绍了MyBatis的五大核心功能特性:支持动态SQL、缓存机制(一级和二级缓存)、插件扩展、延迟加载和SQL注解,帮助读者深入了解其高效灵活的设计理念。
|
SQL XML Java
九、MyBatis动态SQL
九、MyBatis动态SQL
301 2