专栏名称: java那些事
分享java开发中常用的技术,分享软件开发中各种新技术的应用方法。每天推送java技术相关或者互联网相关文章。关注“java那些事”,让自己做一个潮流的java技术人!《java程序员由笨鸟到菜鸟》系列文章火热更新中。
目录
相关文章推荐
芋道源码  ·  如何实现一个合格的分布式锁 ·  10 小时前  
芋道源码  ·  高性能、无侵入的 Java 性能监控神器 ·  2 天前  
Java编程精选  ·  手把手教你Java文件断点下载 ·  4 天前  
51好读  ›  专栏  ›  java那些事

抢红包案例分析以及代码实现

java那些事  · 公众号  · Java  · 2018-11-09 16:00

正文

请到「今天看啥」查看全文


Long id;
// 发红包的用户id
private Long userId;
// 红包金额
private Double amount;
// 发红包日期
private Timestamp sendDate;
// 红包总数
private Integer total;
// 单个红包的金额
private Double unitAmount;
// 红包剩余个数
private Integer stock;
// 版本(为后续扩展用)
private Integer version;
// 备注
private String note;
// 省略set/get
}


抢红包信息

package com.artisan.redpacket.pojo;

import java.io.Serializable;
import java.sql.Timestamp;

/**
*
*
* @ClassName : UserRedPacket
*
* @Description : 用户抢红包表
*
* @author : Mr.Yang
*
* @date : 2018年10月8日 下午3:47:40
*/

public class UserRedPacket implements Serializable {

private static final long serialVersionUID = 7049215937937620886L ;

// 用户红包id
private Long id;
// 红包id
private Long redPacketId;
// 抢红包的用户的id
private Long userId;
// 抢红包金额
private Double amount;
// 抢红包时间
private Timestamp grabTime;
// 备注
private String note;
// 省略set/get
}


Dao层实现

MyBatis Dao接口类及对应的Mapper文件

使用 MyBatis 开发,先来完成大红包信息的查询先来定义一个 DAO 对象

package com.artisan.redpacket.dao;

import org.springframework.stereotype.Repository;

import com.artisan.redpacket.pojo.RedPacket;


@Repository
public interface RedPacketDao {

/**
* 获取红包信息.
* @param id --红包id
* @return 红包具体信息
*/

public RedPacket getRedPacket (Long id) ;

/**
* 扣减抢红包数.
* @param id -- 红包id
* @return 更新记录条数
*/

public int decreaseRedPacket (Long id) ;


}


其中的两个方法 , 一个是查询红包,另一个是扣减红包库存。

抢红包的逻辑是,先查询红包的信息,看其是否拥有存量可以扣减。如果有存量,那么可以扣减它,否则就不扣减。

接着将对应的Mapper映射文件编写一下

xml version= "1.0" encoding= "UTF-8" ?>
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
< mapper namespace = "com.artisan.redpacket.dao.RedPacketDao" >


< select id = "getRedPacket" parameterType = "long"
resultType = "com.artisan.redpacket.pojo.RedPacket" >

select id, user_id as userId, amount, send_date as
sendDate, total,
unit_amount as unitAmount, stock, version, note from
T_RED_PACKET
where id = #{id}
select >


< update id = "decreaseRedPacket" >
update T_RED_PACKET set stock = stock - 1 where id =
#{id}
update >


mapper >


这里getRedPacket并没有加锁这类动作,目的是为了演示超发红包的情况。

然后是抢红包的设计了 ,先来定义插入抢红包的 DAO ,紧接着是Mapper映射文件

package com .artisan .redpacket .dao ;

import org .springframework .stereotype.Repository ;

import com .artisan .redpacket .pojo .UserRedPacket ;

@ Repository
public interface UserRedPacketDao {

/**
* 插入抢红包信息.
* @param userRedPacket ——抢红包信息
* @return 影响记录数.
*/

public int grapRedPacket ( UserRedPacket userRedPacket );
}


xml version= "1.0" encoding= "UTF-8" ?>
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

< mapper namespace = "com.artisan.redpacket.dao.UserRedPacketDao" >

< insert id = "grapRedPacket" useGeneratedKeys = "true"
keyProperty = "id" parameterType = "com.artisan.redpacket.pojo.UserRedPacket" >

insert into T_USER_RED_PACKET( red_packet_id, user_id, amount, grab_time, note)
values (#{redPacketId}, #{userId}, #{amount}, now(), #{note})
insert >
mapper >


这里使用了 useGeneratedKeys 和 keyPrope町,这就意味着会返回数据库生成的主键信息,这样就可以拿到插入记录的主键了 , 关于 DAO 层就基本完成了。 别忘了单元测试!!!


Service层实现

接下来定义两个 Service 层接口,分别是 UserRedPacketService和RedPacketService

package com.artisan.redpacket.service;

import com.artisan.redpacket.pojo.RedPacket;


public interface RedPacketService {

/**
* 获取红包
* @param id ——编号
* @return 红包信息
*/

public RedPacket getRedPacket (Long id) ;

/**
* 扣减红包
* @param id——编号
* @return 影响条数.
*/

public int decreaseRedPacket (Long id) ;

}


package com.artisan.redpacket.service;

public interface






请到「今天看啥」查看全文