- 1. 项目概述
- 1.1 SSM 框架优点
- 1.2 相关技术介绍
- 1.3 秒杀业务分析
- 1.3.1 秒杀系统业务流程
- 1.3.2 秒杀业务的核心:对库存的处理
- 1.3.3 为什么需要事务
- 1.3.4 关于数据落地
- 1.4 MySQL 实现秒杀难点分析
- 1.5 实现哪些秒杀功能
- 2. 创建项目和依赖
- 2.1 创建前的说明
- 2.2 开始创建项目
- 2.3 导入依赖
- 3. 数据库设计编码
- 4. DAO 层实体和接口编码
- 4.1 编写 entity 实体类
- 4.1.1 Seckill 实体类
- 4.1.2 SuccessKilled 类
- 4.2 设计 DAO 接口
- 4.2.1 SeckillDao 接口
- 4.2.2 SuccessKilledDao 接口
- 框架易于使用和轻量级
- 低代码侵入性
- 成熟的社区和用户群
1.MySQL
- 表设计
- SQL 技巧
- 事务和行级锁
2.MyBatis
- DAO 层设计与开发
- MyBatis 合理使用
- MyBatis 与 Spring 整合
3.Spring
- Spring IOC 整合 Service
- 声明式事务运用
4.SpringMVC
- Restful 接口设计和使用
- 框架运作流程
- Controller 开发技巧
5.前端
- 交互设计
- Bootstrap
- jQuery
6.高并发
- 高并发点和高并发分析
- 优化思路并实现
MySQL VS NoSQL
NoSQL:对事务支持不是很好,追求的是性能、高可用、分布式
MySQL:内置的事务机制依然是目前最有效、最可靠的数据落地方案 -> 可以更可靠的记录减库存、记录购买行为
难点问题: 竞争 -> 事务 +行级锁
事务工作机制:
- Start Transaction
- Update 库存数量 -> 竞争出现在此处
- Insert 购买明细
- Commit
行级锁 -> 伴随着竞争
如何高效的处理竞争:高并发
- 秒杀接口暴露
- 执行秒杀
- 相关查询: 列表查询、详情页查询
代码开发阶段
- DAO 设计编码 :数据库表设计、DAO 接口、MyBatis 如何实现 DAO
- Service 设计编码:
Service 接口设计及编码实现、通过 Spring 管理 Service、通过 Spring 声明式事务标注 Service 方法是一个事务 *** 作简化事务控制 - Web 设计编码:Restful 接口、 前端交互
-
从零开始创建
-
从官网获取相关配置
1.文档更全面权威
2.避免过时或错误
-
使用 Maven 创建项目
- 新建 Maven 项目
Maven 安装及其在 IDEA 中的配置和使用 (保姆级教程)
- 新建 Web 项目
Java 学习【框架篇(三)】SpringMVC(一)回顾 MVC 架构 & Servlet
结果如下:
3. 数据库设计编码4.0.0 org.seckill seckill1.0-SNAPSHOT junit junit4.11 test org.slf4j slf4j-api1.7.12 ch.qos.logback logback-core1.1.1 ch.qos.logback logback-classic1.1.1 mysql mysql-connector-java5.1.35 runtime com.mchange c3p00.9.5.2 org.mybatis mybatis3.3.0 org.mybatis mybatis-spring1.2.3 taglibs standard1.1.2 jstl jstl1.2 com.fasterxml.jackson.core jackson-databind2.5.4 javax.servlet javax.servlet-api3.1.0 org.springframework spring-core4.1.7.RELEASE org.springframework spring-beans4.1.7.RELEASE org.springframework spring-context4.1.7.RELEASE org.springframework spring-jdbc4.1.7.RELEASE org.springframework spring-tx4.1.7.RELEASE org.springframework spring-web4.1.7.RELEASE org.springframework spring-webmvc4.1.7.RELEASE org.springframework spring-test4.1.7.RELEASE
Java 学习【框架篇(二)】MyBatis(一)第一个 MyBatis 查询程序
- main 下新建 schema.sql
schema.sql 中 SQL 语句如下:
-- 数据库初始化脚本 -- 创建数据库 CREATE DATAbase `seckill`;
-- 使用数据库 use `seckill`;
-- 创建秒杀库存表 CREATE TABLE `seckill`( `seckill_id` bigint NOT NULL AUTO_INCREMENT COMMENT '商品库存id', `name` varchar(120) NOT NULL COMMENT '商品名称', `number` int NOT NULL COMMENT '库存数量', `start_time` datetime NOT NULL COMMENT '秒杀开始时间', `end_time` datetime NOT NULL COMMENT '秒杀结束时间', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', -- 设计索引 -- idx 为 index 简称 PRIMARY KEY (`seckill_id`), key idx_start_time(`start_time`), key idx_end_time(`end_time`), key idx_create_time(`create_time`) )ENGINE = InnoDB AUTO_INCREMENT = 1000 DEFAULT CHARSET = utf8 COMMENT '秒杀库存表';
-- 初始化数据 insert into `seckill`(`name`, `number`, `start_time`, `end_time`) values ('1000 元秒杀 iphone6', 100, '2015-11-01 00:00:00', '2015-11-02 00:00:00'), ('500 元秒杀 ipad2', 200, '2015-11-01 00:00:00', '2015-11-02 00:00:00'), ('300 元秒杀小米 4', 300, '2015-11-01 00:00:00', '2015-11-02 00:00:00'), ('200 元秒杀红米 note', 400, '2015-11-01 00:00:00', '2015-11-02 00:00:00');
-- 秒杀成功明细表 -- 用户登录认证相关的信息 create table `success_killed`( `seckill_id` bigint NOT NULL COMMENT '秒杀商品 id', `user_phone` bigint NOT NULL COMMENT '用户手机号', `state` tinyint NOT NULL DEFAULT -1 COMMENT '状态标识: -1: 无效 0: 成功 1: 已付款 2: 已发货', `create_time` datetime NOT NULL COMMENT '创建时间', PRIMARY KEY (`seckill_id`, `user_phone`), -- 联合主键 key idx_create_time(create_time) )ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT '秒杀成功明细表';
修改数据库字段属性:
ALTER TABLE `success_killed` MODIFY `create_time` datetime;
显示表是怎么创建的:
show CREATE TABLE `success_killed`;
CREATE TABLE `success_killed` ( `seckill_id` bigint(20) NOT NULL COMMENT '秒杀商品 id', `user_phone` bigint(20) NOT NULL COMMENT '用户手机号', `state` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '状态标识: -1: 无效 0: 成功 1: 已付款 2: 已发货', `create_time` datetime DEFAULT NULL, PRIMARY KEY (`seckill_id`,`user_phone`), KEY `idx_create_time` (`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='秒杀成功明细表'
结果如下:
tabel 和 entity 的对应关系
- 表对应 Java 中的实体类
- 列对应实体中的属性
创建实体包 & DAO 层的包
org.seckill.entity
org.seckill.dao
package org.seckill.entity; import java.util.Date; public class Seckill { private long seckillId; private String name; private int number; private Date startTime; private Date endTime; private Date createTime; // Alt + insert public long getSeckillId() { return seckillId; } public void setSeckillId(long seckillId) { this.seckillId = seckillId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } @Override public String toString() { return "Seckill{" + "seckillId=" + seckillId + ", name='" + name + ''' + ", number=" + number + ", startTime=" + startTime + ", endTime=" + endTime + ", createTime=" + createTime + '}'; } }4.1.2 SuccessKilled 类
package org.seckill.entity; import java.util.Date; public class SuccessKilled { private long skillId; private long userPhone; private short state; private Date createTime; // 变通 // 多对一(复合属性): 一个 Seckill 实体对应多个秒杀成功的记录 private Seckill seckill; public long getSkillId() { return skillId; } public void setSkillId(long skillId) { this.skillId = skillId; } public long getUserPhone() { return userPhone; } public void setUserPhone(long userPhone) { this.userPhone = userPhone; } public short getState() { return state; } public void setState(short state) { this.state = state; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Seckill getSeckill() { return seckill; } public void setSeckill(Seckill seckill) { this.seckill = seckill; } @Override public String toString() { return "SuccessKilled{" + "skillId=" + skillId + ", userPhone=" + userPhone + ", state=" + state + ", createTime=" + createTime + '}'; } }4.2 设计 DAO 接口 4.2.1 SeckillDao 接口
命名规范: 对应的实体 + Dao -> 如:SeckillDao
package org.seckill.dao; import org.seckill.entity.Seckill; import java.util.Date; import java.util.List; public interface SeckillDao { // 减库存 (killTime 执行减库存的时间 对应数据库中的 creatTime) // 如果影响行数 >1, 表示更新的记录行数 int reduceNumber(long seckillId, Date killTime); // 查询需求(根据 id 查询秒杀对象) Seckill queryById(long seckillId); // 根据偏移量查询秒杀商品列表 // offset:偏移量, limit:在偏移量之后取多少条记录 List4.2.2 SuccessKilledDao 接口queryAll(int offset, int limit); }
package org.seckill.dao; import org.seckill.entity.SuccessKilled; public interface SuccessKilledDao { // 插入购买明细,可过滤重复(联合唯一主键) // 插入的行数 int insertSuccessKilled(long seckillId, long userPhone); // 根据 id 查询 SuccessKilled 并携带秒杀产品对象实体 SuccessKilled queryByIdWithSeckill(long seckillId); }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)