[TOC]
## 步骤 1 : 目前Mybatis的问题
目前分类管理中Mybatis中相关类都是自己手动编写的,包括:Category.java, CategoryMapper.java和CategoryMapper.xml。
尤其是CategoryMapper.xml里面主要是SQL语句,可以预见在接下来的开发任务中,随着业务逻辑的越来越复杂,SQL语句也会越来越复杂,进而导致开发速度降低,出错率增加,维护成本上升等问题。
为了解决手动编写SQL语句效率低这个问题,我们对Mybatis部分的代码,使用逆向工程进行重构。
所谓的逆向工程,就是在已经存在的数据库表结构基础上,通过工具,自动生成Category.java, CategoryMapper.java和CategoryMapper.xml。
## 步骤 1 : 逆向工程工具简介
Mybatis Generator是一个用于Mybatis逆向工程的工具。
前面学习的方式都是先有pojo, mapper, xml, 然后再创建表。
用逆向工程的方式,首先保证**数据库里有表**,然后通过Mybatis Generator生成pojo, mapper和xml。
可以节约大家的时间,提高开发效率,降低出错几率
## 步骤 2 : OverIsMergeablePlugin
MybatisGenerator插件是Mybatis官方提供的,这个插件存在一个固有的Bug,即当第一次生成了CategoryMapper.xml之后,再次运行会导致CategoryMapper.xml生成重复内容,而影响正常的运行。
为了解决这个问题,需要写一个小插件类OverIsMergeablePlugin。
至于怎么使用,将在下一个步骤generatorConfig.xml讲解,这里先准备这个类。
> 不用需知道这个是内部是怎么操作的,直接拿来用,这也是从网上搜到的。
>
![](https://box.kancloud.cn/6ddfd3c3f01c9c8d731e5477cdecfbc5_278x136.png)
~~~
package com.dodoke.tmall.util;
import java.lang.reflect.Field;
import java.util.List;
import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
public class OverIsMergeablePlugin extends PluginAdapter {
@Override
public boolean validate(List<String> warnings) {
return true;
}
@Override
public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
try {
Field field = sqlMap.getClass().getDeclaredField("isMergeable");
field.setAccessible(true);
field.setBoolean(sqlMap, false);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
~~~
## 步骤 3 : generatorConfig.xml
在resouces下创建generatorConfig.xml文件,其目的就是为了正确使用本插件而提供必要的配置信息
1. 使用OverIsMergeablePlugin插件
`<plugin type="com.dodoke.tmall.util.OverIsMergeablePlugin" />`
2. 在生成的代码中,不提供注释。如果提供注释,生成出来的代码,看上去乱七八糟的。
`<commentGenerator>`
3. 指定链接数据库的账号和密码,既然是逆向工程,肯定要先链接到数据库才对啊
~~~
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost/tmall_ssm" userId="root" password="">
~~~
4. 指定生成的pojo,mapper, xml文件的存放位置
5. 指定表名以及表名对应的类名,这里只开放了t_category表,其他表都注释掉了,下一个知识点再讲,本知识点只讲解t_category表。
![](https://box.kancloud.cn/c64173eb297a05ec03af1e3ac6358334_268x163.png)
~~~
<?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">
<!--避免生成重复代码的插件-->
<plugin type="com.dodoke.tmall.util.OverIsMergeablePlugin" />
<!--是否在代码中显示注释-->
<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="">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer true,把JDBC DECIMAL
和 NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!--生成pojo类存放位置-->
<javaModelGenerator targetPackage="com.dodoke.tmall.pojo" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!--生成xml映射文件存放位置-->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--生成mapper类存放位置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.dodoke.tmall.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!--生成对应表及类名-->
<!--
domainObjectName:生成的domain类的名字,如果不设置,直接使用表名作为domain类的名字;可以设置为somepck.domainName,那么会自动把domainName类再放到somepck包里面;
enableCountByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询总条数语句(用于分页的总条数查询);
enableUpdateByExample(默认true):MyBatis3Simple为false,指定是否生成动态修改语句(只修改对象中不为空的属性);
enableDeleteByExample(默认true):MyBatis3Simple为false,指定是否生成动态删除语句;
enableSelectByExample(默认true):MyBatis3Simple为false,指定是否生成动态查询语句;
-->
<!-- <table tableName="t_category" domainObjectName="Category" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
使用自增长键
<property name="my.isgen.usekeys" value="true"/>
如果设置为true,生成的model类会直接使用column本身的名字,而不会再使用驼峰命名方法,比如BORN_DATE,生成的属性名字就是BORN_DATE,而不会是bornDate
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<table tableName="t_property" domainObjectName="Property" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
<property name="my.isgen.usekeys" value="true"/>
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<table tableName="t_product" domainObjectName="Product" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
<property name="my.isgen.usekeys" value="true"/>
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<table tableName="t_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="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<table tableName="t_order" domainObjectName="Order" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
<property name="my.isgen.usekeys" value="true"/>
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<table tableName="t_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="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<table tableName="t_review" domainObjectName="Review" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
<property name="my.isgen.usekeys" value="true"/>
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<table tableName="t_user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="true" selectByExampleQueryId="false">
<property name="my.isgen.usekeys" value="true"/>
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
<table tableName="t_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="false"/>
<generatedKey column="id" sqlStatement="JDBC"/>
</table> -->
</context>
</generatorConfiguration>
~~~
## 步骤 4 : MybatisGenerator
运行即生成pojo.mapper和xml。
> 注: 生成代码成功,只能执行一次,以后执行会覆盖掉mapper,pojo,xml 等文件上做的修改。所以在程序开始,我做了一些手脚,必须把today变量修改为今天才可以执行,这样明天再执行就无法运行了,以免以后对Category类做了改动,不小心运行了MybatisGenerator 导致Category类上做的手动改动被覆盖掉了。
~~~
package com.dodoke.tmall.util;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class MybatisGenerator {
public static void main(String[] args) throws Exception {
String today = "2018-08-31";
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd");
Date now =sdf.parse(today);
Date d = new Date();
if(d.getTime()>now.getTime()+1000*60*60*24){
System.err.println("——————未成成功运行——————");
System.err.println("——————未成成功运行——————");
System.err.println("本程序具有破坏作用,应该只运行一次,如果必须要再运行,需要修改today变量为今天,如:" + sdf.format(new Date()));
return;
}
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
InputStream is= MybatisGenerator.class.getClassLoader().getResource("generatorConfig.xml").openStream();
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(is);
is.close();
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
System.out.println("生成代码成功,只能执行一次,以后执行会覆盖掉mapper,pojo,xml 等文件上做的修改");
}
}
~~~
## 步骤 5 : 自动生成的Category
这里是插件自动生成的代码,和手动编写的区别在于id类型从基本类型id变成了Integer。
~~~
package com.dodoke.tmall.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();
}
}
~~~
## 步骤 6 : 自动生成的CategoryExample
MybatisGenerator会生成一个类叫做XXXXExample的。 它的作用是进行排序,条件查询的时候使用。
在分类管理里用到了排序,但是没有使用到其条件查询,在后续的属性管理里就会看到其条件查询的用法了。
这个类比较复杂,我也没有去深入研究它是如何工作的,只是拿来使用。有兴趣的同学可以自己对每行代码进行解读。
~~~
package com.dodoke.tmall.pojo;
import java.util.ArrayList;
import java.util.List;
public class CategoryExample {
protected String orderByClause;
protected boolean distinct;
protected List<Criteria> oredCriteria;
public CategoryExample() {
oredCriteria = new ArrayList<Criteria>();
}
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
public String getOrderByClause() {
return orderByClause;
}
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
public boolean isDistinct() {
return distinct;
}
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(Integer value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(Integer value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(Integer value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(Integer value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(Integer value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(Integer value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<Integer> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<Integer> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(Integer value1, Integer value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(Integer value1, Integer value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andNameIsNull() {
addCriterion("name is null");
return (Criteria) this;
}
public Criteria andNameIsNotNull() {
addCriterion("name is not null");
return (Criteria) this;
}
public Criteria andNameEqualTo(String value) {
addCriterion("name =", value, "name");
return (Criteria) this;
}
public Criteria andNameNotEqualTo(String value) {
addCriterion("name <>", value, "name");
return (Criteria) this;
}
public Criteria andNameGreaterThan(String value) {
addCriterion("name >", value, "name");
return (Criteria) this;
}
public Criteria andNameGreaterThanOrEqualTo(String value) {
addCriterion("name >=", value, "name");
return (Criteria) this;
}
public Criteria andNameLessThan(String value) {
addCriterion("name <", value, "name");
return (Criteria) this;
}
public Criteria andNameLessThanOrEqualTo(String value) {
addCriterion("name <=", value, "name");
return (Criteria) this;
}
public Criteria andNameLike(String value) {
addCriterion("name like", value, "name");
return (Criteria) this;
}
public Criteria andNameNotLike(String value) {
addCriterion("name not like", value, "name");
return (Criteria) this;
}
public Criteria andNameIn(List<String> values) {
addCriterion("name in", values, "name");
return (Criteria) this;
}
public Criteria andNameNotIn(List<String> values) {
addCriterion("name not in", values, "name");
return (Criteria) this;
}
public Criteria andNameBetween(String value1, String value2) {
addCriterion("name between", value1, value2, "name");
return (Criteria) this;
}
public Criteria andNameNotBetween(String value1, String value2) {
addCriterion("name not between", value1, value2, "name");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
}
}
~~~
## 步骤 7 : 自动生成的CategoryMapper.xml
这是插件自动生成的xml,与我们自己手动写的也差不了多少,主要区别在于提供了一个 id="Example_Where_Clause"的SQL,借助这个可以进行多条件查询。
同样的我也没有去深入研究它是如何工作的,只是拿来使用。有兴趣的同学可以自己进行解读。
~~~
<?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="com.dodoke.tmall.mapper.CategoryMapper">
<resultMap id="BaseResultMap" type="com.dodoke.tmall.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="com.dodoke.tmall.pojo.CategoryExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
'false' as QUERYID,
<include refid="Base_Column_List" />
from t_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 t_category
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from t_category
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.dodoke.tmall.pojo.Category" useGeneratedKeys="true">
insert into t_category (name)
values (#{name,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.dodoke.tmall.pojo.Category" useGeneratedKeys="true">
insert into t_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="com.dodoke.tmall.pojo.Category">
update t_category
<set>
<if test="name != null">
name = #{name,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.dodoke.tmall.pojo.Category">
update t_category
set name = #{name,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
~~~
> 生成的xml是比较晦涩的,感兴趣的同学,百度搜索这些用法。
## 步骤 8 : 自动生成的CategoryMapper
与手动编写的CategoryMapper比起来,CategoryMapper也是提供CURD一套,不过方法名发生了变化,比如:
delete叫做deleteByPrimaryKey,
update叫做updateByPrimaryKey.
除此之外,修改还提供了一个updateByPrimaryKeySelective,其作用是只修改变化了的字段,未变化的字段就不修改了。
还有个改动是查询list,变成了`selectByExample(CategoryExample example); `这个方法的用法在紧接着的修改CategoryServiceImpl 中有演示
~~~
package com.dodoke.tmall.mapper;
import com.dodoke.tmall.pojo.Category;
import com.dodoke.tmall.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);
}
~~~
## 步骤 9 : CategoryService没变化
CategoryService没变化,略过不表
## 步骤 10 : 修改CategoryServiceImpl
因为CategoryMapper的方法名发生了变化,所以CategoryServiceImpl要做相应的调整。
值得一提的是list方法:
~~~
CategoryExample example =new CategoryExample();
example.setOrderByClause("id desc");
return categoryMapper.selectByExample(example);
~~~
按照这种写法,传递一个example对象,这个对象指定按照id倒排序来查询
~~~
package com.dodoke.tmall.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.dodoke.tmall.mapper.CategoryMapper;
import com.dodoke.tmall.pojo.Category;
import com.dodoke.tmall.pojo.CategoryExample;
import com.dodoke.tmall.service.CategoryService;
@Service
public class CategoryServiceImpl implements CategoryService {
@Autowired
CategoryMapper categoryMapper;
@Override
public List<Category> list() {
CategoryExample example = new CategoryExample();
example.setOrderByClause("id desc");
return categoryMapper.selectByExample(example);
}
@Override
public void add(Category category) {
categoryMapper.insert(category);
}
@Override
public void delete(int id) {
categoryMapper.deleteByPrimaryKey(id);
}
@Override
public Category get(int id) {
return categoryMapper.selectByPrimaryKey(id);
}
@Override
public void update(Category category) {
categoryMapper.updateByPrimaryKeySelective(category);
}
}
~~~
## 步骤 11 : CategoryController没变化
CategoryController没变化,略过不表
## 步骤 12 : 可运行项目
重构不会影响功能性,所以重构之后的代码一样可以实现分类管理的功能。
鉴于重构经历了较多的步骤,并且略微复杂,任何一步出了问题都会导致目前项目运行失败,实在自己搞不出来,拿到本章节对应的项目,解压出来比较一下。
## 步骤 13 : 改动效果
按照这种方式修改之后,分类的pojo,xml.mapper都不用自己写的,大大提高了生产效率。
在下一个知识点也会演示其余8个实体类自动生成,一下子对应的pojo,xml,mapper都好了,生成出来的代码可读性也很好,还不会出错,生产效率简直提高得不要不要的。
- 项目简介
- 功能一览
- 前台
- 后台
- 开发流程
- 需求分析-展示
- 首页
- 产品页
- 分类页
- 搜索结果页
- 购物车查看页
- 结算页
- 确认支付页
- 支付成功页
- 我的订单页
- 确认收货页
- 确认收货成功页
- 评价页
- 需求分析-交互
- 分类页排序
- 立即购买
- 加入购物车
- 调整订单项数量
- 删除订单项
- 生成订单
- 订单页功能
- 确认付款
- 确认收货
- 提交评价信息
- 登录
- 注册
- 退出
- 搜索
- 前台需求列表
- 需求分析后台
- 分类管理
- 属性管理
- 产品管理
- 产品图片管理
- 产品属性设置
- 用户管理
- 订单管理
- 后台需求列表
- 表结构设计
- 数据建模
- 表与表之间的关系
- 后台-分类管理
- 可运行的项目
- 静态资源
- JSP包含关系
- 查询
- 分页
- 增加
- 删除
- 编辑
- 修改
- 做一遍
- 重构
- 分页方式
- 分类逆向工程
- 所有逆向工程
- 后台其他页面
- 属性管理实现
- 产品管理实现
- 产品图片管理实现
- 产品属性值设置
- 用户管理实现
- 订单管理实现
- 前端
- 前台-首页
- 可运行的项目
- 静态资源
- ForeController
- home方法
- home.jsp
- homePage.jsp
- 前台-无需登录
- 注册
- 登录
- 退出
- 产品页
- 模态登录
- 分类页
- 搜索
- 前台-需要登录
- 购物流程
- 立即购买
- 结算页面
- 加入购物车
- 查看购物车页面
- 登录状态拦截器
- 其他拦截器
- 购物车页面操作
- 订单状态图
- 生成订单
- 我的订单页
- 我的订单页操作
- 评价产品
- 总结