前言:现在自己的学习似乎遇到了瓶颈,感觉学习了 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学习资料

模仿天猫实战【SSM版】——项目起步的更多相关文章

  1. 模仿天猫实战【SSM版】——后台开发

    上一篇文章链接:模仿天猫实战[SSM版]--项目起步 后台需求分析 在开始码代码之前,还是需要先清楚自己要做什么事情,后台具体需要实现哪些功能: 注意: 订单.用户.订单.推荐链接均不提供增删的功能. ...

  2. 模仿天猫实战【SSM】——总结

    第一篇文章链接:模仿天猫实战[SSM版]--项目起步 第二篇文章链接:模仿天猫实战[SSM版]--后台开发 总结:项目从4-27号开始写,到今天5-7号才算真正的完工,有许多粗糙的地方,但总算完成了, ...

  3. JavaWeb入门_模仿天猫整站Tmall_SSM实践项目

    Tmall_SSM 技术栈 Spring MVC+ Mybatis + Spring + Jsp + Tomcat , 是 Java Web 入门非常好的练手项目 效果展示: 模仿天猫前台 模仿天猫后 ...

  4. JavaWeb入门_模仿天猫整站Tmall_SSH实践项目

    Tmall_SSH 技术栈 Struts2 + Hibernate + Spring + Jsp + Tomcat , 是 Java Web 入门非常好的练手项目 效果展示: 模仿天猫前台 模仿天猫后 ...

  5. JavaWeb入门_模仿天猫整站Tmall_JavaEE实践项目

    Tmall_JavaEE 技术栈 Servlet + Jsp + Tomcat , 是Java Web入门非常好的练手项目 效果展示: 模仿天猫前台 模仿天猫后台 项目简介 关联项目 github - ...

  6. Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-2-driver

    1>使用的driver 1〉generic 使用带有SSH的现有VM/主机创建机器. 如果你使用的是机器不直接支持的provider,或者希望导入现有主机以允许Docker Machine进行管 ...

  7. 移动端自动化测试Appium 从入门到项目实战Python版☝☝☝

    移动端自动化测试Appium 从入门到项目实战Python版 (一个人学习或许会很枯燥,但是寻找更多志同道合的朋友一起,学习将会变得更加有意义✌✌)  说到APP自动化测试,Appium可是说是非常流 ...

  8. 移动端自动化测试appium 从入门到项目实战Python版✍✍✍

    移动端自动化测试appium 从入门到项目实战Python版 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程 ...

  9. 移动端自动化测试Appium 从入门到项目实战Python版

    移动端自动化测试Appium 从入门到项目实战Python版  整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课 ...

随机推荐

  1. redis入门(14)redis集群下的数据分区存储

    redis入门(10)redis集群下的数据分区存储

  2. 关于ZK框架的onScroll事件的问题

    由于我现在所在的公司用到的zk框架,遇到了一个需求frozen on top. 简单来说就是滚动超过范围后,希望有一块东西停留在滚动窗口的顶部. 一.zk框架 查看了zk的8.x版本,发现组件的支持的 ...

  3. redis从入门到

    下载 首先我们要到GitHub(https://github.com/MicrosoftArchive/redis/releases)上下载Source code (tar.gz) 上传到Linux上 ...

  4. JAVA_将唐诗按照古文样式输出

    1. 如有唐诗: 锄禾日当午 汗滴禾下土 谁知盘中餐 粒粒皆辛苦 要求将这首唐诗按照古文样式输出,输出格式如下: 粒谁汗锄 粒知滴禾 皆盘禾日 辛中下当 苦餐土午 public class Text ...

  5. building a new horizon

    昨天是4月14日,也是我的23岁生日.正好去参加GDG举办的WTM,这次的主题是building a new horizon. 写一下印象深刻的分享者和她们的闪光点. 1.羡辙-从灵感到落地 羡辙是在 ...

  6. AutoFac+MVC+WebApi源码----我踩过的坑

    发现网上关于AutoFac的Demo源码比较少,综合MVC和WepApi的更少.所以贴出源码 WebApi项目(MVC4不需要引用,历史遗留问题,人懒没删) 建项目 新建类库IAutoFacDal(接 ...

  7. 简明shell入门

  8. 【前端】Ubuntu16下nodejs+npm+vue环境配置

    笔者最近在学习vue.js,不过一直都是在runoob上面各种尝试.今天笔者在本机(Ubuntu16.04)尝试部署了nodejs+npm+vue开发环境,接下来将尽可能详细的讲述安装过程,帮助新人少 ...

  9. [POJ 1006]生理周期

    Description 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这天,人会在相应的方面表现出色.例如,智力周期的高峰 ...

  10. [HNOI2013]数列

    题目描述 小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨.股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N.在疯涨的K天中小T观察到:除第一天外每天的股价都比前一天高,且高出 ...