模仿天貓實(shí)戰(zhàn)【SSM版】——項(xiàng)目起步

前言:現(xiàn)在自己的學(xué)習(xí)似乎遇到了瓶頸添坊,感覺學(xué)習(xí)了 SSM 之后有一些迷茫走哺,不知道接下來該往哪里去努力了串绩,我覺得這是個很不好的狀態(tài),為了度過這段時期枉圃,我準(zhǔn)備把天貓模仿下來(給自己找點(diǎn)事做)之后開始去鞏固 Java 的基礎(chǔ)知識,也準(zhǔn)備好暑假去找實(shí)習(xí)庐冯。

第一步:需求分析

首先要確定要實(shí)現(xiàn)哪些功能孽亲,需要對需求進(jìn)行完整的分析,才能在編寫項(xiàng)目的時候有條不紊展父,我們的目的很明確:就是模仿天貓前端 + 自己實(shí)現(xiàn)后端返劲。并且盡最大努力去降低這個項(xiàng)目的復(fù)雜度(畢竟高深的東西不懂)玲昧。

前端需求分析

規(guī)定:全天貓沒有店鋪,就只有唯一一家叫做 Tmall 的商家篮绿,賣所有的東西孵延。

  • 1.數(shù)據(jù)的顯示:

首頁數(shù)據(jù)顯示分析:

首先是搜索欄下方的九個商品,需要從數(shù)據(jù)庫中取出銷量最高的幾個產(chǎn)品亲配,關(guān)于標(biāo)紅的關(guān)鍵字尘应,是要滿足一定條件的,比如:這一個星期內(nèi)銷量超過多少...

接著是分類導(dǎo)航欄吼虎,首先是商品分類右邊固定的兩個鏈接【天貓超市】和【天貓國際】犬钢,還有緊跟著的八個超鏈,這個可以設(shè)計(jì)為一個單表思灰,存儲它顯示的文字和鏈接過去的地址玷犹,然后是具體的 16 個分類以及輪播:

下面的具體產(chǎn)品展示比較復(fù)雜,我們可以自己做一下簡化洒疚,比如就展示幾個產(chǎn)品比較多的固定的幾個分類就好了歹颓,其他的就直接舍棄:

  • 總結(jié): 總之就是需要顯示各種數(shù)據(jù)庫中的數(shù)據(jù)
  • 2.登錄/注冊頁

需要有一個登錄/注冊頁,能夠完成用戶的登錄和注冊功能油湖,并能提供基礎(chǔ)的例如判斷空值等功能巍扛。

  • 3.產(chǎn)品搜索頁

左上角的圖標(biāo)我們可以統(tǒng)一簡化成 Tmall 的圖片,商品圖片肺魁,我們可以整個大分類使用一張圖电湘,主要就是實(shí)現(xiàn)排序功能還有搜索功能

  • 4.產(chǎn)品展示頁

天貓?jiān)漠a(chǎn)品展示頁有些復(fù)雜,我們可以自己簡化一下鹅经,就不要選這么多東西寂呛,都是一口價(jià),

另外下方規(guī)格參數(shù)和評價(jià)都不能省略:

  • 5.購物車/購買頁面

第二步:表結(jié)構(gòu)設(shè)計(jì)

根據(jù)對于前端的分析瘾晃,數(shù)據(jù)庫有了一些眉目贷痪,為了簡化項(xiàng)目的難度,所以我們需要自己想點(diǎn)辦法蹦误,先來構(gòu)思一下大概需要一些什么樣的表:

我大概就想出來需要用到這些表劫拢,我們一個一個來創(chuàng)建它們:

表一:分類表

首先我們需要一個表來存儲我們的分類信息,也就是【女裝/內(nèi)衣】强胰、【男裝/運(yùn)動戶外】在內(nèi)的 16 個分類舱沧,為了高度一致,這 16 個分類不能多也不能少偶洋。

為了簡化任務(wù)熟吏,可以觀察出,【熱門手機(jī)】、【特色手機(jī)】分欄下的東西都是【手機(jī)/數(shù)碼/電腦辦公】類別里的東西牵寺,所以我們直接砍掉悍引,右邊的一些圖片超鏈也給直接砍掉,我們規(guī)定每一行顯示的產(chǎn)品數(shù)目就可以了帽氓,這樣就簡單多了趣斤。

