业务是多变的,需要存储多种标识。
如:
要标识会员是否是卖家,
要标识会员手机是否已认证
要标识会员是网站还是手机注册
。。。。
这些标识是互相独立,需要支持联合查询
一般的做法是针对每个标识做个字段
tinyint is_sell comment '1:卖家,0:买家'
tinyint mobile_auth comment '1:已认证,0:未认证'
tinyint regist_from comment '1:网站,2:手机'
要查 是卖家,手机已认证的
is_sell = 1 and mobile_auth = 1
问题
标识是随时可能增加的,这意味着字段也要增加,这显然是非常困难的。
解决办法
1.标识以2的次方设置,标识值相加以10进制存储在字段中
如:卖家标识是 2的0次方,1
手机认证是 2的1次方,2
来自手机注册 2的2次方 4
某会员是卖家,来自手机注册,1+4 = 5
存储在数据库标识字段值是:5
2.要查有卖家标识的会员
(5 & 1) == 1 ------> true
二进制与运算,返回值是该标识表明成立
101
001
-----
001
3.要查有卖家标识且手机认证的会员
(5 & (1+2)) == (1+2) ----> false
二进制与运算,返回值是几个标识的和表明成立
101
011
------
001
注意:
1. 在mysql中以long字段存储,可以存储2的64方的值,即最多可存储标识64个
public class BitUtils { /** * 2的几次方 * * @param position * @return */ public static long pow2(int num) { return ((Double) Math.pow(2, num)).longValue(); } /** * 判断 一个数number的二进制格式的第position位是否为1 * * @param number * 十进制数 * @param position * 第几位 右到左从0开始 * @return */ public static boolean isTrue(long number, int position) { long decimalValue = pow2(position); return (decimalValue & number) == decimalValue; } /** * 位或 运算 * * @param m * @param n * @return */ public static long computeOR(long m, long n) { return m | n; } /** * 针对一个10进制数的位运算,增加位 * * @param number * 10进制数 * @param position * 位数 从0开始 * @return */ public static long addBit(long number, int position) { if (number < 0 || position < 0) return 0; return computeOR(number, pow2(position)); } /** * 针对一个10进制数的位运算,删除位 * * @param number * 10进制数 * @param position * 位数 从0开始 * @return */ public static long removeBit(long number, int position) { if (number < 0 || position < 0) return 0; if (isTrue(number, position)) { number = number - pow2(position); } return number; } public static void main(String[] args) { // System.out.println(pow2(0)); long a = addBit(0, 5); System.out.println(a); } }