重要.唯一字段,怎么确保获取"唯一"流水号

流水号,一般是组成编号的一部分,用来实现计数,以及使编号唯一,

一:采用redis.incr获取

可以采用使用redis的 "incr"方法获取,不过有个局限性,就是redis不可删除缓存,如果删除掉之后,会将编号清零,重新计数(附redis工具类),只要传入的"str"不变,获取到的数字会一直递增

public class RedisUtil {

    private static final Logger LOG = LoggerFactory.getLogger(RedisUtil.class);

    private static JedisConnectionFactory jedisConnFactory;

    static {
        jedisConnFactory = ApplicationContextUtil.getContext().getBean(JedisConnectionFactory.class);
    }

    public static Object get(String cacheName, String key) {
        Jedis jedis = jedisConnFactory.getConnection().getNativeConnection();
        Object object = null;
        byte[] reslut = null;
        try {
            if (jedis.exists(key)) {
                reslut = jedis.get(key.getBytes());
                object = (Object) SerializeUtil.unserialize(reslut);
            }
        } catch (Exception e) {
            LOG.error("Read session from redis error", e);
            return null;
        } finally {
            jedis.close();
        }
        return object;

    }

    public static void put(String key, Object value) {
        Jedis jedis = jedisConnFactory.getConnection().getNativeConnection();
        try {
            jedis.set(key.getBytes(), SerializeUtil.serialize(value));
            jedis.expire(key, 1800);
            jedis.expire(key.getBytes(), 1800);
        } catch (Exception e) {
            LOG.error("Put session to redis error", e);
        } finally {
            jedis.close();
        }
    }


    public static void update(String key, Object value, String sessionId) {
        Jedis jedis = jedisConnFactory.getConnection().getNativeConnection();
        try {
            jedis.set(key.getBytes(), SerializeUtil.serialize(value));
            jedis.expire(sessionId, 1800);
            jedis.expire(key.getBytes(), 1800);
        } catch (Exception e) {
            LOG.error("Update session to redis error", e);
        } finally {
            jedis.close();
        }
    }

    public static void del(String key) {
        Jedis jedis = jedisConnFactory.getConnection().getNativeConnection();
        try {
            jedis.del(key);
        } catch (Exception e) {
            LOG.error("Del session to redis error", e);
        } finally {
            jedis.close();
        }
    }

    public static String incr(String str) {
        Jedis jedis = jedisConnFactory.getConnection().getNativeConnection();
        Long incr = jedis.incr(str);
        try {
            return incr.toString();
        } catch (Exception e) {
            LOG.error("get incr to redis error", e);
        } finally {
            jedis.close();
        }
        return null;
    }
}

二.将流水号存入数据库,每次递增+1

在系统中创建一个类,(在数据库中创建一个对应的表),使用数据库存储,每次需要获取新的编号,先去数据库中查询,如果有,获取到再+1, 得到的数字就是新的流水号,并且将新的流水号在数据库中更新,存放新的流水号在数据库中.emmm.稍微理解一下,

上代码

实体类:

@Entity
@Table(name = "serial_number", schema = "")
@SuppressWarnings("serial")
public class SerialNumberEntity implements java.io.Serializable {
    private String id;
    /**
     * 编号key
     */
    private String codeKey;
    /**
     * 编号的序号(流水号)
     */
    private Long serialNumber;

    /**
     * 备注
     */
    private String remark;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCodeKey() {
        return codeKey;
    }

    public void setCodeKey(String codeKey) {
        this.codeKey = codeKey;
    }

    public Long getSerialNumber() {
        return serialNumber;
    }

    public void setSerialNumber(Long serialNumber) {
        this.serialNumber = serialNumber;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

 建表语句:

CREATE TABLE `serial_number` (
  `id` varchar(108) NOT NULL,
  `code_key` varchar(600) DEFAULT NULL,
  `serial_number` double DEFAULT NULL,
  `remark` varchar(1500) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

表样式

获取库中的数据:

public synchronized String getSerialNumber(String string,String digit) {
	List<SerialNumberEntity> serialNumber=this.findByProperty(SerialNumberEntity.class, "codeKey", string);
	if(serialNumber!=null&&serialNumber.isEmpty()){
		SerialNumberEntity s=new SerialNumberEntity();
		s.setCodeKey(string);
		s.setSerialNumber(2L);
		s.setRemark(string);
		this.save(s);
		return string+String.format("%0"+digit+"d", 1);
	}else{
		SerialNumberEntity number =serialNumber.get(0);
		Long serial=number.getSerialNumber();
		number.setSerialNumber(serial+1);
		this.updateEntitie(number);
		return string+String.format("%0"+digit+"d", serial);
		
	}
}

其中"synchronized"锁 是防止不同线程同时去库中获取数据,以造成,生成的流水号相同.

"string":用来传递 codeKey 值 

"digit" 返回的字符串位数 

这里不提供测试类,只提供一种思路

猜你喜欢

转载自blog.csdn.net/hyc123123123123/article/details/86578121
今日推荐