一: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接口路径不一致;

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

  1. SSM实战——秒杀系统之Service层接口设计与实现、Spring托管、声明式事务

    一:Service层接口设计 准备工作:新建三个包:service包.exception包.dto包,分别用来存放业务接口.自定义异常类.dto类. 1:定义接口 package org.myseck ...

  2. SSM实战——秒杀系统之Web层Restful url设计、SpringMVC整合、页面设计

    一:Spring整合SpringMVC 1:编写web.xml,配置DispatcherServlet <web-app xmlns="http://java.sun.com/xml/ ...

  3. SSM实战——秒杀系统之创建项目、管理依赖、设计数据库

    注:本项目使用Myeclipse开发. 一:项目创建 1:使用Myeclipse创建一个web project,命名为MySeckill,并转换为Maven项目. 2:创建项目文件目录如下: 上面四个 ...

  4. SSM实战——秒杀系统前言

    项目来源:慕课网http://www.imooc.com/u/2145618/courses?sort=publish 项目开发流程:整合SSM框架——项目需求分析与实现——解决高并发优化 所用技术: ...

  5. SSM实战——秒杀系统之高并发优化

    一:高并发点 高并发出现在秒杀详情页,主要可能出现高并发问题的地方有:秒杀地址暴露.执行秒杀操作. 二:静态资源访问(页面)优化——CDN CDN,内容分发网络.我们把静态的资源(html/css/j ...

  6. [MyBatis]DAO层只写接口,不用写实现类

    团队开发一个项目,由老大架了一个框架,遇到了DAO层不用写接口了,我也是用了2次才记住这个事的,因为自己一直都是习惯于写DAO层的实现类,所以,习惯性的还是写了个实现类.于是遇到错误了. 找不到那个方 ...

  7. 5.7 Liquibase:与具体数据库独立的追踪、管理和应用数据库Scheme变化的工具。-mybatis-generator将数据库表反向生成对应的实体类及基于mybatis的mapper接口和xml映射文件(类似代码生成器)

    一. liquibase 使用说明 功能概述:通过xml文件规范化维护数据库表结构及初始化数据. 1.配置不同环境下的数据库信息 (1)创建不同环境的数据库. (2)在resource/liquiba ...

  8. 通过数据库中的表,使用 MyEclipse2017的反向生成工具-->hibernate反转引擎引擎(MyEclipse2017自带的插件) 来反转生成实体类和对应的映射文件

    通过数据库中的表,使用 MyEclipse2017的反向生成工具-->hibernate反转引擎引擎(MyEclipse2017自带的插件) 来反转生成实体类和对应的映射文件   文章目录 Ja ...

  9. SSM实现秒杀系统案例

    ---------------------------------------------------------------------------------------------[版权申明:本 ...

随机推荐

  1. TrafficStats——流量统计类的范例,获取实时网速

    2.3开始android就提供来这个类的API,这样我们就可以方便的用他来实现统计手机流量来.这个类其实也很简单,我贴上他的几个方法,大家一看就知道怎么用了. static long getMobil ...

  2. HipHop PHP & HHVM资料收集

    百度百科 HipHop PHP实战(详解web运行模式) 百度 PHP7和HHVM的性能之争

  3. [转]Linux系统下如何查看及修改文件读写权限

    转自 :http://www.cnblogs.com/CgenJ/archive/2011/07/28/2119454.html 查看文件权限的语句: 在终端输入:ls -l xxx.xxx (xxx ...

  4. osg for android学习之一:windows下编译(亲测通过)【转】

    1. 首先需要一个OSG for android的环境 (1)NDK 现在Eclipse 对NDK已经相当友好了,已经不需要另外cygwin的参与,具体可以参考 Android NDK开发篇(一):新 ...

  5. Isilon上数据是如何存放的?

    OneFS的文件系统的block size是8KB.这是OneFS上最小的数据存储单位了,比8KB小的文件都要占掉8KB大小的空间.连续的8KB的block会被用来存储文件的数据,但最多不会超过16个 ...

  6. C# Win32控制台应用程序忽略 Ctrl + C,阻止程序退出

    C# Win32控制台应用程序忽略 Ctrl + C,阻止程序退出,这里使用到了Windows API SetConsoleCtrlHandler函数 注意:在VS中调试执行时,在处理程序例程中设置断 ...

  7. Grid 拾遗

    *.GridSplitter属性是Grid面板的一个特性.(1)预留一行或一列,专门用于放置 GridSplitter对象,如果是行的话,把其Height 设置为 Auto,如果是列的话,把其 Wid ...

  8. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(三)安装spark2.2.1

    如何搭建配置centos虚拟机请参考<Kafka:ZK+Kafka+Spark Streaming集群环境搭建(一)VMW安装四台CentOS,并实现本机与它们能交互,虚拟机内部实现可以上网.& ...

  9. 主成分分析(PCA)原理及推导

    原文:http://blog.csdn.net/zhongkejingwang/article/details/42264479 什么是PCA? 在数据挖掘或者图像处理等领域经常会用到主成分分析,这样 ...

  10. c/c++ sizeof运算符详解以及对象大小

    原文:http://krystism.is-programmer.com/posts/41468.html 学过c的都知道sizeof运算符.不过还是需要注意以下几点.先从c的sizeof说起: 1. ...