一 需求:
编写一个接口,有两个方法:
一个返回当前年月+0001到9999的数值,如:2015040001,2015040002....;另一个方法返回年月日+0001到9999的数值,如:201504220001,201504220002....
二 操作步骤:
2.1 建表
DROP TABLE IF EXISTS `pl_num`;
CREATE TABLE `pl_num` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`cur_year` int(4) NOT NULL COMMENT '当前年份',
`cur_month` int(2) NOT NULL COMMENT '当前月份',
`cur_day` int(2) DEFAULT NULL COMMENT '当前日',
`cur_ymd_num` int(4) DEFAULT NULL COMMENT '年月日自增的数值(0001-9999)',
`cur_ym_num` int(4) DEFAULT NULL COMMENT '年月自增的数值(0001-9999)',
`save_type` varchar(32) NOT NULL COMMENT '保存类型',
`create_time` datetime NOT NULL COMMENT '创建时间(格式:yyyy-MM-dd HH:mm:ss)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8 COMMENT='编号生成器表';
2.2 ibatis配置
文件名:Num.xml sqlmap配置:<sqlMap resource="ibatis/Num.xml"/>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="NumGenerater">
<typeAlias type="com.yht.archives.commons.entity.Num" alias="Num"/>
<!--select,update,insert,delete. id名用于访问该资源,resultClass表示输出类型,parameterClass表示输入参数-->
<!-- 增加一条记录 -->
<insert id="addNum" parameterClass="Num">
INSERT INTO PL_NUM
<dynamic prepend="(" >
<isNotNull prepend="," property="id" > ID </isNotNull>
<isNotNull prepend="," property="cur_year" > CUR_YEAR </isNotNull>
<isNotNull prepend="," property="cur_month" > CUR_MONTH </isNotNull>
<isNotNull prepend="," property="cur_day" > CUR_DAY </isNotNull>
<isNotNull prepend="," property="cur_ymd_num" > CUR_YMD_NUM </isNotNull>
<isNotNull prepend="," property="cur_ym_num" > CUR_YM_NUM </isNotNull>
<isNotNull prepend="," property="save_type" > SAVE_TYPE </isNotNull>
<isNotNull prepend="," property="create_time" > CREATE_TIME </isNotNull>
)
</dynamic>
VALUES
<dynamic prepend="(" >
<isNotNull prepend="," property="id" > #id# </isNotNull>
<isNotNull prepend="," property="cur_year" > #cur_year# </isNotNull>
<isNotNull prepend="," property="cur_month" > #cur_month# </isNotNull>
<isNotNull prepend="," property="cur_day" > #cur_day# </isNotNull>
<isNotNull prepend="," property="cur_ymd_num" > #cur_ymd_num# </isNotNull>
<isNotNull prepend="," property="cur_ym_num" > #cur_ym_num# </isNotNull>
<isNotNull prepend="," property="save_type" > #save_type# </isNotNull>
<isNotNull prepend="," property="create_time" > #create_time# </isNotNull>
)
</dynamic>
</insert>
<!-- 更新一条记录 -->
<update id="updateNum" parameterClass="Num">
<![CDATA[
UPDATE PL_NUM
]]>
<dynamic prepend="SET">
<isNotNull prepend="," property="id"> ID = #id# </isNotNull>
<isNotNull prepend="," property="cur_year"> CUR_YEAR = #cur_year# </isNotNull>
<isNotNull prepend="," property="cur_month"> CUR_MONTH = #cur_month# </isNotNull>
<isNotNull prepend="," property="cur_day"> CUR_DAY = #cur_day# </isNotNull>
<isNotNull prepend="," property="cur_ymd_num"> CUR_YMD_NUM = #cur_ymd_num# </isNotNull>
<isNotNull prepend="," property="cur_ym_num"> CUR_YM_NUM = #cur_ym_num# </isNotNull>
<isNotNull prepend="," property="create_time"> CREATE_TIME = #create_time# </isNotNull>
</dynamic>
<dynamic prepend="WHERE">
<isNotNull prepend="AND" property="id"> ID = #id# </isNotNull>
<isNotNull prepend="AND" property="cur_year"> CUR_YEAR = #cur_year# </isNotNull>
<isNotNull prepend="AND" property="cur_month"> CUR_MONTH = #cur_month# </isNotNull>
<isNotNull prepend="AND" property="cur_day"> CUR_DAY = #cur_day# </isNotNull>
<isNotNull prepend="AND" property="save_type"> SAVE_TYPE = #save_type# </isNotNull>
</dynamic>
</update>
<!-- 查询字段的sql -->
<sql id="select_sql">
<![CDATA[
SELECT
ID AS id,
CUR_YEAR AS cur_year,
CUR_MONTH AS cur_month,
CUR_DAY AS cur_day,
CUR_YMD_NUM AS cur_ymd_num,
CUR_YM_NUM AS cur_ym_num,
SAVE_TYPE AS save_type,
CREATE_TIME AS create_time
FROM
PL_NUM
]]>
</sql>
<!-- 查询过滤条件的sql -->
<sql id="where_sql">
<dynamic prepend="WHERE">
<isNotNull prepend="AND" property="id"> ID = #id# </isNotNull>
<isNotNull prepend="AND" property="cur_year"> CUR_YEAR = #cur_year# </isNotNull>
<isNotNull prepend="AND" property="cur_month"> CUR_MONTH = #cur_month# </isNotNull>
<isNotNull prepend="AND" property="cur_day"> CUR_DAY = #cur_day# </isNotNull>
<isNotNull prepend="AND" property="cur_ymd_num"> CUR_YMD_NUM = #cur_ymd_num# </isNotNull>
<isNotNull prepend="AND" property="cur_ym_num"> CUR_YM_NUM = #cur_ym_num# </isNotNull>
<isNotNull prepend="AND" property="save_type"> SAVE_TYPE = #save_type# </isNotNull>
<isNotNull prepend="AND" property="create_time"> CREATE_TIME = #create_time# </isNotNull>
</dynamic>
</sql>
<!-- 列出记录数 -->
<select id="findNumCount" parameterClass="Num" resultClass="integer">
<![CDATA[
SELECT
COUNT(ID)
FROM
PL_NUM
]]>
<include refid="where_sql"/>
</select>
<!-- 列出一组记录 -->
<select id="findNum" parameterClass="Num" resultClass="Num">
<include refid="select_sql"/>
<include refid="where_sql"/>
<![CDATA[
ORDER BY CREATE_TIME DESC
LIMIT 0,1
]]>
</select>
</sqlMap>
2.3 dao层接口
public interface NumGeneraterDao {
/**
* 新增一条数据
* @param num
* @return
* @throws RuntimeException
*/
public Object addNum(Num num) throws RuntimeException;
/**
* 修改数据
* @param num
* @return
* @throws RuntimeException
*/
public void updateNum(Num num) throws RuntimeException;
/**
* 查询已生成最大的编号
* @return
* @throws RuntimeException
*/
public Num findMaxNum(String save_type) throws RuntimeException;
}
封装ArchivesBaseDao:
public abstract class ArchivesBaseDao extends SqlMapClientDaoSupport{
@Autowired
public void setSqlMapClientForAutowire(SqlMapClient sqlMapClient) {
super.setSqlMapClient(sqlMapClient);
}
protected Object insert(String id,Object param) {
return getSqlMapClientTemplate().insert(id, param);
}
protected int update(String id,Object param) {
return getSqlMapClientTemplate().update(id, param);
}
protected int delete(String id,Object param) {
return getSqlMapClientTemplate().delete(id, param);
}
@SuppressWarnings("rawtypes")
protected List queryForList(String id,Object param) {
return getSqlMapClientTemplate().queryForList(id, param);
}
protected Object queryForObject(String id,Object param) {
return getSqlMapClientTemplate().queryForObject(id, param);
}
protected Integer count(String id,Object param) {
return (Integer) getSqlMapClientTemplate().queryForObject(id, param);
}
}
2.4 dao层接口实现类
@Repository("numGeneraterDao")
public class NumGeneraterDaoImpl extends ArchivesBaseDao implements NumGeneraterDao {
@Override
public Object addNum(Num num) throws RuntimeException {
return (Num) insert("NumGenerater.addNum", num);
}
@Override
public void updateNum(Num num) throws RuntimeException {
update("NumGenerater.updateNum", num);
}
@Override
public Num findMaxNum(String save_type) throws RuntimeException {
Num numQo = new Num();
if(StringUtils.isNotBlank(save_type)){
numQo.setSave_type(save_type);
}
return (Num) queryForObject("NumGenerater.findNum", numQo);
}
}
2.5 service层接口
/**
* 编号数字生成器
* 规则:0001-9999 逐个加一,如0001,0002,0003....
* @author zengdq 2014-12-20
*
*/
public interface NumGeneraterServ {
/**
* 返回年月+0001到9999的数值,如:2014120001,2014120002....
* @return
* @throws Exception
*/
public String getYMNum() throws Exception;
/**
* 返回年月日+0001到9999的数值,如:201412210001,201412210002....
* @return
* @throws Exception
*/
public String getYMDNum(String declare_type) throws Exception;
}
2.6 service层接口实现类
@Service("numGeneraterServ")
@Transactional
public class NumGeneraterServImpl implements NumGeneraterServ {
private Logger logger = Logger.getLogger(getClass());
private final Integer DEFAULT_MIN_NUM = 0001; //默认最小编号,从0001开始
private final Integer DEFAULT_MAX_NUM = 9999; //默认最大编号
private final int DEFAULT_SHOW_NUM = 4; //整数显示最少位数
@Autowired
private NumGeneraterDao numGeneraterDao;
@Override
public synchronized String getYMNum() throws Exception {
//先获取数据库存的最大值
Num num = null;
try {
num = numGeneraterDao.findMaxNum(NumSaveType.YEAR_MONTH.name());
} catch (Exception e) {
logger.error("查询编号生成器SQL错误", e);
throw new FinanceException("","获取编号失败", e);
}
//获取系统当前时间
Integer add_num = DEFAULT_MIN_NUM;
Calendar cal = Calendar.getInstance();
int cur_year = cal.get(Calendar.YEAR);
int cur_month = cal.get(Calendar.MONTH)+1;//月份加1
if(num != null){ //检查数据
if((cur_year == num.getCur_year())
&& (cur_month == num.getCur_month())){
//当前数值+1先加1&保存并返回
Integer cur_ym_num = num.getCur_ym_num();
boolean flag = comparateTwoNum(cur_ym_num,DEFAULT_MIN_NUM);
boolean flag2 = comparateTwoNum(DEFAULT_MAX_NUM,cur_ym_num);
if(!flag || !flag2){
throw new FinanceException("","获取编号失败,编号取值范围必须是:[0001-9999]");
}
//当前值加1
add_num = cur_ym_num.intValue()+1;
}
}
//新增数据&返回年月+4位编号
StringBuffer sbf = saveAndReturnData(cur_year, cur_month,null,add_num,NumSaveType.YEAR_MONTH.name());
return sbf.toString();
}
@Override
public synchronized String getYMDNum(String declare_type) throws Exception {
//先获取数据库存的最大值
Num num = null;
try {
num = numGeneraterDao.findMaxNum(NumSaveType.YEAR_MONTH_DAY.name());
} catch (Exception e) {
logger.error("查询编号生成器SQL错误", e);
throw new FinanceException("","获取编号失败", e);
}
//获取系统当前时间
Integer add_num = DEFAULT_MIN_NUM;
Calendar cal = Calendar.getInstance();
int cur_year = cal.get(Calendar.YEAR);
int cur_month = cal.get(Calendar.MONTH)+1;//月份加1
int cur_day = cal.get(Calendar.DATE);
if(num != null){ //检查数据
if((cur_year == num.getCur_year())
&& (cur_month == num.getCur_month())
&& (cur_day == num.getCur_day())){
//当前数值+1先加1&保存并返回
Integer cur_ym_num = num.getCur_ymd_num();
boolean flag = comparateTwoNum(cur_ym_num,DEFAULT_MIN_NUM);
boolean flag2 = comparateTwoNum(DEFAULT_MAX_NUM,cur_ym_num);
if(!flag || !flag2){
throw new FinanceException("","获取编号失败,编号取值范围必须是:[0001-9999]");
}
//当前值加1
add_num = cur_ym_num.intValue()+1;
}
}
//新增数据&返回年月+4位编号
StringBuffer sbf = new StringBuffer();
if(declare_type.equals(DeclareType.NEW_DECLARE.getValue())){
sbf.append("RZXZ");
}else if(declare_type.equals(DeclareType.CHANGE_DECLARE.getValue())){
sbf.append("RZBG");
}
sbf.append(saveAndReturnData(cur_year, cur_month,cur_day,add_num,NumSaveType.YEAR_MONTH_DAY.name()));
return sbf.toString();
}
/**
* 比较两个整数的大小
* true表现num1小于um2;false表示num1大于或等于num2
* @param cur_ym_num
* @param dEFAULT_MIN_NUM2
* @return
*/
private boolean comparateTwoNum(Integer num1, Integer num2) {
boolean flag = false;
BigDecimal big1 = new BigDecimal(num1);
BigDecimal big2 = new BigDecimal(num2);
//-1表示小于,0表示等于,1表示大于
if(1 == big1.compareTo(big2)){
flag = true;
}else if(0 == big1.compareTo(big2)){
flag = true;
}/*else if(-1 == big1.compareTo(big2)){
flag = false;
}else{
flag = false;
}*/
return flag;
}
/**
* 新增一条,年月+4位编号的数据
* @param cur_year
* @param cur_month
* @return
*/
private StringBuffer saveAndReturnData(Integer cur_year, Integer cur_month,Integer cur_day,Integer number,String save_type) {
StringBuffer sb =new StringBuffer();
Num addNum = new Num();
addNum.setCur_year(cur_year);
addNum.setCur_month(cur_month);
addNum.setSave_type(save_type);
addNum.setCreate_time(DateUtil.getCurrentTime());
//
sb.append(cur_year);
sb.append(numFormat(cur_month,2));
if(NumSaveType.YEAR_MONTH.name().equals(save_type)){
addNum.setCur_ym_num(number);
}else if(NumSaveType.YEAR_MONTH_DAY.name().equals(save_type)){
addNum.setCur_day(cur_day);
addNum.setCur_ymd_num(number);
//
sb.append(numFormat(cur_day,2));
}else{
throw new FinanceException("S","添加编号失败,编号保存类型是非法的");
}
sb.append(numFormat(number,DEFAULT_SHOW_NUM));
try {
numGeneraterDao.addNum(addNum);
} catch (Exception e) {
logger.error("新增编号数据SQL错误", e);
throw new FinanceException("D","添加编号失败", e);
}
//返回该数据
return sb;
}
/**
* 显示固定长度的N位数值
* @param number
* @return
*/
private Object numFormat(Integer num, int minDigit) {
NumberFormat formatter = NumberFormat.getNumberInstance();
formatter.setMinimumIntegerDigits(minDigit); //整数显示最少位数不足前面补零
formatter.setGroupingUsed(false); // true(带逗号),false
//
return formatter.format(num);
}
}
三 测试:
main方法里:
NumGeneraterServ numGeneraterServ = (NumGeneraterServ)getBean("numGeneraterServ");
String value1 = numGeneraterServ.numGeneraterServ.getYMNum();
String value2 = numGeneraterServ.getYMDNum(DeclareType.NEW_DECLARE.name());