spring + mybatis + maven实现高并发秒杀业务(一)

MAVEN整合Spring+SpringMVC+Mybatis 2016/1/20 14:47:28原创,转载请注明出处曾经看过《那些年我们一起追过的女孩》,片中有个比较经典的画面,至今记忆犹新,柯景腾多年后,做了一名作家,每天面对电脑码字,背后是一张张一闪而过的字幅“人生就是不停的战斗”作为程序员,我想一生就是不停的和BUG做战斗了,新来的这家公司,用的很老的Spring+Struts2.0+JDBC的框架,非常的不好用,其中的问题可以陈述10条以上,但是限于 阅读详情

前言

   刚过了“双十一”,相信大家的待收货都是满满哒,在“双十一”期间,相信很多童鞋都参加了产品“秒杀”吧,12点时候在手机或电脑上抢商品抢的不亦乐乎。但是作为一名可爱的程序猿,就在思考这个秒杀是怎么做出来的啦。废话不多说,下面我们就用一个最简单的demo来实现商店购物的秒杀实现。

创建项目和依赖

1.使用maven命令创建项目
  mvn archetype:generate -DgroupId=org.seckill -DartifactId=seckill -DarchetypeArtifactId=mvn-archetype-webapp -DarchetypeCatalog=local

  • -DgroupId:代表组织和整个项目的唯一标识,比如:所有Maven组件的groupId就是org.apache.maven
  • -DartifactId:代表项目的具体名称,它和groupId共同确定一个项目在maven repo中的位置
  • -DarchetypeArtifactId:指的是原型的名字
  • -DarchetypeCatalog:指的是查找的规则

2.创建依赖
   项目创建成功之后,导入idea,我们会看到一个pom.xml文件,它是maven项目的标志,项目的依赖就要在这里面补全啦,如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.seckill</groupId>
  <artifactId>seckill</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>seckill Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
      <!--使用junit4-->

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!--补全项目依赖-->
    <!--日志 java日志:slf4g,log4j,logback,common-logging
        slf4g 是规范/接口
        日志实现 log4j,logback,common-logging
        使用slf4j + logback
    -->
    <dependency>
      <groupId>org.slf4g</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.12</version>
    </dependency>

    <dependency>
      <groupId>ch.gos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.1.1</version>
    </dependency>
    <!--实现slf4j接口并且整合-->
    <dependency>
      <groupId>ch.gos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.1.1</version>
    </dependency>

    <!--数据库相关的依赖-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.35</version>
      <scope>runtime</scope>
    </dependency>

    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1.2</version>
    </dependency>

    <!--DAO框架依赖:mybatis依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.3.0</version>
    </dependency>

    <!--mybatis自身实现的spring整合依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.2.3</version>
    </dependency>

    <!--servlet web相关依赖-->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.5.4</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>

    <!--spring依赖-->
    <!--spring核心依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>

    <!--spring DAO层的依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>

    <!--spring web相关依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>

    <!--spring test相关依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>seckill</finalName>
  </build>
</project>

3.数据库的创建,如下:

-- 数据库初始化脚本

-- 创建数据库
CREATE DATABASE seckill;

-- 使用数据库
use seckill;

-- 创建秒杀数据库
-- 重点是出现多个TIMESTAMP的解决
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  '0000-00-00 00:00:00' COMMENT '秒杀时间开始',
`end_time` TIMESTAMP NOT NULL DEFAULT  '0000-00-00 00:00:00' COMMENT '秒杀时间结束',
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (seckill_id),
KEY inx_start_time(start_time),
KEY inx_end_time(end_time),
KEY inx_create_time(create_time)
)ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT = '秒杀库存表';
-- 可以支持事物的引擎只有InooDB

