SSM实战——秒杀系统之DAO层实体定义、接口设计、mybatis映射文件编写、整合Spring与Mybatis...

一:DAO实体编码

1:首先,在src目录下,新建org.myseckill.entity包,用于存放实体类:

2:实体类设计

根据前面创建的数据库表以及映射关系,创建实体类。

表一:秒杀商品表

对应实体类:

package org.myseckill.entity;

import java.util.Date;

public class Seckill {
    private String SeckillId;
    
    private String name;
    
    private int number;
    
    private Date startTime;
    
    private Date endTime;
    
    private Date createTime;

    public String getSeckillId() {
        return SeckillId;
    }

    public void setSeckillId(String seckillId) {
        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 + "]";
    }
    
    
}

 

表二:秒杀成功记录表

对应实体类:

package org.myseckill.entity;

import java.util.Date;

public class SuccessKilled {
    private long SeckillId;
    
    private long userPhone;
    
    private int state;
    
    private Date createTime;
    
    //映射关系:多对一
    private Seckill seckill;

    public long getSeckillId() {
        return SeckillId;
    }

    public void setSeckillId(long seckillId) {
        SeckillId = seckillId;
    }

    public String getUserPhone() {
        return userPhone;
    }

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

    public int getState() {
        return state;
    }

    public void setState(int 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 [SeckillId=" + SeckillId + ", userPhone="
                + userPhone + ", state=" + state + ", createTime=" + createTime
                + ", seckill=" + seckill + "]";
    }
    
}

 

二:DAO类编码

1:在src.org.myseckill目录下,再新建一个包dao,用于存放dao接口。

2:编写操作seckill表的dao接口类:

package org.myseckill.dao;

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

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

//操作秒杀商品表,主要是增删改查
public interface SeckillDao {
    
    //删:根据秒杀的商品ID减少对应ID的商品数量
    //参数使用@Param为参数值赋予一个名字,对应xml中sql语句的{参数名}
    int reduceNumber(@Param("seckillId")long seckillId,@Param("killTime")Date killTime);
    
    //查:根据id查找相应商品记录,返回一个实体类
    Seckill queryById(long seckillId);
    
    //查:分页查询
    List<Seckill> queryAll(@Param("offset")int offset,@Param("limit")int limit);
    
}

 

3:编写操作successKilled表的dao接口类:

package org.myseckill.dao;

import org.apache.ibatis.annotations.Param;
import org.myseckill.entity.Seckill;
import org.myseckill.entity.SuccessKilled;

public interface SuccessKilledDao {
    
    //增:增加一条秒杀成功的记录,传入秒杀的商品ID以及进行秒杀操作的手机号
    int insertSuccessKilled(@Param("seckillId")long seckillId,@Param("userPhone")long userPhone);
    //查:查找某用户对某商品的秒杀记录
    SuccessKilled queryByIdWithSeckill(@Param("seckillId")long seckillId,@Param("userPhone")long userPhone);

}

 

 

三:Mybatis映射文件编写

配置类文件一致放在src/main/resources目录下管理。

1:在resources目录下新建 mybatis-config.xml,Mybatis的全局配置文件,再创建一个文件夹mapper用于存放mybatis关于不同数据库表的操作映射文件

2:编写mybatis-config.xml

首先,到Mybatis官网上,复制配置文件的dtd头。网址:http://www.mybatis.org/mybatis-3/zh/getting-started.html

然后,配置数据源、mapper等。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">

  <configuration>
  
     <settings>
         <!-- 使用jdbc的getGeneratedKeys 获取数据库自增主键值 -->
        <setting name="useGeneratedKeys" value="true"/>
        <!-- 使用列别名替换列名 默认:true -->
        <setting name="useColumnLabel" value="true"/>
        <!-- 开启驼峰命名转换 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>         
     </settings>
  </configuration>

3:在mapper目录下,为对应的dao接口编写同名的xml映射文件:

SeckillDao.xml:

<?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.myseckill.dao.SeckillDao" >
    <update id="reduceNumber">
    update
      seckill
    set
      number=number - 1
    where
      seckill_id = #{seckillId}
    and
      start_time <![CDATA[ <= ]]> #{killTime}
    and
      end_time >= #{killTime}
    and 
      number>0;
    </update>
    
    <select id="queryById" parameterType="long" resultType="Seckill">
      select seckill_id, name, number, start_time, end_time, create_time 
      from seckill
      where seckill_id = #{seckillId}
    </select>

