推荐学java——MyBatis高级

补两张知识导图

最近的两篇文章[《Maven初识》]和[《第一个MyBatis程序》]文中缺少了知识结构图,这里补充一下。

image.png

初识Maven

image.png

MyBatis知识导图

本节内容是关于 MyBatis 的高级部分,上节的内容重点是带大家从零开始搭建一个使用 MyBatis 框架的java项目,并且能使用 MyBatis 框架完成对[数据库]中表的增删改查操作;这听起来不难理解,但对于新手要实战一遍,还是需要多加练习,推荐大家通过新建 Module 的方式来操作。

本节内容会在上一节的基础上进行,包括项目工程和数据库,内容包括但不限于:

  • MyBatis核心配置文件中其他配置
  • SQL语句如何动态化
  • MyBatis 注解开发模式
  • MyBatis 缓存机制
  • 分页功能

tips:本文demo的源码和数据表,在公众号 推荐学java 回复 myBatisDemo 即可获得。

即将进入正题,请保持安静

配置文件标签

日志管理

日志文件 是用于记录系统操作事件的记录文件或文件集合。

在实际开发中日志是非常重要的,能起到两个很大的作用,其一:帮助开发人员排错其二:能通过记录管理谁操作了什么内容,这两点尤其和库关联的时候,就能起到非常关键的作用,删库跑路这样的说法相信各位都听说过吧!

日志框架掌握两个常用的即可:

  • STDOUT_LOGGING
  • LOG4J

使用方式比较简单,在主配置文件 mybatis-config.xml 中添加如下代码:

<!--  配置日志  -->
<setting name="logImpl" value="STDOUT_LOGGING"/>

对于 STDOUT_LOGGING 添加如上配置即可使用;对于 LOG4J 该库本身支持各种各样的定制,可单独增加属性配置文件,按照自己的需求来修改配置,做到定制化,关于如何配合以及有哪些属性,网上有很多教程,这里不做解释了(最近该库闹出了漏洞,大家都在填坑)。

需要注意的是:MyBatis核心配置文件中的 **configuration**标签下配置的标签是有顺序的,依次为:

  • properties(属性配置,本文后面会做配置,需要掌握)
  • settings(设置,需要掌握)
  • typeAliases(类型别名,需要掌握,能认识会用)
  • typeHandlers(类型处理器,了解即可)
  • objectFactory(对象工厂,了解即可)
  • plugins(插件,需要掌握,依赖一些插件的时候要求配置)
  • environments(环境配置,熟练掌握)
    • environment(环境变量)
      • transactionManager(事务管理器)
      • dataSource(数据源)
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器,熟练掌握)
properties标签

上节我们在settings标签中配置了驼峰命名映射:

这是截至目前接触到的settings标签里的两个配置,下面看properties标签,这是我们第一次接触。举个简单的例子你就知道它的作用了,还记得下面这段代码吗?

这里的 value 对应的值通过这种直接写死的方式很不友好,也是不推荐的,实际开发中是有专门的属性文件来管理这些值的,这就要用到properties标签了。

resources目录下新建文件db.properties,编辑如下内容:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_demo?useUnicode=true&characterEncoding=utf8
username=root
password=root

就是这么简单,有其他编程语言经验的道友应该不陌生,这就是简单的 k-v 形式存储值的方式,接下来就是我们的核心配置文件中的configuration标签下配置如下代码:

 

还记得我们前面提到的顺序问题嘛!不要放错了位置(放错也没关系,IDEA太智能了,它会给你提示的)。想学习交流HashMap,nginx、dubbo、Spring MVC,分布式、高性能高可用、MySQL,redis、jvm、多线程、netty、kafka、的加尉(同英):1253431195 扩列获取资料学习,无工作经验不要加哦!

细心的你可能注意到我们有一处微小的变化:&amp; -> & 那为什么 & 这个符号不能直接在xml中写呢?

我们都知道 xml 里面都是标签,如果我们要写一个小于号<,那么xml在解析的时候会认为你这是某个标签的开始,且这个标签没有写完整,所以就有了一些对应的转义符号,常用的几个:

  • <&lt;
  • >&gt;
  • &&amp;
  • '&apos;
  • "&quot;
typeAliases标签

该标签的作用是为了给繁长且多的javaBean起一个短名字,方便使用减少出错概率,上节内容我们有这样一个查询:

select * from tv_series

这里的 com.javafirst.bean.TVSeriesBean 就是我们要用别名来代替的部分,想一下,如果项目稍微复杂一些,且经历了好几个开发者,那么使用别名就很Nice.下面是别名标签的配置:

<!--    方式2 指定包名的全路径 别名默认是首字母小写类名(如果该类被添加了注解,那么别名会优先取注解名)
    优点是可以一次指定多个,缺点是不能自定义