-- 初始化数据
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` TIMESTAMP NOT NULL COMMENT '创建时间',
-- 联合主键
PRIMARY KEY (seckill_id,user_phone),
KEY idx_create_time(create_time)
)ENGINE = InnoDB  DEFAULT charset=utf8 COMMENT = '秒杀成功明细表';

-- 连接数据库控制台
mysql -uroot -p

  如上面代码,在表seckill里面,我们在创建时间上用到了三个TIMESTAMP,注意这一点,我在编写建表sql的时候,将start_time和end_time写上了默认值,如果不写上默认值的话,数据库5.5在这一点上会出现问题,首先说当出现两个及以上TIMESTAMP建表会报什么错:

Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause 

  这个是mysql5.5的一个经常会遇到的报错信息,这句话的意思是什么呢?是说:不正确的表格定义,只允许一列时间戳列作为当前时间戳的默认或者更新项。在mysql5.5介绍中有这样一段话:

 One TIMESTAMP column in a table can have the current timestamp as the default value for initializing the column, as the auto-update value, or both. It is not possible to have the current timestamp be the default value for one column and the auto-update value for another column.

  而在mysql5.6.5中则有这样一段话:

Previously, at most one TIMESTAMP column per table could be automatically initialized or updated to the current date and time. This restriction has been lifted. Any TIMESTAMP column definition can have any combination of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses. In addition, these clauses now can be used with DATETIME column definitions. For more information, see Automatic Initialization and Updating for TIMESTAMP and DATETIME.

  两句话分别是什么意思呢?很明显,就是移除了以前版本的对值允许一列时间戳作为当前时间戳的更新或者默认项。所以解决办法两个:

  1. 升级mysql的数据库版本
  2. 对时间戳列赋予初始值

    编写实体类:seckill和seckillId

package org.seckill.entity;

import java.util.Date;

/**
 * Created by 荔枝 on 2016-11-11.
 */
public class Seckill {

    private long seckillId;

    private String name;

    private int number;

    private Date startTime;

    private Date endTime;

    private Date createTime;

    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;
    }


//   为了单元测试方便,覆写其toString()方法
    @Override
    public String toString() {
        return "Seckill{" +
                "seckillId=" + seckillId +
                ", name='" + name + '\'' +
                ", number=" + number +
                ", startTime=" + startTime +
                ", endTime=" + endTime +
                ", createTime=" + createTime +
                '}';
    }
}
package org.seckill.entity;

import java.util.Date;

/**
 * Created by 荔枝 on 2016-11-11.
 */
public class SuccessKilled {
    private long seckillId;

    private long userPhone;

    private Date create_time;

    private short state;

//    一个秒杀实体是对应多个秒杀成功的用户,是一个多对一,在多方吧一方的Seckill写出来,这是一个复核属性
    private Seckill seckill;

    public long getSeckillId() {
        return seckillId;
    }

    public void setSeckillId(long seckillId) {
        this.seckillId = seckillId;
    }

    public long getUserPhone() {
        return userPhone;
    }

    public void setUserPhone(long userPhone) {
        this.userPhone = userPhone;
    }

    public Date getCreate_time() {
        return create_time;
    }

    public void setCreate_time(Date create_time) {
        this.create_time = create_time;
    }

    public short getState() {
        return state;
    }

    public void setState(short state) {
        this.state = state;
    }

    public Seckill getSeckill() {
        return seckill;
    }

    public void setSeckill(Seckill seckill) {
        this.seckill = seckill;
    }

    @Override
    public String toString() {
        return "SuccessKilled{" +
                "seckillId=" + seckillId +
                ", userPhone=" + userPhone +
                ", create_time=" + create_time +
                ", state=" + state +
                '}';
    }
}

DAO接口编码

package org.seckill.dao;

import org.apache.ibatis.annotations.Param;
import org.seckill.entity.Seckill;

import java.util.Date;
import java.util.List;

/**
 * Created by 荔枝 on 2016-11-11.
 */
public interface SeckillDao {
    /**
     * 减库存
     * @param seckillId
     * @param killTime
     * @return
     */

    int reduceNumber(@Param("seckillId") long seckillId,@Param("killTime") Date killTime);

    /**
     * 根据ID查询秒杀对象
     * @param seckillId
     * @return
     */

    Seckill queryById(long seckillId);

    /**
     * 根据偏移量查询秒杀对象
     * @param offset
     * @param limit
     * @return
     */

    List<Seckill> queryAll(@Param("offset") int offset, @Param("limit") int limit);




}
package org.seckill.dao;

import org.apache.ibatis.annotations.Param;
import org.seckill.entity.SuccessKilled;

/**
 * Created by 荔枝 on 2016-11-11.
 */
public interface SuccessKilledDao {

    /**
     * 插入购买明细,可过滤重复秒杀
     * @param seckillId
     * @param userphone
     * @return
     */

    int insertSuccessKilled(@Param("seckillId") long seckillId, @Param("userphone") long userphone);

    /**
     * 根据ID查询SuccessKilled并携带秒杀产品对象实体
     * @param seckillId
     * @return
     */

    SuccessKilled queryByIdWithSeckill(@Param("seckillId") long seckillId, @Param("userphone") long userphone);
}

mybatis实现DAO编程实现

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.seckill.dao.SeckillDao">

    <!--目的:为DAO接口方法提供sql语句配置-->

    <update id="reduceNumber">
        update
          seckill
        SET
          number = number - 1
        where seckill_id = # {seckillId}
        and start_time &lt;= #{killTime}
        and end_time &gt;= #{killTime}
        and number > 0;
    </update>

    <select id="queryById" resultType="Seckill" parameterType="long">
        SELECT
          seckill_id,
          name,
          number,
          start_time,
          end_time,
          create_time
        FROM
          seckill
        WHERE
          seckill_id = #{seckill_id}
    </select>

    <select id="quertyAll" resultType="Seckill">
        SELECT
          seckill_id,
          name,
          number,
          start_time,
          end_time,
          crate_time
        FROM
          seckill
        ORDER BY create_time desc
        WHERE
          limit #{offset}, #{limit}
    </select>

</mapper>
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--目的:为DAO接口方法提供sql语句的配置-->
<mapper namespace="org.seckill.dao.SeckillDao">
    <!--主键冲突,报错-->
    <insert id="insertSuccessKilled">

        INSERT ignore
        INTO
          success_killed(seckill_id,user_phone,state)
        VALUES
          (#{seckillId},#{userPhone},0)
    </insert>

    <select id="queryByIdWithSeckill" resultType="SuccessKilled">
     -- 根据Id查询SuccessKilled并携带Seckill实体
     -- 如何告诉mybatis把结果映射到SuccessKilled同时映射seckill属性
     -- mybatisk可以自由控制sql
     SELECT
      sk.seckill_id,
      sk.user_phone,
      sk.create_time,
      sk.state,
      s.seckill_id as "seckill.seckill_id",
      s.name as "seckill.name",
      s.number as "seckill.number",
      s.start_time as "seckill.start_time",
      s.end_time as "seckill.end_time",
      s.create_time as "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.userphone = #{userphone}
    </select>
</mapper>

mybatis整合spring编码

  • 数据库相关参数属性配置:
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/seckill?useUnicode=true&characterEncoding=utf8
jdbc.username = root
password = root
  • spring与mybatis整合配置
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--配置整合mybatis的过程-->
    <!--1:配置数据库相关参数properties的属性:${url}-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--2:数据库的连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--配置连接池属性-->
        <property name="driverClass" value="${driver}"/>
        <property name="jdbcUrl" value="${url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${password}"/>

        <!--c3p0连接池的私有属性-->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!--关闭不自动commit-->
        <property name="autoCommitOnClose" value="false"/>
        <!--获取连接超时时间-->
        <property name="checkoutTimeout" value="1000"/>
        <!--当获取连接失败重试次数-->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

    <!--3:配置SqlSessionFactory对象-->
    <bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        <!--注入数据库连接池-->
        <property name="dataSource" ref="dataSource"/>

        <!--配置mybatis全局配置文件:mybatis-config.xml-->
        <property name="configLocation" value="classpath:mybatis-configs.xml"/>

        <!--扫描entity包 使用别名-->
        <property name="typeAliasesPackage" value="org.seckill.entity"/>

        <!--扫面sql配置文件,也就是mapper需要的xml文件-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!--4:配置扫面dao接口包,动态实现dao接口并注入到spring容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--注入sqlSession的过程-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>

        <!--给出扫描dao接口包-->
        <property name="basePackage" value="org.seckill.dao"/>
    </bean>

</beans>

编写测试DAO层单元测试

  • seckillDao单元测试(idea里面使用快捷键Ctrl+Shift+T快捷生成测试类)
package org.seckill.dao;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.seckill.entity.Seckill;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

import java.util.Date;
import java.util.List;

import static org.junit.Assert.*;

/**
 * Created by 荔枝 on 2016-11-16.
 */

/**
 * 配置spring和Junit的整合,Junit启动时加载springIOC容器
 * spring-test,junit
 */

@RunWith(SpringJUnit4ClassRunner.class)
//告诉Junit spring配置文件
@ContextConfiguration({"classpath:spring/spring-dao.xml"})
public class SeckillDaoTest {

    //注入Dao实现类依赖
    @Resource
    private SeckillDao seckillDao;

    @Test
    public void queryById() throws Exception {
        long id = 1000;
        Seckill seckill = seckillDao.queryById(id);
        System.out.println(seckill.getName());
        System.out.println(seckill);
    }

    @Test
    public void queryAll() throws Exception {
        //List<Seckill> queryAll(int offset, int limit);
        //java没有保存形参的记录queryAll(int offset, int limit)-->queryAll(arg0, arg1)
        //有多个参数的时候,在dao层形参前用@Param
        List<Seckill> seckills = seckillDao.queryAll(0,100);
        for (Seckill seckill : seckills){
            System.out.println(seckill);
        }

    }

    @Test
    public void reduceNumber() throws Exception {

        Date killTime = new Date();
        int updateCount = seckillDao.reduceNumber(1000L, killTime);
        System.out.println("updateCount=" + updateCount);

    }


}
  • SuccessKilledDao的单元测试
package org.seckill.dao;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.seckill.entity.Seckill;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

import java.util.Date;
import java.util.List;

import static org.junit.Assert.*;

/**
 * Created by hspcadmin on 2016-11-16.
 */

/**
 * 配置spring和Junit的整合,Junit启动时加载springIOC容器
 * spring-test,junit
 */

@RunWith(SpringJUnit4ClassRunner.class)
//告诉Junit spring配置文件
@ContextConfiguration({"classpath:spring/spring-dao.xml"})
public class SeckillDaoTest {

    //注入Dao实现类依赖
    @Resource
    private SeckillDao seckillDao;

    @Test
    public void queryById() throws Exception {
        long id = 1000;
        Seckill seckill = seckillDao.queryById(id);
        System.out.println(seckill.getName());
        System.out.println(seckill);
    }

    @Test
    public void queryAll() throws Exception {
        //List<Seckill> queryAll(int offset, int limit);
        //java没有保存形参的记录queryAll(int offset, int limit)-->queryAll(arg0, arg1)
        //有多个参数的时候,在dao层形参前用@Param
        List<Seckill> seckills = seckillDao.queryAll(0,100);
        for (Seckill seckill : seckills){
            System.out.println(seckill);
        }

    }

    @Test
    public void reduceNumber() throws Exception {

        Date killTime = new Date();
        int updateCount = seckillDao.reduceNumber(1000L, killTime);
        System.out.println("updateCount=" + updateCount);

    }


}

  此时一个简单的秒杀功能就实现完成了!后续问题优化会有二、三系列更新。

SpringMVC实战教程:构建高并发秒杀项目 Spring是一个开源的Java平台,最初由Rod Johnson创建,并于2003年首次发布。Spring的核心思想是“依赖注入”和“面向切面编程”,旨在简化Java企业应用开发。Spring框架通过抽象出许多通用的解决方案来降低开发复杂性,并提供了一整套的基础设施支持,使得开发者可以更加专注于业务逻辑的实现。Maven插件是Maven强大功能的来源。插件可以分为编译插件、测试插件、打包插件等多种类型。Maven通过插件来执行实际的任务。:用于编译Java源代码。:用于运行测试。 阅读详情

相关推荐

AI智能体协作:构建更精准的公司破产预测模型

公司破产预测对于金融机构、投资者和监管部门等具有至关重要的意义。准确的破产预测可以帮助金融机构提前做好风险防范,避免贷款损失;投资者可以根据预测结果调整投资组合,降低投资风险;监管部门可以及时发现潜在的金融风险,采取相应的监管措施。然而,传统的公司破产预测模型往往存在精度不高的问题,无法满足实际需求。本研究的目的是利用AI智能体协作的方式,构建一个更精准的公司破产预测模型。通过将多个AI智能体的优势进行整合,充分挖掘公司财务数据、市场数据等多源数据中的信息,提高预测的准确性和可靠性。

2501_92132293的博客 1082

Spring boot整合Mybatis(超详细!)

简介 在传统的SSM框架中,使用Mybatis需要大量的XML配置,而在Spring Boot中,Mybatis官方提供了一套自动化配置方案,可以做到Mybatis开箱即用。 步骤1:创建项目 创建Spring Boot项目,添加Mybatis依赖,数据库驱动依赖以及数据库连接池依赖: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="ht

m0_46741750的博客 1万+

Docker网络冲突?手把手教你解决Dify社区版无法访问172.18.0.0网段的问题

本文详细解析了在部署Dify社区版时,因Docker默认网段与局域网冲突导致无法访问172.18.0.0网段的问题。通过剖析Docker网络原理,提供了修改Docker守护进程默认地址池的根治方案,并介绍了在Compose文件中指定自定义网络等备选方法,帮助用户彻底解决网络冲突,保障服务稳定运行。

p8q9r0的博客 486

SpringBoot+Mybatis完成商品秒杀项目之商品模块开发(七)

商品模型管理——商品创建 1.首先设计商品领域模型 public class ItemModel { private Integer id; //商品名称 private String title; //商品价格 private BigDecimal price; //商品的库存 private Integer stock; ...

dong_learnning的博客 326

用友YonSuite产品实操手把手教学(图文版)

用友YonSuite

ct341688的博客 8180

告别命令行恐惧!用nTopology可视化工具5分钟搞定三维Voronoi泡沫建模

本文介绍如何利用nTopology可视化工具快速生成三维Voronoi泡沫结构,无需编程即可完成复杂建模。Voronoi结构在轻量化设计、能量吸收和生物医学等领域具有重要应用,传统命令行方法门槛较高。通过nTopology的四步流程,用户可在5分钟内创建仿真就绪模型,大幅提升设计效率。

weixin_30764771的博客 427

springboot框架(6):整合MyBatis-Plus和简单操作

整合MyBatis-Plus的小案例 MyBatis-Plus官网:https://baomidou.com/准备的表数据,附sql 配置application.yml文件 编写pojo和mapper 编写测试用例并执行测试

不积跬步,无以至千里 844

【Proteus仿真】74HC595+74LS154驱动显示16X16点阵

【Proteus仿真】74HC595+74LS154驱动显示16X16点阵

perseverance51博客 2893

SpringBoot+Mybatis完成商品秒杀项目之秒杀模块开发(九)

第六章 秒杀模块开发 6.1 秒杀模型管理——活动模型创建 1.使用添加依赖 <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.9.1</version> </depend...

dong_learnning的博客 484

【即插即用模块】Transformer篇 | TCSVT 2025 | DAFM:双注意力聚合+反向跨模态筛选,特征精准捕捉并融合!

本文提出了一种双模态注意力融合模块(DAFM),用于增强多模态图像融合任务中的特征交互。该模块通过双注意力聚合机制,结合自注意力与跨模态注意力,有效提升特征融合效果。DAFM采用可学习平衡因子动态调整注意力权重,并运用深度卷积降低计算复杂度。实验结果表明,该模块能显著提升多模态图像融合质量,适用于RGB-红外等双模态视觉任务。模块代码实现简洁,可直接集成到现有网络中作为特征融合层使用。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 177

某物data魔改与变种算法还原(含加解密Py纯算)

某物data加解密、设备指纹魔改、变异、自定义加密分析与纯算还原

吴秋霖的博客 1283

java实现高并发秒杀---简单示例 springboot+redis+rabbitmq+mybatis

前言 ​ 为什么要写秒杀系统呢,像现在限时秒杀已经成为电商项目中的一种常态,像现在的一些龙头电商企业都具备限时秒杀活动,这样能调动用户的购买兴趣的活动,能够给项目带来更大的活力,所以对于这个秒杀功能不说是一定能写,但是一定要了解他。 原理 秒杀与其他业务最大的区别在于,在秒杀的瞬间,系统的并发量和吞吐量会非常大,与此同时,网络的流量也会瞬间变大。 对于系统并发量变大问题,这里的核心在于如何在大并...

isWeisen的博客 3797

计算机毕设项目一:基于卷积神经网络、resnet、VGG化妆品分类识别 完整代码数据可直接运行

计算机毕设项目一:基于卷积神经网络、resnet、VGG化妆品分类识别 完整代码数据可直接运行

656

基于SpringMVC+Spring+MyBatis实现高并发秒杀API

          基于SpringMVC+Spring+MyBatis实现高并发秒杀项目   项目介绍与说明 使用的相关技术 秒杀业务分析 DAO层接口设计与实现 秒杀业务接口设计与实现 前端交互设计  MVC设计与实现 高并发优化策略及实现 GITHUB下载地址:https://github.com/xiezengcheng/seckill 项目介绍与说明 1)这...

wonderfulwork 1109

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

新人一看就懂:Spring Boot+Spring mvc+Mybatis的基础框架demo

Spring Boot的设计目的是来简化新Spring应用的初始搭建以及开发过程,大大减少了代码量,通过这篇文章你可以清楚的看到。这是一个基于Spring Boot的简单demo,希望读者可以通过这篇文章大概能看懂这一个简单的框架搭建。后续我会陆续更新,微服务架构(Spring Boot、Spring Cloud)、分布式架构(Dobbo+Zookeeper)、大数据架构以及源码解析等相关的文章,感兴趣的话可以关注一下。

程序员云帆哥的博客 2万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

高并发秒杀业务 DAO层

为什么要学习秒杀 秒杀的业务场景具有典型的事务特性 秒杀/红包类需求越来越常见 面试常问问题 相关技术介绍 Mysql (①表设计 ②SQL技巧 ③事务和行级锁) MyBatis(①DAO层的设计开发 ②MyBatis合理使用 ③Mybatis和Spring整合) Spring(①Spring IOC整合Service ②声明式事务运用) SpringMVC(①Restful接口...

Javaer`s blog 248

