整合MyBatis实战Web MVC开发流程

    科技2025-10-21  11

    目录

    步骤一:建立数据库表user_order

    步骤二:mybatis逆向工程生成Entity/Mapper/Mapper.xml

    步骤三:定义Controller/Service/Util/中间件服务...开启CRUD征战之旅

    结合WebMVC中的View

    删除订单

    分页模糊查询订单

    新增订单和修改订单


    MVC Java Web应用项目开发中盛行的一种开发模式!!

    Model实体 View视图  Controller控制器

    MVC开发流程~无非就是针对一个功能模块进行CRUD操作!

    CRUD一般只是个简称,许多功能模块的操作远远不知CRUD

    步骤一:建立数据库表user_order

    use sb_middleaware; create table user_order( id int(11) not null auto_increment, order_no varchar(100) not null comment "订单编号", user_id int(11) not null comment "用户id", is_active smallint(4) default 1 comment "状态(1=有效;0=无效)", create_time datetime default current_timestamp comment "下单时间", update_time timestamp null default null on update current_timestamp, primary key(id), unique key idx_order_no(order_no) using btree ) engine=InnoDB auto_increment=5 default charset=utf8 comment="用户下单记录表";

    步骤二:mybatis逆向工程生成Entity/Mapper/Mapper.xml

    导入GenerateSqlmapCustom工程,修改generatorConfig.xml文件,再运行GenerateSqlmap类即可

    <?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="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <!-- <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://47.107.235.77:3306/db_second_auth" userId="root" password="linsen"> </jdbcConnection> --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/sb_middleaware?characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Hongkong" userId="root" password="cuihua4huajie"> </jdbcConnection> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="true" /> </javaTypeResolver> <!-- targetProject:生成PO类的位置 --> <javaModelGenerator targetPackage="com.cuihua.boot.middleware.model.entity" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.cuihua.boot.middleware.model.mappers" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.cuihua.boot.middleware.model.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定数据库表 --> <table schema="" tableName="user_order" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> </table> <!-- <table schema="" tableName="user" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false" enableUpdateByExample="false"> </table> --> </context> </generatorConfiguration>

    将自动生成的entiry mapper mappers拷贝至项目中(注意,mappers文件夹拷贝至resouces目录下,不然会出现绑定错误的问题)

    步骤三:定义Controller/Service/Util/中间件服务...开启CRUD征战之旅

    UserOrderController.java

    package com.cuihua.boot.middleware.server.controller; import com.cuihua.boot.middleware.api.response.BaseResponse; import com.cuihua.boot.middleware.api.response.StatusCode; import com.cuihua.boot.middleware.model.entity.UserOrder; import com.cuihua.boot.middleware.server.service.UserOrderService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("user/order") public class UserOrderController extends AbstractController{ @Autowired private UserOrderService userOrderService; @RequestMapping(value = "info", method = RequestMethod.GET) @ResponseBody public BaseResponse info(@RequestParam String orderNo){ if(StringUtils.isBlank(orderNo)){ return new BaseResponse(StatusCode.InvalidParam); } BaseResponse response = new BaseResponse(StatusCode.Success); try{ response.setData(userOrderService.getInfo(orderNo)); }catch (Exception e){ log.error("用户提交订单controller~订单详情~发生异常:orderNo={}", orderNo, e.fillInStackTrace()); response = new BaseResponse(StatusCode.Fail); } return response; } }

    写Service层,先自己编写sql语句运行,写dao层

    在UserOrderMapper中添加对应的方法

    serOrder selectByOrderNo(@Param("orderNo") String orderNo);

    在 UserOrderMapper.xml中写sql语句

    <select id="selectByOrderNo" resultType="com.cuihua.boot.middleware.model.entity.UserOrder"> select <include refid="Base_Column_List"/> from user_order where is_active = 1 and order_no = #{orderNo}; </select>

    UserOrderService类 

    package com.cuihua.boot.middleware.server.service; import com.cuihua.boot.middleware.model.entity.UserOrder; import com.cuihua.boot.middleware.model.mapper.UserOrderMapper; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserOrderService{ private static final Logger log = LoggerFactory.getLogger(UserOrder.class); @Autowired private UserOrderMapper userOrderMapper; //获取用户订单详情 public UserOrder getInfo(final String orderNo) throws Exception{ if(StringUtils.isNotBlank(orderNo)){ return userOrderMapper.selectByOrderNo(orderNo); } return null; } }

    在mybatis-config.xml中开启sql控制台输出

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!-- Globally enables or disables any caches configured in any mapper under this configuration --> <setting name="cacheEnabled" value="true"/> <!-- Sets the number of seconds the driver will wait for a response from the database --> <setting name="defaultStatementTimeout" value="3000"/> <!-- Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- Allows JDBC support for generated keys. A compatible driver is required. This setting forces generated keys to be used if set to true, as some drivers deny compatibility but still work --> <setting name="useGeneratedKeys" value="true"/> <!-- 设置控制台打印sql --> <setting name="logImpl" value="stdout_logging" /> </settings> <!-- Continue going here --> <plugins> <!-- com.github.pagehelper为PageHelper类所在包名 --> <plugin interceptor="com.github.pagehelper.PageHelper"> <!-- 4.0.0以后版本可以不设置该参数 --> <property name="dialect" value="mysql"/> <!-- 该参数默认为false --> <!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 --> <!-- 和startPage中的pageNum效果一样--> <property name="offsetAsPageNum" value="true"/> <!-- 该参数默认为false --> <!-- 设置为true时,使用RowBounds分页会进行count查询 --> <property name="rowBoundsWithCount" value="true"/> <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 --> <!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)--> <property name="pageSizeZero" value="true"/> <!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 --> <!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 --> <!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 --> <property name="reasonable" value="false"/> <!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 --> <!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 --> <!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,orderBy,不配置映射的用默认值 --> <!-- 不理解该含义的前提下,不要随便复制该配置 --> <!--<property name="params" value="pageNum=pageHelperStart;pageSize=pageHelperRows;"/>--> <!-- 支持通过Mapper接口参数来传递分页参数 --> <property name="supportMethodsArguments" value="false"/> <!-- always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page --> <property name="returnPageInfo" value="none"/> </plugin> </plugins> </configuration>

    结合WebMVC中的View

    配置可以访问静态资源js,css, image等等

    在config包下新建一个配置类,

    @Configuration public class CustomWebConfig implements WebMvcConfigurer { public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/statics/**").addResourceLocations("classpath:/statics/"); } }

    Controller中 

    @RequestMapping(value = "info/page", method = RequestMethod.GET) public String pageInfo(@RequestParam String orderNo, ModelMap modelMap){ modelMap.put("orderNo",orderNo); return "userOrder"; }

     templates下的UserOrder.html

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="${request.contextPath}/statics/jquery-1.7.1.js" type="text/javascript"></script> <title>用户订单详情</title> </head> <input id="orderNo" value="${orderNo}" type="text"/> <body> <div id="infoNo"> <strong>查到暂无该订单详情</strong> </div> <div id="infoYes"> <strong>当前订单编号:</strong><span class="currOrderNo"></span><br/> <strong>订单用户ID:</strong><span class="currUserId"></span><br/> <strong>是否有效(1=是: 0=否):</strong><span class="currActice"></span><br/> <strong>创建订单时间:</strong><span class="currOrderTime"></span><br/> </div> </body> <script> $(function () { var orderNo = $("#orderNo").val(); var url = "http://localhost:9099/middleware/user/order/info"; $.get( url, { orderNo:orderNo }, function (res) { console.log(res); if(res.data == null){ $("#infoYes").attr("hidden", "hidden"); } else{ $("#infoNo").attr("hidden", "hidden"); $(".currOrderNo").html(res.data.orderNo); $(".currUserId").html(res.data.userId); $(".currActive").html(res.data.isActive); $(".currOrderTime").html(res.data.createTime); } } ); }); </script> </html>

    步骤四:CRUD的先后征战顺序~查询-分页模糊查询-新增-修改-删除-......

    删除订单

    UserOrderMapper.xml

    <delete id="deleteOrder"> update user_order set is_active = 0, update_time = now() where id= #{id} </delete> UserOrderMapper接口 Integer deleteOrder(@Param("id") Integer id); UserOrderService类 //删除订单(逻辑删除) public Integer delete(final Integer id) throws Exception{ return userOrderMapper.deleteOrder(id); }

    UserOrderController类

    @RequestMapping(value = "/delete", method = RequestMethod.POST) @ResponseBody public BaseResponse delete(@RequestParam Integer id){ if(id == null || id <= 0){ return new BaseResponse(StatusCode.InvalidParam); } BaseResponse response = new BaseResponse(StatusCode.Success); try{ userOrderService.delete(id); }catch (Exception e){ log.error("用户订单controler-删除订单-发生异常:id={}", id, e.fillInStackTrace()); return new BaseResponse(StatusCode.Fail); } return response; }

    分页模糊查询订单

    两个Dto类 PageDto类 和具体的UserOrderPageDto类

    package com.cuihua.boot.middleware.model.dto; import java.io.Serializable; public class PageDto implements Serializable { //这两个参数由前端传递过来,如果前端未传,需要给定一个默认值 private Integer pageNo = 1; private Integer pageSize = 10; public Integer getPageNo() { return pageNo; } public void setPageNo(Integer pageNo) { this.pageNo = pageNo; } public Integer getPageSize() { return pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } }

     

    package com.cuihua.boot.middleware.model.dto; import java.io.Serializable; //用户订单分页查询dto public class UserOrderPageDto extends PageDto implements Serializable { private String search; public String getSearch() { return search; } public void setSearch(String search) { this.search = search; } }

    mapper.xml 

    <select id="pageSelectOrder" resultType="com.cuihua.boot.middleware.model.entity.UserOrder" parameterType="com.cuihua.boot.middleware.model.dto.UserOrderPageDto"> select <include refid="Base_Column_List"></include> from user_order where is_active = 1 <if test="search!=null and search!= ''"> and order_no like concat('%', #{search}, '%') </if> order by create_time desc </select>

    mapper接口

    List<UserOrder> pageSelectOrder(UserOrderPageDto dto);

    service层

    //分页查询用户订单列表 public PageInfo<UserOrder> pageGetOrders(UserOrderPageDto userOrderPageDto) throws Exception{ //直接利用MyBatis提供的分页插件,而不是直接去写原生代码 PageHelper.startPage(userOrderPageDto.getPageNo(), userOrderPageDto.getPageSize()); List<UserOrder> list = userOrderMapper.pageSelectOrder(userOrderPageDto); return new PageInfo<UserOrder>(list); }

    controller层

    @RequestMapping(value = "page/list", method = RequestMethod.GET) @ResponseBody public BaseResponse pageList(UserOrderPageDto userOrderPageDto){ BaseResponse response = new BaseResponse(StatusCode.Success); try{ response.setData(userOrderService.pageGetOrders(userOrderPageDto)); }catch (Exception e){ log.error("用户订单controler-分页模糊查询订单-发生异常:dto={}", userOrderPageDto, e.fillInStackTrace()); return new BaseResponse(StatusCode.Fail); } return response; }

    请求结果

    新增订单和修改订单

    UserOrderDto类

    package com.cuihua.boot.middleware.model.dto; import java.io.Serializable; public class UserOrderDto implements Serializable { private Integer id; private String orderNo; private Integer userId; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public Integer getUserId() { return userId; } public void setUserId(Integer usrId) { this.userId = usrId; } }

    service层

    //新增订单 public Integer add(UserOrderDto dto) throws Exception{ UserOrder entity = new UserOrder(); BeanUtils.copyProperties(dto, entity); entity.setId(null); entity.setCreateTime(DateTime.now().toDate()); userOrderMapper.insert(entity); //需要在mapper.xml中指定useGeneratedKeys="true" keyProperty="id" return entity.getId(); } //修改订单 public Integer update(UserOrderDto dto) throws Exception{ UserOrder entity = userOrderMapper.selectByPrimaryKey(dto.getId()); if(entity != null){ //id的值不需要再进行修改 BeanUtils.copyProperties(dto, entity, "id"); entity.setUpdateTime(DateTime.now().toDate()); userOrderMapper.updateByPrimaryKeySelective(entity); } return dto.getId(); }

    controller层

    @RequestMapping(value = "add", method = RequestMethod.POST) @ResponseBody public BaseResponse add(@RequestBody UserOrderDto userOrderDto){ if(StringUtils.isBlank(userOrderDto.getOrderNo()) || userOrderDto.getUserId() == null){ return new BaseResponse(StatusCode.InvalidParam); } BaseResponse response = new BaseResponse(StatusCode.Success); try{ Integer id = userOrderService.add(userOrderDto); response.setData(id); }catch (Exception e){ log.error("用户订单controler-新增订单-发生异常:dto={}", userOrderDto, e.fillInStackTrace()); return new BaseResponse(StatusCode.Fail); } return response; } @RequestMapping(value = "update", method = RequestMethod.POST) @ResponseBody public BaseResponse update(@RequestBody UserOrderDto userOrderDto){ if(StringUtils.isBlank(userOrderDto.getOrderNo()) || userOrderDto.getUserId() == null){ return new BaseResponse(StatusCode.InvalidParam); } BaseResponse response = new BaseResponse(StatusCode.Success); try{ Integer id = userOrderService.update(userOrderDto); }catch (Exception e){ log.error("用户订单controler-修改订单-发生异常:dto={}", userOrderDto, e.fillInStackTrace()); return new BaseResponse(StatusCode.Fail); } return response; }

     注意参数的@RequestBody;不然就会出错

    结果

     

    Processed: 0.009, SQL: 8