-->

这样设置后,我们在对应的mapper.xml里就可以这样使用:

select * from tv_series

细心同学注意到了吧,有两种方式,但推荐大家用这里举例的方式,至于注解方式,本文后面会讲。

动态SQL

动态SQL 是指根据参数动态组织SQL的技术。简单来说,可以通过在java项目中动态的改变条件等来执行SQL得到需要的结果。其实并不难,也不高深,下面来一一了解:

  • 动态SQL-if
  • 动态SQL-where(对if的优化)
  • 动态SQL-choose(when,otherwise)
  • 动态SQL-foreach
  • 动态SQL-片段
动态SQL-片段

使用注意事项:

  • 尽量基于单表实现
  • 不要嵌套 where 标签

我们先来定义一个SQL片段:

select * from tv_series

语法很简单,使用sql标签,里面是基本的SQL语句,可以使增删改查中的其一,可以定义多个,只需id唯一即可,使用方式也很简单,看下面的示例:

当然,你也可以嵌套在语句中,比如这样:

where tv_id = #{tvId}

使用起来还是比较灵活的,尤其当我们的SQL比较长的时候,把一些独立的内容提取出来对我们理解程序有很大的意义。

动态SQL-if

相信你应该已经猜到了,没错,就是要学习if标签,还要把它应用在sql语句书写中,作为条件判断使用,这就很有意思了。在开始之前先来插入几条数据,作为接下来学习使用,完整SQL如下,可以直接执行哈:

INSERT INTO tv_series (tv_title,tv_sub_title,tv_type)
VALUES ("《天龙八部》",“这部小说以宋哲宗时代为背景,通过宋、辽、大理、西夏、吐蕃等王国之间的武林恩怨和民族矛盾,从哲学的高度对人生和社会进行审视和描写,展示了一幅波澜壮阔的生活画卷。”,2),
("《侠客行》",“孤悬海外的侠客岛,每十年即派出赏善罚恶二使来到中原,强行邀请武林各大门派掌门人赴岛喝腊八粥。凡不接受邀请的门派皆被二使斩尽杀绝,而去了侠客岛的掌门人又个个渺无音信。”,1),
("《笑傲江湖》",“该剧讲述华山派大弟子令狐冲,生性豁达不羁。偶遇剑宗高人风清扬授以《独孤九剑》,又意外尽得五岳各派剑法精髓,导致师父岳不群猜疑,藉口逐出师门。”,2),
("《人民的名义》",“夜幕下的汉东省京州市,看似平静的官场霎时间阴云密布。国家部委项目处处长赵德汉涉嫌受贿,遭到最高人民检察院反贪总局侦查处处长侯亮平(陆毅 饰)的突击调查。”,6)
;

现在我们来看个很简单的例子:

通过标题或者类型来查询数据,返回一个List集合.

实现这个功能,并不难,关键是我们要通过动态SQL技术来做,但我们熟悉的三步骤不会变。第一步,在TVSeriesDao中定义接口List<TVSeriesBean> selectByDynamicSQL_if(Map<String, Object> params) ;

第二步,在TVSeriesMapper.xml中完成SQL的编写:

where tv_title=#{title}
<if test="type > 0 and type < 7">
    or tv_type = #{type}
</if>

第三步,就是测试方法,代码如下:

/**

  • 动态SQL-if 测试
    */
    @Test
    public void testDynamicSQL_if() {
    SqlSession sqlSession = MyBatisUtil.openSqlSession();
    TVSeriesDao tvSeriesDao = sqlSession.getMapper(TVSeriesDao.class);

    // 通过标题 或者 类型 来查找数据
    Map<String, Object> params = new HashMap<>();
    params.put(“title”, “《人民的名义》”);
    //params.put(“type”, 2);

    List beanList = tvSeriesDao.selectByDynamicSQL_if(params);

    for (TVSeriesBean seriesBean : beanList) {
    System.out.println(seriesBean);
    }

    sqlSession.close();
    }

完成以上三步,最后就是看结果了,这里给各位几组测试参数:

// 第一组
params.put(“title”, “《人民的名义》”);
//params.put(“type”, 2);

// 第二组
params.put(“title”, “《人民的名义》”);
params.put(“type”, 2);

// 第三组
//params.put(“title”, “《人民的名义》”);
params.put(“type”, 2);

// 第四组
params.put(“title”, “”);
params.put(“type”, 12);

大家测试后一定会发现第三组和第四组参数是会出错的,这就是只使用IF标签带来的问题,此时这两组参数对应的SQL变为下面这样了:

select * from tv_series where or tv_type=2

select * from tv_series where