Java高并发秒杀API-Java高并发秒杀APi之业务分析与DAO层代码编写

总结复习一下之前的demo,本demo使用SpringMVC+Spring+MyBatis+MySQL实现一个秒杀系统。 1、Java高并发秒杀API之业务分析与DAO层 2、Java高并发秒杀API之web层 3、Java高并发秒杀API之Service层 4、Java高并发秒杀API之高并发优化 其实这几个流程也就是开发的流程,首先从DAO层开始开发,从后往前开发,开始Coding吧! 项目环...

小强博客 770

Java高并发秒杀——业务分析与DAO层

Java高并发秒杀——业务分析与DAO层 一、业务分析与DAO层分析   1、使用IDEA创建Maven项目   2、合理地设计数据库   3、MyBatis的相关配置与接口式编程   4、MyBatis整合Spring   5、利用Junit单元测试DAO层 二、在IDEA中创建Maven项目   引用别人构建Maven的步骤(IDEA为2018版本)   http://yayihouse.co...

xiaoaxiao 474

SSM实战项目——Java高并发秒杀API

SSM实战项目——Java高并发秒杀API 项目介绍 何为秒杀? 所谓“秒杀”,就是网络卖家发布一些超低价格的商品,所有买家在同一时间网上抢购的一种销售方式。由于商品价格低廉,往往一上架就被抢购一空,有时只用一秒钟。 为何选择Java高并发秒杀作为实战项目? 秒杀业务场景具有典型事务特性 秒杀/红包类需求越来越常见 为何使用SpringMVC+Spri...

