码周记(第四期)

提示:可能对很多人来说码周记中的内容比较菜,不喜勿喷!!!

简介

本周想分享以下几个内容:

  1. tomcat配置文件对spring定时任务的影响
  2. 使用BigDecimal原因和BigDecimal的坑
  3. java中的“find_in_set”函数
  4. 你不知道的mybatis,执行多条sql

一、tomcat配置文件对spring定时任务的影响

描述: 以前一直都没有研究过tomcat的启动,一直都是默认启动,即:把war包名字改成ROOT,然后启动tomcat就能直接访问了。但是这次在一个简单的单服项目中加了一个简单的spring定时任务之后,发现这个定时任务执行了两边。。。运维的人意思是我这边代码的问题,但是我本地测了好几遍都是只执行了一次,所以我怀疑是运维做了负载,最后发现是tomcat配置的问题。

打开server.xml配置文件,我们来看看这几个参数
在这里插入图片描述

1、appBase:这个参数,个人认为就是指定tomcat去加载哪个目录下的文件

2、docBase:这个参数,个人认为就是让tomcat去解压appBase下名字为XXX的war包(XXX就是docBase配置的名字)

3、path:问题就是出在这个参数,如果我们不配置这个参数的话,他会生成在appBase指定的目录下生成两个文件夹:ROOT和docBase中指定的名字,如:
在这里插入图片描述
实际上你启动的tomcat是启动了两个项目,一个是ROOT,一个是zongsMobileApi-0.0.1-SNAPSHOT,虽然在配置文件中配置了跳转到zongsMobileApi-0.0.1-SNAPSHOT项目中去,但是ROOT项目确确实实也是起来了运行的,对于spring定时任务来说,无论有没有前端在调用这个项目并不影响,ROOT项目中的定时任务也会执行,这样就变成了两个定时任务在执行了!

解决: 其实不配置path这个参数,无非就是想访问的时候不加项目名称,但是如果这样不配置的话,定时任务就出现了执行两边的问题,解决方式无非就是三种:

  1. 单服下:配置path,然后如果想访问的时候不加项目名称,可以在nginx上配置转发,即:转发的时候配置上项目名称
  2. 单服下:将war包的名称改为ROOT,这样tomcat解压的时候就会生成一个ROOT项目,这样外面访问也不需要加上项目名称
  3. 用quartz集群来做(一般简单的定时任务不建议用quartz,这个东西要引入一大堆表)

二、使用BigDecimal原因和BigDecimal的坑

名人不说暗话,我是第一次在java里面用BigDecimal,无奈本人没文化,曾今以为double、int行天下,直到我在单元测试中跑出了这么个例子(意不意外,惊不惊喜):
在这里插入图片描述
在意外和惊喜之中,我们是不是发现曾今如此信任的double竟然有bug?最近我刚好在做的是一个电商项目,之前规定数据库中存入的金额都是分,这个时候如果使用了double是不是就莫名其妙的少了一分钱,那如果日交易量大的话,是不是会造成不少的损失呢?下面我们来看看用BigDecimal会变成什么样,是不是也有同样的bug呢?

BigDecimal构造参数是String型:
在这里插入图片描述
BigDecimal构造参数是double型:
在这里插入图片描述
结果:实验结果告诉我们,BigDecimal在使用String类型的构造函数的时候,结果是准确的,而使用double的构造函数的时候任然存在这种隐形的bug,这样就是为什么网上为什么那么多建议使用String类型的构造函数的原因。

问题:看到这里是不是大家都觉得BigDecimal那么好,其实他也有坑的地方!
在这里插入图片描述
神奇不?第一次用BigDecimal的我百度了一下BigDecimal的加法,然后发现是用add的,但是后来发现项目中结果add和没add一样,但是单元测试输出他们add的结果又是对的。

分析(个人版本。可能不对):这是因为这里存在一个误区,把BigDecimal的add类似于list的那种add了,这是一种严重的错误,我们可以认为 int a=0; a++;a就变成了1,但是BigDecimal是一个对象,bigDecimal.add(bigDecimal1)这个对象确实存在,也输出了,但是bigDecimal这个引用并没有指向这片新的内存;只有bigDecimal=bigDecimal.add(bigDecimal1)这么写才改变了bigDecimal的引用!

三、java中的“find_in_set”函数

大家还记得在上期中分享的mysql中的find_in_set函数吗,这个函数主要体现的是mysql中处理数据的能力,而java中的“find_in_set”函数其实并不存在,而是一种思想。

我想大家对String的contains、indexOf和lastIndexOf这几个函数应该不陌生,但是想通过这几个函数达到mysql中的find_in_set功能,你们觉得能实现吗???

如果正常思维显然是不能实现的(判断这个人的公司列表是否含有id为12的公司):
在这里插入图片描述
解决:其实我看我同事这么写的时候,我是震惊的,说实话不难,也没啥水准可言,但是我的他很有想法!
在这里插入图片描述

四、你不知道的mybatis,执行多条sql

很多小伙伴看到这个标题,肯定第一想到的是foreach,恭喜你答对了一半,那还有一半是什么呢?

可能在大多数情况下,我们认识的执行多条sql是一个执行头(insert、delete、update、select)即:

<select id="XXXX" resultType="java.util.HashMap">
  SELECT user_name  FROM   XXX   where delete_mark=0 and user_id in
   <foreach collection="list" item="item" open="(" close=")" separator=",">
         #{item}
   </foreach>
</select>

但是我今天要讲的是如何在mybatis里面一个dao方法执行多个执行头:

 <update id="XXX">
   <foreach collection="list" item="item"   separator=";">
       update  XXX   set column1=#{item.SSSS} where id=#{item.id}
   </foreach>
 </update>

这种写法。。。是不是既熟悉又陌生???其实这种写法在java里面就是for循环调用update方法而已,但是为什么要这么写呢?

优势:我们不妨想象一下,如果这个循环是100,而你在java里面循环调用dao,在连接数据库的话,是不是需要连接100次数据库,如果这个数是1000,1万呢,你觉得你数据库的连接数扛得住吗,但是这种写法只要连接一次数据库就行了!

其实我们很多时候数据库挂了,tomcat挂了等等,都是我们平时写代码的时候没考虑性能问题造成的,大量的连表,for循环连接数据库等,这种操作对于数据库来说都是头皮发麻!

注意:上面介绍的那种写法需要做一个配置:allowMultiQueries=true 即:支持执行多条sql

jdbc:mysql://XXXX:3306/XXX?characterEncoding=utf-8&allowMultiQueries=true
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值