[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講解,這里先準備這個類。
> 不用需知道這個是內部是怎么操作的,直接拿來用,這也是從網上搜到的。
>

~~~
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表。

~~~
<?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
- 前臺-無需登錄
- 注冊
- 登錄
- 退出
- 產品頁
- 模態登錄
- 分類頁
- 搜索
- 前臺-需要登錄
- 購物流程
- 立即購買
- 結算頁面
- 加入購物車
- 查看購物車頁面
- 登錄狀態攔截器
- 其他攔截器
- 購物車頁面操作
- 訂單狀態圖
- 生成訂單
- 我的訂單頁
- 我的訂單頁操作
- 評價產品
- 總結