不积跬步,无以至千里 1万+

一、高并发秒杀API简介与业务分析

1 简介        该项目主要整合运用Mybatis+Spring+Spring MVC三个框架来开发;同时这三个框架也是互联网公司的常用框架,比如美团、阿里、搜狐、京东等大型互联网网站常用这三个框架,主要是因为这三个框架易于使用并且比较轻量级,另外一个原因就是低代码侵入性,并且拥有成熟的用户群和社区。        现在网络上秒杀和红包类业务需求越来越常见,这种业务是一种竞争性的产品

此处省略三千字 2366

SSM框架实现高并发秒杀API学习笔记

慕课网yijun zhang老师的《Java高并发秒杀API》系列课程学习总结 maven命令创建web骨架项目 mvn archetype:generate -DgroupId=org.seckill -DartifactId=seckill -DarchetypeArtifactId=maven-archetype-webapp groupId和artifactId用来标注项目坐标,项目名为o...

weixin_33859504的博客 252

java高并发秒杀项目之Dao

Java高并发秒杀APi之业务分析与DAO层代码编写 具体可以参考github Maven创建项目seckill mvn archetype:generate -DgroupId=cn.codingxiaxw.seckill -DartifactId=seckill -Dpackage=cn.codingxiaxw.seckill -Dversion=1.0-SNAPSHOT -Darchetyp...