CREATE TABLE category (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) NOT NULL COMMENT '分類的名字',
  PRIMARY KEY (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

表二:商品分類右邊的超鏈表

即在【天貓國際】右邊的 8 個超鏈,我們單獨(dú)新建一個表來存儲超鏈顯示的文字和鏈接的地址黎休,這樣就可以任意的修改其內(nèi)容:

百度翻譯【推薦鏈接】翻譯為【Referral links】浓领,那我們也這么給我們的表命名好了:

CREATE TABLE referal_link (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  text varchar(255) NOT NULL COMMENT '超鏈顯示的文字',
  link varchar(255) NOT NULL COMMENT '超鏈的地址',
  PRIMARY KEY (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

表三:產(chǎn)品表

每個分類下都要一定的產(chǎn)品,這些產(chǎn)品還有自己的一些屬性奋渔,所以另外需要屬性表镊逝,這個表另外創(chuàng)建,我們先來觀察一下一個產(chǎn)品表需要一些什么東西:

  • 用于展示的 5 張圖片
  • 產(chǎn)品名稱
  • 小標(biāo)題(即名稱下面一排標(biāo)紅的小字)
  • 價(jià)格(就一口價(jià)嫉鲸,沒別的)
  • 銷量(別月銷量了撑蒜,能簡化就簡化一下)
  • 累計(jì)評價(jià)(還需要設(shè)計(jì)一個評價(jià)表)
  • 庫存
  • 屬性(需要關(guān)聯(lián)另外的屬性表)
CREATE TABLE product (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) NOT NULL COMMENT '產(chǎn)品的名稱',
  sub_title varchar(255) DEFAULT NULL COMMENT '小標(biāo)題',
  price float DEFAULT NULL COMMENT '價(jià)格',
  sale int(11) DEFAULT NULL COMMENT '銷量',
  stock int(11) DEFAULT NULL COMMENT '庫存',
  category_id int(11) DEFAULT NULL COMMENT '對應(yīng)的分類id',
  PRIMARY KEY (id),
  CONSTRAINT fk_product_category FOREIGN KEY (category_id) REFERENCES category (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
  • 注意: 其中產(chǎn)品圖片,累計(jì)評價(jià)玄渗,屬性都作為單獨(dú)的表存在并讓當(dāng)前表的 id 作為外鍵

表四:屬性表

去掉詳細(xì)的規(guī)格參數(shù)劃分座菠,其實(shí)屬性也就是一個名字而已(簡化簡化簡化)。

CREATE TABLE property (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) DEFAULT NULL COMMENT '屬性名稱',
  product_id int(11) NOT NULL COMMENT '對應(yīng)的產(chǎn)品id',
  PRIMARY KEY (id),
  CONSTRAINT fk_property_product FOREIGN KEY (product_id) REFERENCES product(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 突然想到的問題:
    每一個產(chǎn)品的屬性其實(shí)是很多的藤树,如果每一個產(chǎn)品都對應(yīng)很多屬性的話浴滴,對于天貓這樣的數(shù)據(jù)量來說,應(yīng)該會讓數(shù)據(jù)庫爆炸的吧...
  • 改進(jìn)方法:
    將屬性表關(guān)聯(lián)到 category 表上岁钓,因?yàn)槠鋵?shí)每一個分類下的產(chǎn)品的屬性差不多升略!

修改數(shù)據(jù)庫

根據(jù)以上問題,修改一下數(shù)據(jù)庫表之間的關(guān)系

并將屬性表的外鍵修改為 category 的主鍵:

CREATE TABLE property (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) DEFAULT NULL COMMENT '屬性名稱',
  category_id int(11) NOT NULL COMMENT '對應(yīng)的分類id',
  PRIMARY KEY (id),
  CONSTRAINT fk_property_category FOREIGN KEY (category_id) REFERENCES category(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表五:屬性值表

其中就是保存了對應(yīng)屬性的值屡限,并且應(yīng)該有兩個外鍵品嚣,一個指向 Property 表,而另一個則指向 Product 表

CREATE TABLE property_value (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  product_id int(11) NOT NULL COMMENT '對應(yīng)產(chǎn)品id',
  properti_id int(11) NOT NULL COMMENT '對應(yīng)屬性id',
  value varchar(255) DEFAULT NULL COMMENT '具體的屬性值',
  PRIMARY KEY (id),
  CONSTRAINT fk_property_value_property FOREIGN KEY (properti_id) REFERENCES property (id),
  CONSTRAINT fk_property_value_product FOREIGN KEY (product_id) REFERENCES product (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

表六:產(chǎn)品圖片表

這個表名義上是保存了產(chǎn)品的圖片钧大,其實(shí)只是保存了產(chǎn)品圖片的位置即圖片名稱翰撑,我們可以規(guī)定所有的產(chǎn)品圖片都放在一個統(tǒng)一的文件夾下面,然后通過 id 來獲取對應(yīng)名稱的圖片

CREATE TABLE product_image (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  product_id int(11) DEFAULT NULL COMMENT '對應(yīng)的產(chǎn)品id',
  PRIMARY KEY (id),
  CONSTRAINT fk_product_image_product FOREIGN KEY (product_id) REFERENCES product (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 注意: 我們通過把產(chǎn)品圖片的文件命名為 id.jpg 啊央,然后通過相對路徑來獲取到產(chǎn)品圖片

表七:用戶表

用戶表很簡單眶诈,也沒有權(quán)限之類的東西:

CREATE TABLE user (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) NOT NULL COMMENT '用戶名稱',
  password varchar(255) NOT NULL COMMENT '用戶密碼',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 我們或許會在之后把密碼弄成 “*********” 這種形式的,但是現(xiàn)在一切為了簡單瓜饥!

表八:評價(jià)表

評價(jià)表對應(yīng)了用戶和產(chǎn)品兩個表逝撬,也比較簡單,我們?yōu)榱撕唵闻彝粒焉厦婕t色的部分全部砍掉宪潮,因?yàn)闆]有商家,所以也不需要回復(fù)用戶的評價(jià),都砍掉砍掉坎炼!

CREATE TABLE review (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  content varchar(4000) DEFAULT NULL COMMENT '評價(jià)內(nèi)容',
  user_id int(11) NOT NULL COMMENT '對應(yīng)的用戶id',
  product_id int(11) NOT NULL COMMENT '對應(yīng)的產(chǎn)品id',
  createDate datetime DEFAULT NULL COMMENT '評價(jià)時間',
  PRIMARY KEY (id),
  CONSTRAINT fk_review_product FOREIGN KEY (product_id) REFERENCES product (id),
    CONSTRAINT fk_review_user FOREIGN KEY (user_id) REFERENCES user (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

表九:訂單表

由于 Order 是 MySql 的一個關(guān)鍵字,所以我們在訂單表的最后添加一個下劃線:

CREATE TABLE order_ (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  order_code varchar(255) NOT NULL COMMENT '訂單號',
  address varchar(255) NOT NULL COMMENT '收貨地址',
  post varchar(255) NOT NULL COMMENT '郵編',
  receiver varchar(255) NOT NULL COMMENT '收貨人姓名',
  mobile varchar(255) NOT NULL COMMENT '手機(jī)號碼',
  user_message varchar(255) NOT NULL COMMENT '用戶備注的信息',
  create_date datetime NOT NULL COMMENT '訂單創(chuàng)建時間',
  pay_date datetime DEFAULT NULL COMMENT '訂單支付時間',
  delivery_date datetime DEFAULT NULL COMMENT '發(fā)貨日期',
  confirm_date datetime DEFAULT NULL COMMENT '確認(rèn)收貨日期',
  user_id int(11) DEFAULT NULL COMMENT '對應(yīng)的用戶id',
  status varchar(255) NOT NULL COMMENT '訂單狀態(tài)',
  PRIMARY KEY (id),
  CONSTRAINT fk_order_user FOREIGN KEY (user_id) REFERENCES user (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

表十:訂單項(xiàng)表

一個訂單里面可能有多個訂單項(xiàng)拦键,一個產(chǎn)品也可能對應(yīng)多個訂單項(xiàng)谣光,所以這個表應(yīng)該有兩個外鍵:

CREATE TABLE order_item (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  product_id int(11) NOT NULL COMMENT '對應(yīng)產(chǎn)品id',
  order_id int(11) NOT NULL COMMENT '對應(yīng)訂單id',
  number int(11) DEFAULT NULL COMMENT '對應(yīng)產(chǎn)品購買的數(shù)量',
  PRIMARY KEY (id) COMMENT '郵編',
  CONSTRAINT fk_order_item_product FOREIGN KEY (product_id) REFERENCES product (id),
  CONSTRAINT fk_order_item_order FOREIGN KEY (order_id) REFERENCES order_ (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

匯總:

我們在創(chuàng)建表之前,應(yīng)該創(chuàng)建一個新的數(shù)據(jù)庫芬为,并命名為【tmall_ssm】

DROP DATABASE IF EXISTS tmall_ssm;
CREATE DATABASE tmall_ssm DEFAULT CHARACTER SET utf8;

將這十個表匯個總就是:

DROP DATABASE IF EXISTS tmall_ssm;
CREATE DATABASE tmall_ssm DEFAULT CHARACTER SET utf8;

use tmall_ssm;

CREATE TABLE category (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) NOT NULL COMMENT '分類的名字',
  PRIMARY KEY (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE referal_link (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  text varchar(255) NOT NULL COMMENT '超鏈顯示的文字',
  link varchar(255) NOT NULL COMMENT '超鏈的地址',
  PRIMARY KEY (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE product (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) NOT NULL COMMENT '產(chǎn)品的名稱',
  sub_title varchar(255) DEFAULT NULL COMMENT '小標(biāo)題',
  price float DEFAULT NULL COMMENT '價(jià)格',
  sale int(11) DEFAULT NULL COMMENT '銷量',
  stock int(11) DEFAULT NULL COMMENT '庫存',
  category_id int(11) DEFAULT NULL COMMENT '對應(yīng)的分類id',
  PRIMARY KEY (id),
  CONSTRAINT fk_product_category FOREIGN KEY (category_id) REFERENCES category (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE property (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) DEFAULT NULL COMMENT '屬性名稱',
  category_id int(11) NOT NULL COMMENT '對應(yīng)的分類id',
  PRIMARY KEY (id),
  CONSTRAINT fk_property_category FOREIGN KEY (category_id) REFERENCES category(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE property_value (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  product_id int(11) NOT NULL COMMENT '對應(yīng)產(chǎn)品id',
  properti_id int(11) NOT NULL COMMENT '對應(yīng)屬性id',
  value varchar(255) DEFAULT NULL COMMENT '具體的屬性值',
  PRIMARY KEY (id),
  CONSTRAINT fk_property_value_property FOREIGN KEY (properti_id) REFERENCES property (id),
  CONSTRAINT fk_property_value_product FOREIGN KEY (product_id) REFERENCES product (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE product_image (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  product_id int(11) DEFAULT NULL COMMENT '對應(yīng)的產(chǎn)品id',
  PRIMARY KEY (id),
  CONSTRAINT fk_product_image_product FOREIGN KEY (product_id) REFERENCES product (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE user (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) NOT NULL COMMENT '用戶名稱',
  password varchar(255) NOT NULL COMMENT '用戶密碼',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE review (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  content varchar(4000) DEFAULT NULL COMMENT '評價(jià)內(nèi)容',
  user_id int(11) NOT NULL COMMENT '對應(yīng)的用戶id',
  product_id int(11) NOT NULL COMMENT '對應(yīng)的產(chǎn)品id',
  createDate datetime DEFAULT NULL COMMENT '評價(jià)時間',
  PRIMARY KEY (id),
  CONSTRAINT fk_review_product FOREIGN KEY (product_id) REFERENCES product (id),
  CONSTRAINT fk_review_user FOREIGN KEY (user_id) REFERENCES user (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE order_ (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  order_code varchar(255) NOT NULL COMMENT '訂單號',
  address varchar(255) NOT NULL COMMENT '收貨地址',
  post varchar(255) NOT NULL COMMENT '郵編',
  receiver varchar(255) NOT NULL COMMENT '收貨人姓名',
  mobile varchar(255) NOT NULL COMMENT '手機(jī)號碼',
  user_message varchar(255) NOT NULL COMMENT '用戶備注的信息',
  create_date datetime NOT NULL COMMENT '訂單創(chuàng)建時間',
  pay_date datetime DEFAULT NULL COMMENT '訂單支付時間',
  delivery_date datetime DEFAULT NULL COMMENT '發(fā)貨日期',
  confirm_date datetime DEFAULT NULL COMMENT '確認(rèn)收貨日期',
  user_id int(11) DEFAULT NULL COMMENT '對應(yīng)的用戶id',
  status varchar(255) NOT NULL COMMENT '訂單狀態(tài)',
  PRIMARY KEY (id),
  CONSTRAINT fk_order_user FOREIGN KEY (user_id) REFERENCES user (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE order_item (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  product_id int(11) NOT NULL COMMENT '對應(yīng)產(chǎn)品id',
  order_id int(11) NOT NULL COMMENT '對應(yīng)訂單id',
  number int(11) DEFAULT NULL COMMENT '對應(yīng)產(chǎn)品購買的數(shù)量',
  PRIMARY KEY (id) COMMENT '郵編',
  CONSTRAINT fk_order_item_product FOREIGN KEY (product_id) REFERENCES product (id),
  CONSTRAINT fk_order_item_order FOREIGN KEY (order_id) REFERENCES order_ (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

直接復(fù)制進(jìn) MySql 中執(zhí)行萄金,就能看到我們創(chuàng)建好的十個數(shù)據(jù)庫:


第三步:創(chuàng)建 SSM 開發(fā)環(huán)境

根據(jù)之前我寫過的博文:IDEA 整合 SSM 搭建好 SSM 開發(fā)環(huán)境,這里給出完整的項(xiàng)目結(jié)構(gòu)和 pom.xml 文件:

  • 完整的項(xiàng)目結(jié)構(gòu):
  • pom.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<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>
    <packaging>war</packaging>

    <name>wmyskxz</name>
    <groupId>cn.wmyskxz</groupId>
    <artifactId>wmyskxz</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.7</version>
                <configuration>
                    <connectors>
                        <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                            <port>8888</port>
                            <maxIdleTime>30000</maxIdleTime>
                        </connector>
                    </connectors>
                    <webAppSourceDirectory>${project.build.directory}/${pom.artifactId}-${pom.version}
                    </webAppSourceDirectory>
                    <contextPath>/</contextPath>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <properties>
        <!-- 設(shè)置項(xiàng)目編碼編碼 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- spring版本號 -->
        <spring.version>4.3.5.RELEASE</spring.version>
        <!-- mybatis版本號 -->
        <mybatis.version>3.4.1</mybatis.version>
    </properties>

    <dependencies>

        <!-- pageHelper -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.2-beta</version>
        </dependency>

        <!--jsqlparser-->
        <dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>1.0</version>
        </dependency>

        <!-- jstl標(biāo)簽 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-impl</artifactId>
            <version>1.2.5</version>
        </dependency>

        <!-- java ee -->
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
        </dependency>

        <!-- 單元測試 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!-- 實(shí)現(xiàn)slf4j接口并整合 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.2</version>
        </dependency>

        <!-- JSON -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.7</version>
        </dependency>


        <!-- 數(shù)據(jù)庫 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
            <scope>runtime</scope>
        </dependency>

        <!-- 數(shù)據(jù)庫連接池 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>

        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>

        <!-- mybatis/spring整合包 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>

        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

    </dependencies>

</project>

MyBatis 逆向工程

按照正常的流程媚朦,我們應(yīng)該去創(chuàng)建數(shù)據(jù)庫對應(yīng)的 POJO 和 DAO 類還有對應(yīng)的 mapper 映射文件氧敢,按照上面的分析我們一共有十張表,想象一下為這十張表做這些無技術(shù)含量的機(jī)械化的繁雜的工作是多么頭疼的一件事询张,我們希望的是:有人幫我自動創(chuàng)建好這些孙乖!

  • MyBatis 官方提供了一種名為 “逆向工程” 的機(jī)制,其可以針對數(shù)據(jù)庫中的單表自動生成 MyBatis 執(zhí)行所需要的代碼
  • 包括:
    Java 實(shí)體類份氧、Mapper映射配置唯袄、Mapper代理接口

第一步:添加必要的 jar 包

我們使用逆向工程,需要先導(dǎo)入 Mybatis Generator 的官方包蜗帜,由于我們使用的是 Maven 搭建的 SSM 項(xiàng)目恋拷,所有我們可以去 Maven 的官網(wǎng)去查詢需要的相關(guān)包:http://mvnrepository.com/

戳進(jìn)去點(diǎn)擊最新的包:

就可以在下方找到 Maven 依賴添加的語句:

直接粘進(jìn) pom.xml 就可以了,這里就不演示了厅缺。

第二步:generatorConfig.xml

在【resources】下創(chuàng)建 generatorConfig.xml 配置文件蔬顾,該配置文件說明了一些逆向工程的細(xì)節(jié):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

    <context id="DB2Tables" targetRuntime="MyBatis3">

        <!-- 是否去除自動生成的代碼中的注釋 true:是 false:否-->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!-- 數(shù)據(jù)庫連接信息:驅(qū)動類、連接地址湘捎、用戶名诀豁、密碼 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost/tmall_ssm"
                        userId="root" password="root">
        </jdbcConnection>

        <!-- 默認(rèn) false,把 JDBC DECIMAL 和 NUMERIC 類型解析為 Integer
             為 true 時解析為 java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- targetProject:生成 POJO 類的位置 -->
        <javaModelGenerator targetPackage="cn.wmyskxz.pojo" targetProject="src/main/java">
            <!-- enableSubPackages:是否讓 schema 作為包的后綴-->
            <property name="enableSubPackages" value="false"/>
            <!-- trimStrings:從數(shù)據(jù)庫返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- targetProject:生成xml映射文件存放位置 -->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
            <!-- enableSubPackages:是否讓 schema 作為包的后綴-->
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>

        <!-- targetProject:生成mapper類存放位置 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="cn.wmyskxz.mapper" targetProject="src/main/java">
            <!-- enableSubPackages:是否讓 schema 作為包的后綴-->
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

        <!--生成對應(yīng)表及類名
            tableName:要生成的表名
            domainObjectName:生成后的實(shí)例名
            enableCountByExample:Count語句中加入where條件查詢消痛,默認(rèn)為true開啟
            enableUpdateByExample:Update語句中加入where條件查詢且叁,默認(rèn)為true開啟
            enableDeleteByExample:Delete語句中加入where條件查詢,默認(rèn)為true開啟
            enableSelectByExample:Select多條語句中加入where條件查詢秩伞,默認(rèn)為true開啟
            selectByExampleQueryId:Select單個對象語句中加入where條件查詢逞带,默認(rèn)為true開啟
        -->
        <table tableName="category" domainObjectName="Category" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false">
            <!-- 使用數(shù)據(jù)庫中實(shí)際的字段名作為生成的實(shí)體類的屬性 -->
            <property name="useActualColumnNames" value="true"/>
            <!-- 使用自增長鍵 -->
            <property name="my.isgen.usekeys" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="property" domainObjectName="Property" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false">
            <property name="useActualColumnNames" value="true"/>
            <property name="my.isgen.usekeys" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="product" domainObjectName="Product" enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="product_image" domainObjectName="ProductImage" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="order_" domainObjectName="Order" enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="property_value" domainObjectName="PropertyValue" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="review" domainObjectName="Review" enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="order_item" domainObjectName="OrderItem" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>

        <table tableName="referal_link" domainObjectName="ReferalLink" enableCountByExample="false"
               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true"
               selectByExampleQueryId="false">
            <property name="my.isgen.usekeys" value="true"/>
            <property name="useActualColumnNames" value="true"/>
            <generatedKey column="id" sqlStatement="JDBC"/>
        </table>
    </context>
</generatorConfiguration>

這樣配置文件也就編寫好了

第三步:逆向數(shù)據(jù)文件生成類

在編寫完配置文件只有,就需要加載該配置文件,利用逆向工程的機(jī)制來對數(shù)據(jù)庫的各個表進(jìn)行一系列文件的生成霹肝,我們在【test/java】包下創(chuàng)建【TestMyBatisGenerator】類:

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.api.ShellCallback;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 逆向工程測試類
 *
 * @author: @我沒有三顆心臟
 * @create: 2018-04-27-上午 8:26
 */
public class TestMybatisGenerator {

    public static void main(String[] args) throws Exception {
        // warnings 為用于放置生成過程中警告信息的集合對象
        List<String> warnings = new ArrayList<String>();
        // 指定是否覆蓋重名文件
        boolean overwrite = true;
        // 加載配置文件
        File configFile = new File(MyBatisGenerator.class.getClassLoader().getResource("generatorConfig.xml").toURI());
        // 配置解析類
        ConfigurationParser cp = new ConfigurationParser(warnings);
        // 配置解析類解析配置文件并生成 Configuration 配置對象
        Configuration config = cp.parseConfiguration(configFile);
        // ShellCallback 負(fù)責(zé)如何處理重復(fù)文件
        ShellCallback callback = new DefaultShellCallback(overwrite);
        // 逆向工程對象
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        // 執(zhí)行逆向文件生成操作
        myBatisGenerator.generate(null);
        // 打印提示信息
        System.out.println("MyBatis 逆向工程執(zhí)行成功燕刻,刷新項(xiàng)目查看文件!");
    }
}

執(zhí)行該測試類遇汞,就能看見自動生成的文件:

  • Oh!這真的是太爽了!突然開心(**)

看一下自動生成的文件

以 Category 為例空入,我們來看一下自動生成的文件:

  • Category 實(shí)體類:
package cn.wmyskxz.pojo;

public class Category {
    private Integer id;

    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }
}
  • CategoryMapper 映射類:
package cn.wmyskxz.mapper;

import cn.wmyskxz.pojo.Category;
import cn.wmyskxz.pojo.CategoryExample;
import java.util.List;

public interface CategoryMapper {
    int deleteByPrimaryKey(Integer id);

    int insert(Category record);

    int insertSelective(Category record);

    List<Category> selectByExample(CategoryExample example);

    Category selectByPrimaryKey(Integer id);

    int updateByPrimaryKeySelective(Category record);

    int updateByPrimaryKey(Category record);
}
  • CategoryMapper.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="cn.wmyskxz.mapper.CategoryMapper">
    <resultMap id="BaseResultMap" type="cn.wmyskxz.pojo.Category">
        <id column="id" jdbcType="INTEGER" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
    </resultMap>
    <sql id="Example_Where_Clause">
        <where>
            <foreach collection="oredCriteria" item="criteria" separator="or">
                <if test="criteria.valid">
                    <trim prefix="(" prefixOverrides="and" suffix=")">
                        <foreach collection="criteria.criteria" item="criterion">
                            <choose>
                                <when test="criterion.noValue">
                                    and ${criterion.condition}
                                </when>
                                <when test="criterion.singleValue">
                                    and ${criterion.condition} #{criterion.value}
                                </when>
                                <when test="criterion.betweenValue">
                                    and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                                </when>
                                <when test="criterion.listValue">
                                    and ${criterion.condition}
                                    <foreach close=")" collection="criterion.value" item="listItem" open="("
                                             separator=",">
                                        #{listItem}
                                    </foreach>
                                </when>
                            </choose>
                        </foreach>
                    </trim>
                </if>
            </foreach>
        </where>
    </sql>
    <sql id="Base_Column_List">
    id, name
  </sql>
    <select id="selectByExample" parameterType="cn.wmyskxz.pojo.CategoryExample" resultMap="BaseResultMap">
        select
        <if test="distinct">
            distinct
        </if>
        'false' as QUERYID,
        <include refid="Base_Column_List"/>
        from category
        <if test="_parameter != null">
            <include refid="Example_Where_Clause"/>
        </if>
        <if test="orderByClause != null">
            order by ${orderByClause}
        </if>
    </select>
    <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from category
        where id = #{id,jdbcType=INTEGER}
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from category
    where id = #{id,jdbcType=INTEGER}
  </delete>
    <insert id="insert" keyColumn="id" keyProperty="id" parameterType="cn.wmyskxz.pojo.Category"
            useGeneratedKeys="true">
    insert into category (name)
    values (#{name,jdbcType=VARCHAR})
  </insert>
    <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="cn.wmyskxz.pojo.Category"
            useGeneratedKeys="true">
        insert into category
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="name != null">
                name,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="name != null">
                #{name,jdbcType=VARCHAR},
            </if>
        </trim>
    </insert>
    <update id="updateByPrimaryKeySelective" parameterType="cn.wmyskxz.pojo.Category">
        update category
        <set>
            <if test="name != null">
                name = #{name,jdbcType=VARCHAR},
            </if>
        </set>
        where id = #{id,jdbcType=INTEGER}
    </update>
    <update id="updateByPrimaryKey" parameterType="cn.wmyskxz.pojo.Category">
    update category
    set name = #{name,jdbcType=VARCHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

其中就只有映射文件稍微有些復(fù)雜络它,但細(xì)看下來其實(shí)跟我們自己寫的差不多,甚至自動生成的完成得更好歪赢。

xxxExample

MybatisGenerator會生成一個類叫做XXXXExample的化戳。,它的作用是進(jìn)行排序埋凯,條件查詢的時候使用点楼。

這里有詳細(xì)的說明,了解一下就好了:戳這里

第四步:測試

我們這里僅僅就用 CategoryMapper 映射類來進(jìn)行簡單測試了:

@Autowired
CategoryMapper categoryMapper;

@Test
public void test() {
    Category category = new Category();
    category.setName("分類1");
    categoryMapper.insert(category);
}

由于我們使用了自增長鍵 id 白对,所以僅僅只需要提供 name 屬性就可以了掠廓,執(zhí)行,可以看到數(shù)據(jù)庫中有正確的數(shù)據(jù):


總結(jié)

根據(jù)以上的 “折騰” 算是完成了項(xiàng)目的起步工作了吧甩恼,我是一邊寫項(xiàng)目一邊寫博客的蟀瞧,所以可能有時候想著想著寫著寫著思緒會有點(diǎn)飄,寫得凌亂条摸,這也是沒有辦法的事黄橘,不管寫得好還是差我都希望能記錄下來,這些都是屬于我自己的思路和學(xué)習(xí)路程屈溉。

歡迎轉(zhuǎn)載塞关,轉(zhuǎn)載請注明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關(guān)注公眾微信號:wmyskxz_javaweb
分享自己的Java Web學(xué)習(xí)之路以及各種Java學(xué)習(xí)資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末子巾,一起剝皮案震驚了整個濱河市帆赢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌线梗,老刑警劉巖椰于,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仪搔,居然都是意外死亡瘾婿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門烤咧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偏陪,“玉大人,你說我怎么就攤上這事煮嫌〉亚” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵昌阿,是天一觀的道長饥脑。 經(jīng)常有香客問我恳邀,道長,這世上最難降的妖魔是什么灶轰? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任谣沸,我火速辦了婚禮,結(jié)果婚禮上笋颤,老公的妹妹穿的比我還像新娘鳄抒。我一直安慰自己,他們只是感情好椰弊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瓤鼻,像睡著了一般秉版。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茬祷,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天清焕,我揣著相機(jī)與錄音,去河邊找鬼祭犯。 笑死秸妥,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的沃粗。 我是一名探鬼主播粥惧,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼最盅!你這毒婦竟也來了突雪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤涡贱,失蹤者是張志新(化名)和其女友劉穎咏删,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體问词,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡督函,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了激挪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辰狡。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖垄分,靈堂內(nèi)的尸體忽然破棺而出搓译,到底是詐尸還是另有隱情,我是刑警寧澤锋喜,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布些己,位于F島的核電站豌鸡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏段标。R本人自食惡果不足惜涯冠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逼庞。 院中可真熱鬧蛇更,春花似錦、人聲如沸赛糟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽璧南。三九已至掌逛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間司倚,已是汗流浹背豆混。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留动知,地道東北人皿伺。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像盒粮,于是被迫代替她去往敵國和親鸵鸥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容