Step‑by‑Step Guide to Building a High‑Concurrency Seckill Project with the SSM Framework

This tutorial walks through creating a Java SSM‑based high‑concurrency seckill application, covering project workflow, environment setup, Maven dependencies, database schema, entity classes, MyBatis mapper interfaces and XML configurations, as well as testing and common MySQL version pitfalls.

Java Captain
Java Captain
Java Captain
Step‑by‑Step Guide to Building a High‑Concurrency Seckill Project with the SSM Framework

This article introduces a complete development workflow for a high‑concurrency "seckill" (flash‑sale) project built with the SSM stack (Spring, Spring MVC, MyBatis) and Maven.

Project Development Process

The project is divided into four stages: DAO layer, web layer, service layer, and high‑concurrency optimization. Basic Maven knowledge and Java syntax are required.

Environment Setup

Recommended tools: Ubuntu 17.04, IntelliJ IDEA 2016.2.5 (or Eclipse), JDK 1.8+, Tomcat 8.0, MySQL 5.6.17, Maven for dependency management. The article explains how to configure Maven archetype generation and IDE import steps.

Database Schema

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` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '秒杀开启的时间',
  `end_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '秒杀结束的时间',
  `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建的时间',
  PRIMARY KEY (seckill_id),
  KEY idx_start_time(start_time),
  KEY idx_end_time(end_time),
  KEY idx_create_time(create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='秒杀库存表';

INSERT INTO seckill (name, number, start_time, end_time) VALUES
('1000元秒杀iphone6', 100, '2016-5-22 00:00:00', '2016-5-23 00:00:00'),
('500元秒杀iPad2', 200, '2016-5-22 00:00:00', '2016-5-23 00:00:00'),
('300元秒杀小米4', 300, '2016-5-22 00:00:00', '2016-5-23 00:00:00'),
('200元秒杀红米note', 400, '2016-5-22 00:00:00', '2016-5-23 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已付款',
  `create_time` TIMESTAMP NOT NULL COMMENT '创建时间',
  PRIMARY KEY (seckill_id, user_phone),
  KEY idx_create_time(create_time)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='秒杀成功明细表';

The article also discusses MySQL 5.7 strict mode issues and how to add default values for TIMESTAMP columns.

Entity Classes

package com.suny.entity;

public class Seckill implements Serializable {
    private long seckillId;
    private String name;
    private int number;
    private LocalDateTime startTime;
    private LocalDateTime endTime;
    private LocalDateTime createTIme;
    // getters, setters, constructors, toString()
}

public class SuccessKilled implements Serializable {
    private long seckillId;
    private long userPhone;
    private short state;
    private LocalDateTime createTime;
    private Seckill seckill;
    // getters, setters, constructors, toString()
}

Mapper Interfaces

public interface SeckillMapper {
    int reduceNumber(@Param("seckillId") long seckillId, @Param("killTime") LocalDateTime killTime);
    Seckill queryById(@Param("seckillId") long seckillId);
    List<Seckill> queryAll(@Param("offset") int offset, @Param("limit") int limit);
}

public interface SuccessKilledMapper {
    int insertSuccessKilled(@Param("seckillId") long seckillId, @Param("userPhone") long userPhone);
    SuccessKilled queryByIdWithSeckill(@Param("seckillId") long seckillId, @Param("userPhone") long userPhone);
}

MyBatis XML Configurations

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.suny.dao.SeckillMapper">
  <update id="reduceNumber">
    UPDATE seckill SET number = number - 1
    WHERE seckill_id = #{seckillId}
      AND start_time <= #{killTime}
      AND end_time >= #{killTime}
      AND number > 0
  </update>
  <select id="queryById" resultType="com.suny.entity.Seckill">
    SELECT * FROM seckill WHERE seckill_id = #{seckillId}
  </select>
  <select id="queryAll" resultType="com.suny.entity.Seckill">
    SELECT * FROM seckill ORDER BY create_time DESC LIMIT #{offset}, #{limit}
  </select>
</mapper>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.suny.dao.SuccessKilledMapper">
  <insert id="insertSuccessKilled">
    INSERT IGNORE INTO success_killed (seckill_id, user_phone, state) VALUES (#{seckillId}, #{userPhone}, 0)
  </insert>
  <select id="queryByIdWithSeckill" resultType="com.suny.entity.SuccessKilled">
    SELECT sk.seckill_id, sk.user_phone, sk.create_time, sk.state,
           s.seckill_id "seckill.seckill_id", s.name "seckill.name", s.number "seckill.number",
           s.start_time "seckill.start_time", s.end_time "seckill.end_time", s.create_time "seckill.create_time"
    FROM success_killed sk INNER JOIN seckill s ON sk.seckill_id = s.seckill_id
    WHERE sk.seckill_id = #{seckillId} AND sk.user_phone = #{userPhone}
  </select>
</mapper>

Spring DAO Configuration (applicationContext-dao.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
  <context:property-placeholder location="classpath:jdbc.properties"/>
  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="${jdbc.user}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="maxPoolSize" value="30"/>
    <property name="minPoolSize" value="10"/>
    <property name="autoCommitOnClose" value="false"/>
    <property name="checkoutTimeout" value="1000"/>
  </bean>
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="mybatis-config.xml"/>
    <property name="typeAliasesPackage" value="com.suny.entity"/>
    <property name="mapperLocations" value="classpath*:com/suny/dao/*.xml"/>
  </bean>
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <property name="basePackage" value="com.suny.dao"/>
  </bean>
</beans>

Testing with JUnit

package com.suny.dao;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring/applicationContext-dao.xml"})
public class SeckillMapperTest {
    @Resource
    private SeckillMapper seckillMapper;

    @Test
    public void reduceNumber() throws Exception {
        long seckillId = 1000L;
        LocalDateTime now = LocalDateTime.now();
        int result = seckillMapper.reduceNumber(seckillId, now);
        System.out.println(result);
    }

    @Test
    public void queryById() throws Exception {
        Seckill seckill = seckillMapper.queryById(1000L);
        System.out.println(seckill);
    }

    @Test
    public void queryAll() throws Exception {
        List<Seckill> list = seckillMapper.queryAll(0, 100);
        list.forEach(System.out::println);
    }
}

The guide also highlights common pitfalls such as MySQL 5.7 strict mode requiring explicit default values for TIMESTAMP columns and updating web.xml to servlet version 3.0 to enable annotations.

Overall, the article provides a hands‑on reference for developers building high‑throughput Java web applications using the SSM stack.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Webhigh-concurrency
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.