模仿天猫实战【SSM版】——项目起步

前言:现在自己的学习似乎遇到了瓶颈,感觉学习了 SSM 之后有一些迷茫,不知道接下来该往哪里去努力了,我觉得这是个很不好的状态,为了度过这段时期,我准备把天猫模仿下来(给自己找点事做)之后开始去巩固 Java 的基础知识,也准备好暑假去找实习。

第一步:需求分析

首先要确定要实现哪些功能,需要对需求进行完整的分析,才能在编写项目的时候有条不紊,我们的目的很明确:就是模仿天猫前端 + 自己实现后端。并且尽最大努力去降低这个项目的复杂度(毕竟高深的东西不懂)。

前端需求分析

规定:全天猫没有店铺,就只有唯一一家叫做 Tmall 的商家,卖所有的东西。

  • 1.数据的显示:

首页数据显示分析:

首先是搜索栏下方的九个商品,需要从数据库中取出销量最高的几个产品,关于标红的关键字,是要满足一定条件的,比如:这一个星期内销量超过多少...

接着是分类导航栏,首先是商品分类右边固定的两个链接【天猫超市】和【天猫国际】,还有紧跟着的八个超链,这个可以设计为一个单表,存储它显示的文字和链接过去的地址,然后是具体的 16 个分类以及轮播:

下面的具体产品展示比较复杂,我们可以自己做一下简化,比如就展示几个产品比较多的固定的几个分类就好了,其他的就直接舍弃:

  • 总结: 总之就是需要显示各种数据库中的数据
  • 2.登录/注册页

需要有一个登录/注册页,能够完成用户的登录和注册功能,并能提供基础的例如判断空值等功能。

  • 3.产品搜索页

左上角的图标我们可以统一简化成 Tmall 的图片,商品图片,我们可以整个大分类使用一张图,主要就是实现排序功能还有搜索功能

  • 4.产品展示页

天猫原生的产品展示页有些复杂,我们可以自己简化一下,就不要选这么多东西,都是一口价,

另外下方规格参数和评价都不能省略:

  • 5.购物车/购买页面

第二步:表结构设计

根据对于前端的分析,数据库有了一些眉目,为了简化项目的难度,所以我们需要自己想点办法,先来构思一下大概需要一些什么样的表:

我大概就想出来需要用到这些表,我们一个一个来创建它们:

表一:分类表

首先我们需要一个表来存储我们的分类信息,也就是【女装/内衣】、【男装/运动户外】在内的 16 个分类,为了高度一致,这 16 个分类不能多也不能少。

为了简化任务,可以观察出,【热门手机】、【特色手机】分栏下的东西都是【手机/数码/电脑办公】类别里的东西,所以我们直接砍掉,右边的一些图片超链也给直接砍掉,我们规定每一行显示的产品数目就可以了,这样就简单多了。

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 个超链,我们单独新建一个表来存储超链显示的文字和链接的地址,这样就可以任意的修改其内容:

百度翻译【推荐链接】翻译为【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;

表三:产品表

每个分类下都要一定的产品,这些产品还有自己的一些属性,所以另外需要属性表,这个表另外创建,我们先来观察一下一个产品表需要一些什么东西:

  • 用于展示的 5 张图片
  • 产品名称
  • 小标题(即名称下面一排标红的小字)
  • 价格(就一口价,没别的)
  • 销量(别月销量了,能简化就简化一下)
  • 累计评价(还需要设计一个评价表)
  • 库存
  • 属性(需要关联另外的属性表)
