Mybatis中利用OGNL和bind标签灵活应对常量值经常修改的需求

写在前面: 这是个悲伤的故事.....................................................


系统中经常会碰到这样的情况, 表里面有个状态字段, 有各种各样的状态, 比如用户表可能有下面的状态:

用户状态枚举类(这里就是为了说名举的例子,将就着用吧 - -! )

package com.haogrgr.buka.consts;

public interface UserConst {

	public enum UserStatus {

		SYSTEM("系统用户", "2"), NORMAL("正常用户", "1"), BLOCK("冻结用户", "-1"), DEL("删除用户", "-2"),;

		UserStatus(String desc, String value) {
			this.desc = desc;
			this.value = value;
		}

		private String desc;
		private String value;

		public String getDesc() {
			return desc;
		}

		public String getValue() {
			return value;
		}

	}

}


当我们需要查询出可用用户(SYSTEM或NORMAL) 时  : 

sql :     select * from user where status = '2' or status = '1'     或者:  sql:   select * from user where status != '-1' and status != '-2'

这样会有问题, 当我们改变常量值时, 比如以前 是    SYSTEM(2), NORMAL(1), BLOCK(-1), DEL(-2); 现在变成了  SYSTEM(11), NORMAL(10), BLOCK(-10), DEL(-12);  

虽然这种情况很少,但是还是可能会出现的, 比如说, 我不哭~~~~ 


当碰到改变常量值的情况时: 我们就得小心了.... 得找到所有引用的地方, 然后一个个的改, 比如这里要改成

sql :     select * from user where status = '11' or status = '10'

如果到条件到处都是写死在sql中~~~~~~嘿嘿, 有得你改了, 你得找出所有用到了的地方~~~而且可能在其他的sql文件中也用到了这个状态过滤~~~~~~~

总之....这么写, 一旦改了常量值~~~~蛋蛋疼~~~~ 


那么如何改呢?

可以这样:  select * from user where status = #{systemStatus} or status = #{normalStatus}

然后dao和service这么写(我用的是Spring帮我动态代理生成的mapper实现类, 所以mapper不需要写实现类~~~)

UserMapper:
public List<User> findAvailableUser(String systemStatus, String normalStatus);

UserService;
public List<User> findAvailableUser(){
    return userMappser.findAvailableUser(UserStatus.SYSTEM.getValue(), UserStatus.NORMAL.getValue());
}


这么写是ok啦, 就是有那么点蛋疼~~~特别是查询条件复杂的情况下, 要传很多的参数~~~~接口不干净~~~~

现在解决办法来了

mybatis的sql文件很灵活, 因为里面有些标签可以使用OGNL表达式

比如说<bind> 标签   , (ognl表达式不知道的去百度,google吧~~~我这里就不讲了....) 

于是我们可以这样用了(注意:OGNL是通过反射来获取值的,所以一定要保证你的类或get方法的可见性, public 声明)

<select id="findAvailableUser" resultMap="BaseResultMap">
    <bind name="_SYSTEM" value="@com.haogrgr.buka.consts.UserConst$UserStatus@SYSTEM.value"/>
    <bind name="_NORMAL" value="@com.haogrgr.buka.consts.UserConst$UserStatus@NORMAL.value"/>
    select * from user where status = #{_SYSTEM} or status = #{_NORMAL}
</select>

然后mapper接口也变得简洁了:
UserMapper:
public List<User> findAvailableUser();

现在接口清晰多了, 而且常量也没有写死. (如果你的常量是static变量, ognl也能获取到~~~百度去吧~~~)


总结: 总的来说, 就是通过bind标签, 来写ognl表达式来获取值, 所以ognl能获取到的东西,都能用到sql中去....

注意:使用了这种方式后, 还有问题: 比如改包名, 将 com.haogrgr.buka.consts.UserConst 改成  com.haogrgr.buka.consts.user.UserConst  那么执行sql会报错

       但是有一点好的就是, 当改了常量类包名或者类名或者常量名时, 执行sql就会报错, 能够尽早的被发现.

       当然,使用这总方式还会损失点性能~~~~就那么一点点啦,就那么一点点啦,哈哈哈哈哈哈哈哈哈哈哈哈


其实一般项目哪会经常改常量的值啊~~~~搞这么复杂干什么~~~~但是写代码嘛, 总是追求更好的做法, 否则挺无聊的.

(ps:我不是第一个想到这么做的~~~)


最后听说写文章要首位呼应, 于是

写在最后:是怎样的经历才会让一位少年想出如此蛋疼的搞法.....................................................


发现个天大的bug, 对于已有数据的系统~~~~你改了常量值....数据库中已有记录的值还是存的老值~~~所以还是少改常量值的好~~~蛋蛋疼.


转载于:https://my.oschina.net/haogrgr/blog/295008

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值