loserChen的博客 285

SSM+Redis秒杀系统---业务分析

SSM+Redis秒杀系统项目介绍和面试问题总结

weixin_43224291的博客 473

Java高并发秒杀API之业务分析与DAO层

目录(?)[+] 课程介绍 高并发和秒杀都是当今的热门词汇,如何使用Java框架实现高并发秒杀API是该系列课程要研究的内容。秒杀系列课程分为四门,本门课程是第一门,主要对秒杀业务进行分析设计,以及DAO层的实现。课程中使用了流行的框架组合SpringMVC+spring+MyBatis,还等什么,赶快来加入吧! 第1章 课程介绍  本章介绍秒杀系统的技术内

my_name_nb的博客 985

推荐使用:Imooc Java 高并发秒杀系统

推荐使用:Imooc Java 高并发秒杀系统 1、项目介绍 欢迎探索并使用这个由 Imooc 提供的 Java 高并发秒杀在线购物系统。它是一个专为处理大量用户请求而设计的系统,适用于电子商务和零售行业的高流量活动。该系统采用了先进的技术和架构,保证了在高峰期的稳定性和高性能。 2、项目技术分析 这个系统的背后是强大的技术栈,包括: Spring 和 SpringMVC:提供了全面的应用程序结...

gitblog_00082的博客 402
上一篇: JDBC
下一篇: mysql之存储过程和函数
荔枝妹妹
博客等级 码龄10年 6粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值