DAO(Data Access Object) 數據訪問對象
首先須要建立秒殺庫存表和秒殺成功明細表,以下所示: 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 COMMENT '秒殺開啓時間', `end_time` timestamp NOT NULL 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 AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='秒殺庫存表'; insert into seckill(name,number,start_time,end_time) values ('1000元秒殺iphone6',100,'2017-04-30 00:00:00','2017-06-02 00:00:00'), ('500元秒殺ipad2',200,'2017-04-30 00:00:00','2017-06-02 00:00:00'), ('300元秒殺小米4',300,'2017-04-30 00:00:00','2017-06-02 00:00:00'), ('200元秒殺紅米note',400,'2017-05-30 00:00:00','2017-06-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='秒殺成功明細表'; dao包須要的相關類名和函數名如表6-9所示。
SeckillDao.java: public interface SeckillDao { int reduceNumber(@Param("seckillId") long seckillId,@Param("killTime") Date killTime); Seckill queryById(long seckillId); List<Seckill> queryAll(@Param("offset") int offet, @Param("limit") int limit); void killByProcedure(Map<String,Object> paramMap); } SuccessKilledDao.java: public interface SuccessKilledDao { int insertSuccessKilled(@Param("seckillId") long seckillId ,@Param("userPhone") long userPhone); SuccessKilled queryByIdWithSeckill(@Param("seckillId") long seckillId, @Param("userPhone") long userPhone); } 基於MyBatis來實現咱們設計的Dao層接口。首先須要配置咱們的MyBatis,在resources包下建立MyBatis全局配置文件mybatis-config.xml文件。 <configuration> <settings> <setting name="useGeneratedKeys" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> </configuration> 配置文件建立好後咱們須要關注的是Dao接口該如何實現,mybatis爲咱們提供了mapper動態代理開發的方式爲咱們自動實現Dao的接口。在mapper包下建立對應Dao接口的xml映射文件,裏面用於編寫咱們操做數據庫的sql語句,SeckillDao.xml和SuccessKilledDao.xml。 SeckillDao.xml: <mapper namespace="org.seckill.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" resultType="Seckill" parameterType="long"> select seckill_id,name,number,start_time,end_time,create_time from seckill where seckill_id = #{seckillId} </select> <select id="queryAll" resultType="Seckill"> select seckill_id,name,number,start_time,end_time,create_time from seckill order by create_time desc limit #{offset},#{limit} </select> <select id="killByProcedure" statementType="CALLABLE"> call execute_seckill( #{seckillId,jdbcType=BIGINT,mode=IN}, #{phone,jdbcType=BIGINT,mode=IN}, #{killTime,jdbcType=TIMESTAMP,mode=IN}, #{result,jdbcType=INTEGER,mode=OUT} ) </select> </mapper> SuccessKilledDao.xml: <mapper namespace="org.seckill.dao.SuccessKilledDao"> <insert id="insertSuccessKilled"> 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", 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> MyBatis和Spring的整合,整合目標: (1)更少的編碼:只寫接口,不寫實現類。 (2)更少的配置:別名、配置掃描映射xml文件、dao實現。 (3)足夠的靈活性:自由定製SQL語句、自由傳結果集自動賦值。 在spring包下建立一個spring-dao.xml,用於配置dao層對象的配置文件,在resources包下建立jdbc.properties.xml,用於配置數據庫的鏈接信息,配置以下。 spring-dao.xml: <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"> <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.username}"/> <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"/> <property name="acquireRetryAttempts" value="2"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="typeAliasesPackage" value="org.seckill.entity"/> <property name="mapperLocations" value="classpath:mapper/*.xml"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <property name="basePackage" value="org.seckill.dao"/> </bean> <bean id="redisDao" class="org.seckill.dao.cache.RedisDao"> <constructor-arg index="0" value="localhost"/> <constructor-arg index="1" value="6379"/> </bean> </beans> jdbc.properties.xml: jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/seckill?useUnicode=true&characterEncoding=utf8 jdbc.username=root jdbc.password=123456