【Java从0到架构师】项目实战 - 驾考(旧)- Freemarker、MyBatis-Plus
项目实战 - 驾考(旧)- Freemarker、MyBatis-Plus
- 各种 Object
- Freemarker
- 简单使用
- 常用功能
- 集成到 SpringBoot
- MyBatis-Plus
- 简单使用
- 分页配置
- MyBatis Generator - 配置文件、插件
- 查询条件 Wrapper
- MySQL 建议 - 数据类型的选择
- Easy Code
- 逻辑删除
- 驾考(旧)知识点
- 分页的类设计(包含关键字)
- mybatis-plus 封装好的分页
- 多表查询
Java 从 0 到架构师目录:【Java从0到架构师】学习记录
Gitee 代码:https://gitee.com/szluyu99/mj_java_frame/tree/master/05_Project/OldJiaKao
企业开发中常见的后台管理系统:
CRM (Customer Relationship Management):客户关系管理
- 管理客户信息(个人信息、订单信息等)
OA (Office Automation):办公自动化
- 基于工作流概念,使企业内部人员方便快捷地共享信息,高效协同工作
ERP (Office Automation):企业资源管理
- 物资资源管理、人力资源管理、财务资源管理、信息资源管理等集成一体化
各种 Object
在阿里巴巴的开发手册,定义了各种 object,比如:PO,BO,DTO、VO,POJO、Query
PO (Persistent Object):持久化对象
- 属性跟数据库表的字段对应,一个 PO 对象对应数据表的一条记录
BO (Business Object):业务对象
- 一类业务就会对应一个 BO,除了 get \ set 方法以外,它有很多业务操作,比如针对自身数据进行计算的方法
PO 与 BO 示例1:
- PO1 是教育经理,PO2 是工作经历,PO3 是项目经理
- BO 是简历,包含 PO1 ~ PO3
PO 与 BO 示例2:
- PO1 是交易记录,PO2 是登陆记录,PO3 是商品浏览记录,PO4 是购物车记录,PO5 是搜索记录
- BO 是个人网站行为,包含 PO1 ~ PO5
DTO (Data Transfer Object):数据传输对象
- 很多时候并不需要 PO 的所有属性(数据库表的所有字段)传输给客户端
- 所以,可以根据客户端的业务需要对 PO、BO 的属性进行增删,重新组装成 DTO 对象
VO (View Object):视图对象
- 传输给客户端的数据展示对象,通常对应一个页面
- 在有些时候,业务字段的值和最终展示的值是不一样的,比如:DTO 中,sex 的值是:0、1
页面 A 的 VO 中,sex 的值是:男生、女生
页面 B 的 VO 中,sex 的值是:帅哥、美女
POJO (Plain Ordinary Java Object):简单的 Java 对象
- 是 PO、BO、DTO、VO 的统称
Query:数据查询对象
Freemarker
Gitee 代码:驾考 - Freemarker
中文官网:http://freemarker.foofun.cn/
与 JSP、Thymeleaf 一样,Freemarker 也是一款优秀的模版引擎
- 可以生成任意格式的文本文件(HTML、XML、Java 等),与 Web 环境无关,不依赖 Web 容器
Freemarker 是在公司中非常受欢迎的一款模板引擎
对比 JSP、Thymeleaf:
- JSP:只能用在 Web 环境中,依赖于 Web 容器
- Thymeleaf:虽然不依赖 Web 容器,但它只能生成 XML 规范的文本文件
XML 规范:比如 HTML、XML 等由标签对、单标签组成的文件格式
简单使用
引入依赖:
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version>
</dependency>
准备一个模版文件,它的后缀名是:.ftl
(FreeMarker Template Language)
<#-- test.ftl -->
<html><body><h2>${name}</h2><h3>${age}</h3></body>
</html>
在 Java 代码中给模版填充数据:
Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
cfg.setDefaultEncoding("UTF-8");// 模板文件的存放目录
cfg.setDirectoryForTemplateLoading(new File("F:/templates"));// 数据
Map<String, Object> data = new HashMap<>();
data.put("name", "MJ");
data.put("age", 10);try (FileWriter out = new FileWriter(new File("F:/templates/test.html"))) {// 获取模板文件Template tpl = cfg.getTemplate("mapper.ftl");// 合并数据到模版文件中tpl.process(data, out);
}
常用功能
Freemarker 中的注释,使用这种注释不会渲染 到 HTML中
<#-- -->
Freemarker 中抽取公共代码:
<#include "common/style.ftlh">
Freemarker 中默认渲染 Null 会报错,在后面加个 !
则不可以渲染 Null 不报错
${query.keyword!}
集成到 SpringBoot
<!-- Freemarker -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
与之前学习的 Thymeleaf 一样:
- 静态资源:可以放在 classpath:/static/ 目录下
- 模版文件:可以放在 classpath:/templates/ 目录下
需要注意的是,在 SpringBoot 中:
- freemarker 的模版文件拓展名要用
.ftlh
,而不是.ftl
- 默认的视图解析器会增加前缀:classpath:/templates/;增加后缀:.ftlh
Freemarker 中获取项目路径的方法,建议写在 .ftlh 文件的第一行:
<#-- 获取context path, 赋值给ctx -->
<#assign ctx="${springMacroRequestContext.getContextPath()}">
MyBatis-Plus
MyBatis-Plus(简称 MP )是 MyBatis 的增强工具
- 在 MyBatis 的基础上只做增强不做改名,为简化开发、提高效率而生
- 官网:https://baomidou.com/
简单使用
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version>
</dependency>
public interface DictTypeMapper extends BaseMapper<DicType> {}
public interface DicTypeService extends IService<DictType> {}
@Service
@Transactional
public class DictTypeServiceImplextends ServiceImpl<DictTypeMapper, DictTyp>implements DictTypeService {@Autowiredprivate DictTypeMapper mapper;
}
分页配置
Gitee 代码:分页配置
@Configuration
@MapperScan("com.mj.jk.mapper")
public class MyBatisPlusCfg {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();PaginationInnerInterceptor innerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);// 当页数超过总页数时,自动跳回到第1页innerInterceptor.setOverflow(true);interceptor.addInnerInterceptor(innerInterceptor);return interceptor;}@Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration -> configuration.setUseDeprecatedExecutor(false);}
}
MyBatis Generator - 配置文件、插件
参考:http://mybatis.org/generator/
MyBatis Generator 是 MyBatis 官方提供的代码生成器
- 可以根据数据库信息,逆向生成 Model 类,Mapper 类,Mapper 配置文件
- 大大节省开发者的编码时间,提高开发效率
在 resources 目录下准备一个 generationConfig.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration><context id="default" targetRuntime="MyBatis3Simple"><commentGenerator><!-- 去除所有注释 --><property name="suppressAllComments" value="true"/></commentGenerator><!-- 数据库连接 --><jdbcConnection driverClass="com.mysql.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/new_jiakao?serverTimezone=GMT%2B8"userId="root" password="root"/><!-- Model的位置 --><javaModelGenerator targetPackage="com.mj.jk.pojo.po"targetProject="src/test/java"/><!-- XML的位置 --><sqlMapGenerator targetPackage="com.mj.jk.mapper"targetProject="src/test/resources"/><!-- Mapper的位置 --><javaClientGenerator type="XMLMAPPER"targetPackage="com.mj.jk.mapper"targetProject="src/test/java"/><!-- %代表所有表 --><table tableName="%"/><!-- table tableName="dict_type"/> --></context>
</generatorConfiguration>
MyBatis Generator - 插件:
<plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.2</version><configuration><configurationFile>src/test/resources/generatorConfig.xml</configurationFile><overwrite>true</overwrite><verbose>true</verbose></configuration><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency></dependencies>
</plugin>
查询条件 Wrapper
// 查询条件
LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();wrapper.like(DictType::getName, keyword).or().like(DictType::getValue, keyword).or().like(DictType::getIntro, keyword);
MySQL 建议 - 数据类型的选择
优先使用符合需求的最小数据类型
- 比如:非负数就是用 UNSIGNED、使用 INT UNSIGNED 存储 IP 地址
INET_ATON (‘255.255.255.255’) = 4294967295
INET_NTOA (4294967295) = ‘255.255.255.255’
固定长度的字符串就是用 CHAR
- 比如手机号、身份证、MD5 密码
谨慎使用 TEXT、 ENUM
- TEXT 在很多时候会降低数据库的性能
- 当需要修改 ENUM 类型的待选值时,需要使用 ALTER 语句(需要锁表)
金钱相关的数据,必须使用 DECIMAL 类型
注意, Java 中的整数类型都是有符号的,与 MySQL 类型的正确映射关系如下:
Easy Code
一款国产的代码生成插件,参考文档:https://gitee.com/makejava/EasyCode/wikis/pages
逻辑删除
物理删除:真正从数据库中删除了,永久消失
逻辑删除(软删除):数据库还留在数据库中,只是对用户来说,数据被删掉了
逻辑删除实现方案:在数据表中增加一个字段标识数据是否被删除
id name deleted age
1 jack 0 10
2 rose 1 10
编写 SQL 的时候需要指定 WHERE deleted = 0
实际上在 MyBatisPlus 中实现逻辑删除特别简单
逻辑删除 - 全局配置:
mybatis-plus:global-config:# 全局配置# 逻辑删除字段logic-delete-field: deleted# 代表已删除的字段值logic-delete-value: 1# 代表未删除的字段值logic-not-delete-value: 0
注意:就算进行了全局配置,在 Po 类中还是要加 deleted 字段
逻辑删除 - 局部配置:
// 局部配置
@TableLogic(value = "0", delval = "1")
@TableField(select = false)
private Short deleted;
注意:自定义 SQL 语句时,MP 并不会自动加上逻辑删除相关的功能,需要自实现逻辑删除
- 也就利用 xml 写 SQL 的时候,需要自己加上逻辑删除
驾考(旧)知识点
项目:驾考(旧)
分页的类设计(包含关键字)
PageQuery.java
@Data
public class PageQuery<T> {private static final int DEFAULT_SIZE = 10;// 当前页数private long page;// 每一页的记录数private long size;// 总记录数private long count;// 总页数private long pages;private List<T> data;public long getPage() {return Math.max(1, page);}public long getSize() {return (size < 1) ? DEFAULT_SIZE : size;}
}
KeywordQuery.java
@EqualsAndHashCode(callSuper = true)
@Data
public class KeywordQuery<T> extends PageQuery<T> {private String keyword;
}
DictTypeQuery.java
@EqualsAndHashCode(callSuper = true)
@Data
public class DictTypeQuery extends KeywordQuery<DictType> {}
mybatis-plus 封装好的分页
DictTypeMapper.java
public interface DictTypeMapper extends BaseMapper<DictType> {}
DictTypeServiceImpl.java
@Service
@Transactional
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictType>implements DictTypeService {@Autowiredprivate DictTypeMapper mapper;@Overridepublic void list(DictTypeQuery query) {// 查询条件LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();String keyword = query.getKeyword();if (!StringUtils.isEmpty(keyword)) {wrapper.like(DictType::getName, keyword).or().like(DictType::getValue, keyword).or().like(DictType::getIntro, keyword);}// 分页对象Page<DictType> page = new Page<>(query.getPage(), query.getSize());// 查询mapper.selectPage(page, wrapper);// 填充queryquery.setData(page.getRecords());query.setCount(page.getTotal());query.setPages(page.getPages());}
}
DictTypeController.java
- 注意
service.list(query);
是将数据重新传回到 query 对象中
@Controller
@RequestMapping("/dictTypes")
public class DictTypeController {@Autowiredprivate DictTypeService service;@GetMapping("/list")public String list(DictTypeQuery query, Model model) {service.list(query);model.addAttribute("query", query);return "pages/dictType";}
}
多表查询
MyBatis Plus 中对单表查询的支持非常好,如果用它实现多表查询,还是需要依赖于 XML 文件
public interface ExamPlaceCourseMapper extends BaseMapper<ExamPlaceCourse> {MpPage<ExamPlaceCourseVo> selectPageVos(MpPage<ExamPlaceCourseVo> page,@Param(Constants.WRAPPER) Wrapper<ExamPlaceCourseVo> wrapper);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mj.jk.mapper.ExamPlaceCourseMapper"><resultMap id="rmSelectPageVos"type="ExamPlaceCourseVo"><id property="id" column="id"/><result property="name" column="name"/><result property="price" column="price"/><result property="type" column="type"/><result property="placeId" column="place_id"/><result property="provinceId" column="province_id"/><result property="cityId" column="city_id"/><result property="cover" column="cover"/></resultMap><select id="selectPageVos"resultMap="rmSelectPageVos">SELECTc.id,c.name,c.price,c.type,c.intro,c.place_id,c.cover,p.province_id,p.city_idFROM exam_place_course cJOIN exam_place p ON p.id = c.place_id${ew.customSqlSegment}</select>
</mapper>
@Override
@Transactional(readOnly = true)
public PageVo<ExamPlaceCourseVo> list(ExamPlaceCoursePageReqVo query) {MpQueryWrapper<ExamPlaceCourseVo> wrapper = new MpQueryWrapper<>();Integer placeId = query.getPlaceId();Integer provinceId = query.getProvinceId();Integer cityId = query.getCityId();Short type = query.getType();// 类型if (type != null && type >= 0) {wrapper.eq("c.type", type);}// 考场 -> 城市 -> 省份if (placeId != null && placeId > 0) {wrapper.eq("c.place_id", placeId);} else if (cityId != null && cityId > 0) {wrapper.eq("p.city_id", cityId);} else if (provinceId != null && provinceId > 0) {wrapper.eq("p.province_id", provinceId);}// 关键词wrapper.like(query.getKeyword(), "c.name", "c.intro");return baseMapper.selectPageVos(new MpPage<>(query), wrapper).buildVo();
}
【Java从0到架构师】项目实战 - 驾考(旧)- Freemarker、MyBatis-Plus相关推荐
- 【Java从0到架构师】项目实战 - 会话管理、EhCache、JWT、权限管理 Shiro、打包部署
项目实战 - 权限管理 会话管理 客户端身份认证 - 基于 Cookie.Session 客户端身份验证 - 基于 token EhCache - 简单的缓存框架 JWT - 基于 JSON 的 to ...
- 【Java从0到架构师】项目实战 - 前后端分离、后端校验、Swagger、全局异常处理
项目实战 - 前后端分离.后端校验.Swagger Layui 同源策略 SpringMVC 实现 CORS 后端校验 - hibernate-validator 方法的 Model 参数校验 方法的 ...
- 【Java从0到架构师】个人简历项目实战
项目实战 功能性 登陆流程 验证码 JavaWeb Service.Dao 方法名规范 form 文件上传 - 前端.后台.实时预览 页面可见性 Service 层 面向接口编程 后端技巧 利用 Ja ...
- 【Java从0到架构师】Maven - 依赖冲突、分模块构建项目
SpringBoot - Maven 补充 依赖冲突 解决方案 - dependencyManagement 自定义属性 分模块构建项目 继承 - parent 聚合 - modules 依赖 - d ...
- 【Java从0到架构师(1),Java中高级面试题总结(全面)
JSP 九大内置对象 MySQL 基础 + 多表查询 [Java从0到架构师]MySQL 基础 MySQL MySQL 的使用步骤 数据库的内部存储细节 GUI 工具 SQL 语句 DDL 语句 DD ...
- 【Java从0到架构师】SpringCloud - Sleuth、Zipkin、Config
SpringCloud 链路追踪组件 Sleuth Zipkin 分布式配置中心 - Config Git + Config 分布式配置中心 Java 从 0 到架构师目录:[Java从0到架构师]学 ...
- 【Java从0到架构师】SpringCloud - Hystrix、Zuul
SpringCloud 基本概念 熔断和降级 服务雪崩效应 服务熔断与降级 - Hystrix SpringBoot 集成 Hystrix 熔断降级服务异常报警通知 重点属性 - 熔断隔离策略.超时时 ...
- 【Java从0到架构师】SpringCloud - Eureka、Ribbon、Feign
SpringCloud 分布式.微服务相关概念 微服务框架构选型 SpringCloud 概述 服务注册与发现 - Eureka 案例项目 Eureka 自我保护机制 微服务调用方式 - Ribbon ...
- 【Java从0到架构师】RocketMQ 基础 - 应用、核心组件、安装
RocketMQ 消息中间件 基础知识 消息中间件的应用 异步解耦 削峰填谷 消息分发 RocketMQ 核心组件 RocketMQ 安装 源码安装 修改配置参数 启动 管理控制台安装 测试项目 Ja ...
最新文章
- QT发布中遇到的问题 - wufan的专栏 - 博客频道 - CSDN.NET
- pycharm导入自定义模块问题
- 【前端就业课 第一阶段】HTML5 零基础到实战(十一)canvas 基础
- ip_forward
- 计算机数据恢复报告单,计算机数据恢复第三章MBR引导分析篇
- 十个提升网站访问性能的方法
- 2018-2019-2 20165222《网络对抗技术》Exp9 Web安全基础
- java J2EE 分层设计思想及各个文件命名规范
- UWB定位系统中为何要加入陀螺仪
- Mac怎么方便看节假日安排,添加中国法定节假日安排
- 基于jsp+mysql+Spring+mybatis的SSM健身房管理系统
- 高中必备学习软件_学霸必备app有哪些高中生必备app排行
- linux新增加swap空间,Linux增加swap空间的方法
- CentOS 7.2 配置Apache服务(httpd)--上篇
- DNS域名解析和正向解析
- rz command
- 我爷爷都看的懂的《栈和队列》,学不会来打我
- 电商交易之订单中心设计(一)
- 粉丝投稿 | Openvino2020.2.117在LattePanda上的安装和demo演示
- H5互动小游戏如何提升用户留存
热门文章
- 麒麟810相当于骁龙多少?
- 新买的手机一直没有更新系统,是不是新买的手机原装系统最好用啊?
- 【leveldb】资料
- vscode 使用flask
- html退出登录_退出登录 0152
- 获取SQL Server数据库增长和收缩事件的详细信息
- 数据库创建存储过程_创建存储过程来修复孤立的数据库用户
- T-SQL命令性能比较– NOT IN与SQL NOT EXISTS与SQL LEFT JOIN与SQL EXCEPT
- EasyNVR智能云终端硬件与EasyNVR解决方案软件综合对比
- Linux下OneinStack一键安装JAVA+PHP+Tomcat+Nginx+MySQL网站环境