CREATE TABLE product (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  name varchar(255) NOT NULL COMMENT '产品的名称',
  sub_title varchar(255) DEFAULT NULL COMMENT '小标题',
  price float DEFAULT NULL COMMENT '价格',
  sale int(11) DEFAULT NULL COMMENT '销量',
  stock int(11) DEFAULT NULL COMMENT '库存',
  category_id int(11) DEFAULT NULL COMMENT '对应的分类id',
  PRIMARY KEY (id),
  CONSTRAINT fk_product_category FOREIGN KEY (category_id) REFERENCES category (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
  • 注意: 其中产品图片,累计评价,属性都作为单独的表存在并让当前表的 id 作为外键

表四:属性表

去掉详细的规格参数划分,其实属性也就是一个名字而已(简化简化简化)。

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 '对应的产品id',
  PRIMARY KEY (id),
  CONSTRAINT fk_property_product FOREIGN KEY (product_id) REFERENCES product(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 突然想到的问题:
    每一个产品的属性其实是很多的,如果每一个产品都对应很多属性的话,对于天猫这样的数据量来说,应该会让数据库爆炸的吧...
  • 改进方法:
    将属性表关联到 category 表上,因为其实每一个分类下的产品的属性差不多!

修改数据库

根据以上问题,修改一下数据库表之间的关系

并将属性表的外键修改为 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 '对应的分类id',
  PRIMARY KEY (id),
  CONSTRAINT fk_property_category FOREIGN KEY (category_id) REFERENCES category(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表五:属性值表

其中就是保存了对应属性的值,并且应该有两个外键,一个指向 Property 表,而另一个则指向 Product 表

CREATE TABLE property_value (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  product_id int(11) NOT NULL COMMENT '对应产品id',
  properti_id int(11) NOT NULL COMMENT '对应属性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;

表六:产品图片表

这个表名义上是保存了产品的图片,其实只是保存了产品图片的位置即图片名称,我们可以规定所有的产品图片都放在一个统一的文件夹下面,然后通过 id 来获取对应名称的图片

CREATE TABLE product_image (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一索引id',
  product_id int(11) DEFAULT NULL COMMENT '对应的产品id',
  PRIMARY KEY (id),
  CONSTRAINT fk_product_image_product FOREIGN KEY (product_id) REFERENCES product (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 注意: 我们通过把产品图片的文件命名为 id.jpg ,然后通过相对路径来获取到产品图片

表七:用户表

用户表很简单,也没有权限之类的东西:

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 '评价内容',
  user_id int(11) NOT NULL COMMENT '对应的用户id',
  product_id int(11) NOT NULL COMMENT '对应的产品id',
  createDate datetime DEFAULT NULL COMMENT '评价时间',
  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 的一个关键字,所以我们在订单表的最后添加一个下划线:

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 '手机号码',
  user_message varchar(255) NOT NULL COMMENT '用户备注的信息',
  create_date datetime NOT NULL COMMENT '订单创建时间',
  pay_date datetime DEFAULT NULL COMMENT '订单支付时间',
  delivery_date datetime DEFAULT NULL COMMENT '发货日期',
  confirm_date datetime DEFAULT NULL COMMENT '确认收货日期',
  user_id int(11) DEFAULT NULL COMMENT '对应的用户id',
  status varchar(255) NOT NULL COMMENT '订单状态',
  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 '对应产品id',
  order_id int(11) NOT NULL COMMENT '对应订单id',
  number int(11) DEFAULT NULL COMMENT '对应产品购买的数量',
  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;

汇总:

我们在创建表之前,应该创建一个新的数据库,并命名为【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 '产品的名称',
  sub_title varchar(255) DEFAULT NULL COMMENT '小标题',
  price float DEFAULT NULL COMMENT '价格',
  sale int(11) DEFAULT NULL COMMENT '销量',
  stock int(11) DEFAULT NULL COMMENT '库存',
  category_id int(11) DEFAULT NULL COMMENT '对应的分类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 '对应的分类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 '对应产品id',
  properti_id int(11) NOT NULL COMMENT '对应属性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 '对应的产品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 '评价内容',
  user_id int(11) NOT NULL COMMENT '对应的用户id',
  product_id int(11) NOT NULL COMMENT '对应的产品id',
  createDate datetime DEFAULT NULL COMMENT '评价时间',
  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 '手机号码',
  user_message varchar(255) NOT NULL COMMENT '用户备注的信息',
  create_date datetime NOT NULL COMMENT '订单创建时间',
  pay_date datetime DEFAULT NULL COMMENT '订单支付时间',
  delivery_date datetime DEFAULT NULL COMMENT '发货日期',
  confirm_date datetime DEFAULT NULL COMMENT '确认收货日期',
  user_id int(11) DEFAULT NULL COMMENT '对应的用户id',
  status varchar(255) NOT NULL COMMENT '订单状态',
  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 '对应产品id',
  order_id int(11) NOT NULL COMMENT '对应订单id',
  number int(11) DEFAULT NULL COMMENT '对应产品购买的数量',
  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;

直接复制进 MySql 中执行,就能看到我们创建好的十个数据库:


第三步:创建 SSM 开发环境

根据之前我写过的博文:IDEA 整合 SSM 搭建好 SSM 开发环境,这里给出完整的项目结构和 pom.xml 文件:

  • 完整的项目结构:

  • 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>
        <!-- 设置项目编码编码 -->
        <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标签 -->
        <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>

        <!-- 实现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>


        <!-- 数据库 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
            <scope>runtime</scope>
        </dependency>

        <!-- 数据库连接池 -->
        <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 逆向工程

按照正常的流程,我们应该去创建数据库对应的 POJO 和 DAO 类还有对应的 mapper 映射文件,按照上面的分析我们一共有十张表,想象一下为这十张表做这些无技术含量的机械化的繁杂的工作是多么头疼的一件事,我们希望的是:有人帮我自动创建好这些!

  • MyBatis 官方提供了一种名为 “逆向工程” 的机制,其可以针对数据库中的单表自动生成 MyBatis 执行所需要的代码
  • 包括:
    Java 实体类、Mapper映射配置、Mapper代理接口

第一步:添加必要的 jar 包

我们使用逆向工程,需要先导入 Mybatis Generator 的官方包,由于我们使用的是 Maven 搭建的 SSM 项目,所有我们可以去 Maven 的官网去查询需要的相关包:http://mvnrepository.com/

戳进去点击最新的包:

就可以在下方找到 Maven 依赖添加的语句:

直接粘进 pom.xml 就可以了,这里就不演示了。

第二步:generatorConfig.xml

在【resources】下创建 generatorConfig.xml 配置文件,该配置文件说明了一些逆向工程的细节:

<?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>

        <!-- 数据库连接信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost/tmall_ssm"
                        userId="root" password="root">
        </jdbcConnection>

        <!-- 默认 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:从数据库返回的值被清理前后的空格 -->
            <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>

        <!--生成对应表及类名
            tableName:要生成的表名
            domainObjectName:生成后的实例名
            enableCountByExample:Count语句中加入where条件查询,默认为true开启
            enableUpdateByExample:Update语句中加入where条件查询,默认为true开启
            enableDeleteByExample:Delete语句中加入where条件查询,默认为true开启
            enableSelectByExample:Select多条语句中加入where条件查询,默认为true开启
            selectByExampleQueryId:Select单个对象语句中加入where条件查询,默认为true开启
        -->
        <table tableName="category" domainObjectName="Category" 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="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>

这样配置文件也就编写好了

第三步:逆向数据文件生成类

在编写完配置文件只有,就需要加载该配置文件,利用逆向工程的机制来对数据库的各个表进行一系列文件的生成,我们在【test/java】包下创建【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 负责如何处理重复文件
		ShellCallback callback = new DefaultShellCallback(overwrite);
		// 逆向工程对象
		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
		// 执行逆向文件生成操作
		myBatisGenerator.generate(null);
		// 打印提示信息
		System.out.println("MyBatis 逆向工程执行成功,刷新项目查看文件!");
	}
}

执行该测试类,就能看见自动生成的文件:

  • Oh!这真的是太爽了!突然开心(**)

看一下自动生成的文件

以 Category 为例,我们来看一下自动生成的文件:

  • Category 实体类:
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>

其中就只有映射文件稍微有些复杂,但细看下来其实跟我们自己写的差不多,甚至自动生成的完成得更好。

xxxExample

MybatisGenerator会生成一个类叫做XXXXExample的。,它的作用是进行排序,条件查询的时候使用。

这里有详细的说明,了解一下就好了:戳这里

第四步:测试

我们这里仅仅就用 CategoryMapper 映射类来进行简单测试了:

@Autowired
CategoryMapper categoryMapper;

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

由于我们使用了自增长键 id ,所以仅仅只需要提供 name 属性就可以了,执行,可以看到数据库中有正确的数据:


总结

根据以上的 “折腾” 算是完成了项目的起步工作了吧,我是一边写项目一边写博客的,所以可能有时候想着想着写着写着思绪会有点飘,写得凌乱,这也是没有办法的事,不管写得好还是差我都希望能记录下来,这些都是属于我自己的思路和学习路程。

欢迎转载,转载请注明出处!
简书ID:@我没有三颗心脏
github:wmyskxz
欢迎关注公众微信号:wmyskxz_javaweb
分享自己的Java Web学习之路以及各种Java学习资料

posted @ 2018-04-27 10:39  我没有三颗心脏  阅读(5114)  评论(10编辑  收藏  举报