建议 利用mybatis标签替换硬编码
背景 在项目中偶尔看到这样的代码:
1 2 3 4 5 6 7 8 9 <sql id ="querySqlString" > <where > 1=1 <if test ="fundsOrderIdList != null and fundsOrderIdList.size()>0" > and funds_order_id IN <foreach collection ="fundsOrderIdList" item ="id" index ="index" open ="(" close =")" separator ="," > #{id} </foreach > </if >
这段代码中有个1=1
很扎眼,这个不是bug,也没有什么性能问题,只是程序员世代传承下来的一个习惯。
故事 在很久以前,充满智慧的程序员为了解决动态条件拼接的问题,发明了1=1
这个写法,对应的还有1=0
的写法,我们来看看这个写法在以前是怎么解决问题的:
1 2 3 4 5 6 7 sql = "select * from car_table where 1=1" for (Condtion condition:conditions){ sql = sql + " and " + condition.field + " = " + condition.value }
确实很巧妙,而且也没有性能问题,不信我给你举个🌰:
1 select * from pay_channel_with_bank where 1 = 1 and channel_code = '50008' ;
这是一条很简单的SQL,其中就有1=1
的写法,我们来看看MySQL查询优化器优化后实际执行的SQL:
1 2 3 4 5 EXPLAIN select * from pay_channel_with_bank where 1 = 1 and channel_code = '50008' ;SHOW WARNINGS;实际执行的SQL : select 此处省略很多column from `online_paychannel`.`pay_channel_with_bank` where (`online_paychannel`.`pay_channel_with_bank`.`channel_code` = 50008 )
可以看到1=1
已经被优化掉了。
结论 虽然这种写法没啥大问题,但是代码是给人看的。如果不了解这种写法,乍一眼看过去肯定有点懵。
而且我们现在使用的Mybatis提供的<where>
标签本身就会帮我们做优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void applyPrefix (StringBuilder sql, String trimmedUppercaseSql) { if (!prefixApplied) { prefixApplied = true ; if (prefixesToOverride != null ) { for (String toRemove : prefixesToOverride) { if (trimmedUppercaseSql.startsWith(toRemove)) { sql.delete(0 , toRemove.trim().length()); break ; } } } if (prefix != null ) { sql.insert(0 , " " ); sql.insert(0 , prefix); } } }
WhereSqlNode
中定义的prefixesToOverride
:
1 private static List<String> prefixList = Arrays.asList("AND " ,"OR " ,"AND\n" , "OR\n" , "AND\r" , "OR\r" , "AND\t" , "OR\t" );
所以使用了<where>
标签后可以放心大胆的去掉1=1
。