很明显,这两条SQL语法都错误的,无法执行,导致我们的程序出现异常。那么解决方案是什么呢?这就是接下来要学的动态SQL-where标签和if结合使用。

动态SQL-where(if)

在前面的基础上,我们只需要修改一下 mapper.xml中的代码即可测试结果:

tv_title=#{title}
    <if test="type > 0 and type < 7">
        or tv_type = #{type}
    </if>
</where>

验证结果各位自行测试,这里不做演示,需要说明的是MyBatis会自动取消紧跟在where标签后的orand,正是因为这样,我们的SQL会自动拼装为可执行的语句。想学习交流HashMap,nginx、dubbo、Spring MVC,分布式、高性能高可用、MySQL,redis、jvm、多线程、netty、kafka、的加尉(同英):1253431195 扩列获取资料学习,无工作经验不要加哦!

动态SQL-choose(when,otherwise)

过程都一样,这里直接上代码了,定义接口TVSeriesBean selectByDynamicSQL_choose(Map<String, Object> params);接着是mapper.xml中的代码如下:

tv_type = #{type}
        <when test="title == null or title == ''">
            tv_title = '《人民的名义》'
        </when>

        <otherwise>
            tv_id = #{id}
        </otherwise>
    </choose>
</where>

这里说明一下代码功能,choose-when-otherwise 结构和我们在java基础部分学习过的switch-case结构作用是等同的,只是书写语法不同而已,理解起来一点难度没有。

简言之,只要其中一个when标签的判断条件满足情况,那么就不会走后面的逻辑;如果when条件都不满足,那么会走otherwise后的逻辑,就这么简单。

最后是我们的测试代码,如下:

/**

  • 动态SQL-choose-when-otherwise
    */
    @Test
    public void testSelectByDynamicSQL_choose() {
    SqlSession sqlSession = MyBatisUtil.openSqlSession();
    TVSeriesDao tvSeriesDao = sqlSession.getMapper(TVSeriesDao.class);

    Map<String, Object> params = new HashMap<>();
    params.put(“title”, “xxx”);
    params.put(“type”, 12);
    // 条件都不满足 则取默认值
    params.put(“id”, 2);

    TVSeriesBean bean = tvSeriesDao.selectByDynamicSQL_choose(params);

    System.out.println(bean);

    sqlSession.close();
    }

结果大家自行尝试,通过变换参数来实践结果,理解更透彻。

动态SQL-foreach

常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。这里会分别讲解集合的泛型是IntegerObject类型,他们只是稍微有点区别,先来看包装类型的集合遍历。

定义接口List<TVSeriesBean> selectByDynamicSQL_foreach(List<Integer> ids);然后是mapper.xml中的代码:

where tv_id in #{cus_id}

这里对每个属性的意义都做了解释,其实是完全对应我们之前学习过集合的结构来的,所以理解起来并不难,因为xml中始终都是按照节点来做解析的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架是主要的开源应用程序开发框架,它使得Java/J2EE开发更容易、效率更高。本书不仅向读者展示了Spring能做什么?而且揭示了Spring完成这些功能的原理,解释其功能和动机,以帮助读者使用该框架的所有部分来开发成功的应用程序。本书涵盖Spring的所有特性,并且演示了如何将其构成一个连贯的整体,帮助读者理解Spring方法的基本原理、何时使用Sping以及如何效仿最佳实践。所有这些都以完整的样本应用程序来举例说明。读完本书,读者将能够有效地在各种应用中(从简单的web应用程序到复杂的企业级应用程序)使用Spring。 作者:(美)约翰逊 译者:蒋培 Rod Johnsn是Spring框架的创始人,并且是Java和J2EE领域的著名专家。   Rod获悉民大博士位。他具有C/C++开发背景,从Java和J2EE发布以来就作为开发者、休系结构设计者和顾问涉足了Java和J2EE领域。   他撰写了两本最普及并最有影响力的J2EE书籍:《Expert One-on-one J2EE Design and Deuelo Pment》(Wrox,2002),和《J2EE without EJB》(Wrox,2004.与Juergen Hoelle合著)。这两本书在“敏捷J2EE的兴起和心变过度复杂的传统J2EE体系结构方面都起了得要作用。   Rod是Spring框架的共同领导之一。他的发言很受欢迎,并且经常出现在美国、欧洲和亚洲举行的Java重要活动中。了是一些JSR的专家组的成员,为Java社区发展计划(Java Community Process,JCP)EBTL。   他还具有在银行和金融、保险、软件、媒体等领域从事顾问的广泛经验。他是Interface21的CEO,Interface21是一家致力于提供专家级J2EE和Spring框架服务的咨询公司。他各极参与客户项目和Spring开发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值