    <select id="queryAll" resultType="Seckill" parameterType="int">
    select seckill_id, name, number, start_time, end_time, create_time 
    from seckill
    order by create_time desc
    limit #{offset},#{limit}
    </select> 
    
</mapper>

SuccessKilledDao.xml

<?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.SuccessKilledDao">
    <insert id="insertSuccessKilled">
        <!-- ignore:主键冲突时,返回0,不报错 -->
        insert ignore into success_killed(seckill_id,user_phone,state)
        values(#{seckillId},#{userPhone},0)
    </insert>
    <select id="queryByIdWithSeckill" resultType="SuccessKilled">
        select
          sk.seckill_id,
          sk.user_phone,
          sk.create_time,
          sk.state,
          s.seckill_id "seckill.seckill_id",//多对一关系:SuccessKilled实体中的seckill成员属性的属性值赋值
          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与Mybatis

整合的目标:更少的编码(mabatis接口无需手动实现)、更少的配置(包扫描)、dao托管(spring自动注入dao实现类)、灵活性(自定制sql语句、自由传参、结果集自动转换)

1:在resources目录下新建一个文件夹spring,用于保存Spring相关的配置文件。

在spring下新建spring-dao.xml,用于整合mabatis。

 在resources下新建一个jdbc.properties文件,配置数据库连接相关。

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8
username=root
password=root

2:编写spring-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.xsd">
  <!-- 1:配置数据库参数文件所在 -->
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties" />
    </bean>

   <!-- 2:配置数据库连接池:使用c3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driver}" />
        <property name="jdbcUrl" value="${url}" />
        <property name="user" value="${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-config.xml" />
        <!-- 扫描entity 使用别名 -->
        <property name="typeAliasesPackage" value="org.myseckill.entity"/>
        <!-- 扫描sql映射文件:mapper需要的xml文件 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>
    
    <!-- 4:配置扫描 Dao接口包,由factory动态实现Dao接口,注入到Spring容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- 给出需要扫描的Dao接口 -->
        <property name="basePackage" value="org.myseckill.dao"/>
    </bean>

</beans>

 

五:单元测试

在test/main/java下,新建包org.myseckill.dao,并创建SeckillDao的测试类:SeckillDaoTest。

package org.myseckill.dao;

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

import javax.annotation.security.RunAs;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.myseckill.entity.Seckill;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/spring-dao.xml")
public class SeckillDaoTest {
    //要测试SeckillDao,则定义这样一个对象,并由spring自动注入
    @Autowired
    private SeckillDao seckillDao;
    
    @Test
    public void testQueryById(){
        long id = 1000;
        Seckill seckill = seckillDao.queryById(id);
        System.out.println(seckill);
    }
    
    @Test
    public void testQueryAll(){
        //java没有保存形参的记录:queryAll(int offset,int limit) --> queryAll(arg0, arg1)
        //所以需要:queryAll(@Param("offset")int offset, @Param("limit")int limit);
        List<Seckill> list = seckillDao.queryAll(0,100);
        for (Seckill seckill:list) {
            System.out.println(seckill);
        }
    }
    
    @Test
    public void testReduceNumber(){
        int updateCount = seckillDao.reduceNumber(1000, new Date());
        System.out.println(updateCount);
    }    
}

同理,创建SuccessKilledDaoTest

package org.myseckill.dao;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.myseckill.dao.SuccessKilledDao;
import org.myseckill.entity.SuccessKilled;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/spring-dao.xml")
public class SuccessKilledDaoTest {
    @Autowired
    SuccessKilledDao successKilledDao;
    
    @Test
    public void testInsertSuccessKilled(){
        int insertCount = successKilledDao.insertSuccessKilled(1001, 15764210366L);
        System.out.println(insertCount);
    }
    
    @Test
    public void testQueryByIdWithSeckill(){
        SuccessKilled successKilled = successKilledDao.queryByIdWithSeckill(1000, 15764210366L);
        System.out.println(successKilled);
        System.out.println(successKilled.getSeckill());
    }

}

 

测试记录一:ClassNotFound:com.mysql.Driver加载失败

原因排除:

首先检查是否没导入这个jar包,由于是用maven管理的,检查pom.xml已经导入了这个包,依赖库里也已经下载;

然后检查是否下载的包损坏或版本不对:手动下载mysql-connector-java-5.1.5.jar包,拷贝到目录下并添加到buildPath,测试通过。

结论:是pom.xml中导入的jar包版本不对,换成5.1.5的即可。

 

测试记录二:BindingException: Invalid bound statement (not found) 

Mybatis接口绑定错误:

首先检查是否dao接口中的方法与xml中配置的id名字不一;

然后检查是否xml中mapper标签的namespace属性与dao接口路径不一致;

转载于:https://www.cnblogs.com/ygj0930/p/6905871.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值