MyBatisPlus概述
需要的基础:MyBatis、Spring、 SpringMVC
MyBatisPlus可以节省我们大量工作时间,所有的CRUD代码它都可以自动化完成!JPA、tk-mapper、MyBatisPlus

简介:

MyBatis Plus - 图1MyBatis Plus - 图2

特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

快速入门

地址: https://mp.baomidou.com/guide/quick-start.html#初始化工程
使用第三方组件:
1、导入对应的依赖
2、研究依赖如何配置
3、代码如何编写
4、提高扩展技术能力!

步骤

1、创建数据库mybatis_plus

2、创建user表

  1. DROP TABLE IF EXISTS user;
  2. CREATE TABLE user
  3. (
  4. id BIGINT(20) NOT NULL COMMENT '主键ID',
  5. name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
  6. age INT(11) NULL DEFAULT NULL COMMENT '年龄',
  7. email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
  8. PRIMARY KEY (id)
  9. );
  10. INSERT INTO user (id, name, age, email) VALUES
  11. (1, 'Jone', 18, 'test1@baomidou.com'),
  12. (2, 'Jack', 20, 'test2@baomidou.com'),
  13. (3, 'Tom', 28, 'test3@baomidou.com'),
  14. (4, 'Sandy', 21, 'test4@baomidou.com'),
  15. (5, 'Billie', 24, 'test5@baomidou.com');
  16. -- 真实开发中,version (乐观锁)、deleted (逻辑删除)、gmt_ _create gmt_ modified

导入依赖:

  1. <!--数据库驱动-->
  2. <dependency>
  3. <groupId>mysql</groupId>
  4. <artifactId>mysql-connector-java</artifactId>
  5. </dependency>
  6. <!--lombok-->
  7. <dependency>
  8. <groupId>org.projectlombok</groupId>
  9. <artifactId>lombok</artifactId>
  10. </dependency>
  11. <!--mybatis—plus是自己开发的,并非官方的-->
  12. <!--mybatis—plus-->
  13. <dependency>
  14. <groupId>com.baomidou</groupId>
  15. <artifactId>mybatis-plus-boot-starter</artifactId>
  16. <version>3.0.5</version>
  17. </dependency>

5、连接数据库,

  1. # mysql 5驱动不同 com.mysqL.jdbc.Driver
  2. # mysqL 8驱动不同com.mysqL.cj.jdbc.Driver、需要增加时区的配置 serverTimezone=GMT
  3. spring.datasource.username=root
  4. spring.datasource.password=123456
  5. spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8
  6. spring.datasource.driver-class-name=com.mysql.jdbc.Driver

6、传统方式pojo-dao (连接mybatis ,配置mapper.xml文件) -service-controller

6、使用了mybatis-plus之后

  • pojo
  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class User {
  5. /**
  6. * 主键ID
  7. */
  8. private Long id;
  9. /**
  10. * 姓名
  11. */
  12. private String name;
  13. /**
  14. * 年龄
  15. */
  16. private Integer age;
  17. /**
  18. * 邮箱
  19. */
  20. private String email;
  21. }
  • mapper接口
  1. //在对应的Mapper.上面继承基本的接本BaseMapper
  2. @Repository
  3. /*@Mapper*/
  4. public interface UserMapper extends BaseMapper<User>{
  5. /*
  6. * 一、选择加mapper注解
  7. * 二、选择上面加@Repository 代表持久层
  8. * */
  9. //所有的CRUD操作都已经编写完成了
  10. //不需要像以前的配置一大堆文件了!
  11. }
  • 注意点,我们需要在主启动类上去扫描我们的mapper包下的所有接口@MapperScan("cn.dafran.mapper")
  1. /*扫描dao层注解*/
  2. @SpringBootApplication
  3. @MapperScan("cn.dafran.mapper")
  4. public class MybatisPlusApplication {
  5. public static void main(String[] args) {
  6. SpringApplication.run(MybatisPlusApplication.class, args);
  7. }
  8. }
  • 测试类中测试
  1. @SpringBootTest
  2. class MybatisPlusApplicationTests {
  3. /*继承了BaseMapper,所有的方法都来自己父类,我们也可以编写自己的扩展方法!*/
  4. @Autowired
  5. private UserMapper userMapper;
  6. @Test
  7. void contextLoads() {
  8. //参数是一个Wrapper,条件构造器,这里我们先不用null
  9. // 查询全部用户
  10. List<User> users = userMapper.selectList(null);
  11. users.forEach(System.out::println);
  12. }
  13. }
  • 结果
    MyBatis Plus - 图3

1、SQL谁帮我们写的? MyBati-Plus都写好了
2、方法哪里来的? MyBatis-Plus 都写好了

配置日志

我们所有的sq|现在是不可见的,我们希望知道它是怎么执行的,所以我们必须要看日志!

  1. # 配置日志文件
  2. mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

MyBatis Plus - 图4

SELECT id,name,age,email FROM user 为执行的sql语句

CRUD扩展

Insert 插入操作

  1. //插入测试
  2. @Test
  3. public void testInsert(){
  4. User user = new User();
  5. user.setName("6b92d6");
  6. user.setAge(10);
  7. user.setEmail("dafran@yeah.net");
  8. int result = userMapper.insert(user); //帮我们自动生成id
  9. System.out.println(result); //帮受影响的行数
  10. System.out.println(user); //发现,id会自动回填
  11. }

MyBatis Plus - 图5

数据库插入的id的默认值为:全局的唯- -id

主键生成策略

默认ID_ WORKER全局唯一id

分布式系统唯一id生成 : httpst://www.cnblogs.com/haoxinyue/p/5208136.html

雪花算法:
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。 其核心思想是:使用41 bit作为毫秒数, 10bit作为机器的
ID ( 5个bit是数据中心, 5个bit的机器ID ) , 12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID ) , 最后还
有一一个符号位,永远是0。可以保证几乎全球唯一!

我们需要配置主键自增:
1、实体类字段上@TableId(type = IdType.AUTO )
2、数据库字段一定要是自增!

MyBatis Plus - 图6

3、再次测试插入即可!

MyBatis Plus - 图7

其余的源码解释

  1. pub1ic enum IdType {
  2. AUTO(0),//数据库id自增
  3. NONE(1),//未设置主键
  4. INPUT(2),//手动输入
  5. ID_ _WORKER(3), //默认的全局唯一id
  6. UUID(4),//全局唯一id uuid
  7. ID_ WORKER_ STRI5); //ID_ WORKER 字符串表示法
  8. }

Update 更新操作

  1. //测试更新
  2. @Test
  3. public void testUpdate(){
  4. // 通过条件自动拼接动态sq1
  5. User user = new User();
  6. user.setId(5L);
  7. user.setName("6b92d6");
  8. user.setAge(110);
  9. // 注意: updateById 但是参数是一个对象!
  10. int i = userMapper.updateById(user);
  11. System.out.println(i);
  12. }

MyBatis Plus - 图8

自动填充

创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表: gmt_ create、 gmt _modified几乎所有的表都要配置上!而且需要自动化!

方式一:数据库级别(工作中不允许修改数据库)

1、在表中新增字段create _time, update _time

MyBatis Plus - 图9

2、再次测试插入方法,我们需要先把实体类同步!

  1. /**
  2. * 创建时间
  3. */
  4. private Date createTime;
  5. /**
  6. * 更新时间
  7. */
  8. private Date updateTime;

3、再次更新查看结果即可

MyBatis Plus - 图10

方式二:代码级别

1、删除数据库的默认值、更新操作!

MyBatis Plus - 图11

2、实体类字段属性上需要增加注解

  1. /**
  2. * 创建时间
  3. */
  4. //字段添加填充内容
  5. @TableField(fill = FieldFill.INSERT)
  6. private Date createTime;
  7. /**
  8. * 更新时间
  9. */
  10. @TableField(fill = FieldFill.INSERT_UPDATE)
  11. private Date updateTime;

3、编写处理器来处理这个注解即可!

  1. @Slf4j
  2. @Component //一定不要忘 记把处理器加到IOC容器中!
  3. public class MyMetaObjectHandler implements MetaObjectHandler {
  4. // 插入时的填充策略
  5. @Override
  6. public void insertFill(MetaObject metaObject) {
  7. log.info("start insert fill ...");
  8. //setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
  9. this.setFieldValByName("createTime",new Date(),metaObject);
  10. this.setFieldValByName("updateTime",new Date(),metaObject);
  11. }
  12. // 更新时的填充策略
  13. @Override
  14. public void updateFill(MetaObject metaObject) {
  15. log.info("start uptate fill ...");
  16. this.setFieldValByName("updateTime",new Date(),metaObject);
  17. }
  18. }

4、测试插入、测试更新、观察时间即可!

此处修改成了Auto

MyBatis Plus - 图12

MyBatis Plus - 图13

乐观锁

在面试过程中,我们经常会被问道乐观锁,悲观锁!这个其实非常简单!

乐观锁:顾名思义十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,再次更新值测试
悲观锁:顾名思义十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

乐观锁机制:

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
  1. 乐观锁:1、先查询,获得版本号 version = 1
  2. -- A
  3. update user set name = "dafran", version = version+1
  4. where id = 2 and version = 1
  5. -- B 线程抢先完成,这个时候 version = 2,会导致A修改失败!
  6. update user set name = "dafran", version = version+1
  7. where id = 2 and version = 1

测试MyBatis Plus 乐观锁

1、给数据库中增加version字段!

MyBatis Plus - 图14

2、实体类添加相应字段

  1. /**
  2. * 乐观锁
  3. */
  4. @Version//乐观锁Version注解
  5. private Integer version;

3、注册组件

  1. @Configuration //配置类
  2. @MapperScan("cn.dafran.mapper") //扫描dao层注解
  3. @EnableTransactionManagement
  4. public class MyBatisPlusConfig {
  5. //注册乐观锁插件
  6. @Bean
  7. public OptimisticLockerInterceptor optimisticLockerInterceptor(){
  8. return new OptimisticLockerInterceptor();
  9. }
  10. }

测试乐观锁:

  1. //测试乐观锁成功
  2. @Test
  3. public void testOptimisticLockerInterceptor(){
  4. //1、查询用户信息
  5. User user = userMapper.selectById(1L);
  6. //2、修改用户信息
  7. user.setName("dafran");
  8. user.setEmail("1412148742@qq.com");
  9. //3、执行更新操作
  10. userMapper.updateById(user);
  11. }
  12. //测试乐观锁失败
  13. @Test
  14. public void test2OptimisticLockerInterceptor(){
  15. //线程一
  16. User user = userMapper.selectById(1L);
  17. user.setName("dafran");
  18. user.setEmail("1412148742@qq.com");
  19. //线程二进行插队操作
  20. User user1 = userMapper.selectById(1L);
  21. user1.setName("dafran111");
  22. user1.setEmail("1111412148742@qq.com");
  23. userMapper.updateById(user1);
  24. //自旋锁来多次尝试提交!
  25. userMapper.updateById(user); //如果没有乐观锁就会覆盖插队线程的值!
  26. }

MyBatis Plus - 图15

MyBatis Plus - 图16

Select 查询操作

  1. //测试查询操作
  2. @Test
  3. public void testSelectById(){
  4. User user = userMapper.selectById(1L);
  5. System.out.println(user);
  6. }
  7. //测试批量查询
  8. @Test
  9. public void testSelectByBatchId(){
  10. List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
  11. users.forEach(System.out::println);
  12. }
  13. //条件查询之一 map
  14. @Test
  15. public void testSelectByBatchIds(){
  16. HashMap<String, Object> map = new HashMap<>();
  17. //自定义查询
  18. map.put("name","6b92d6");
  19. map.put("age","1");
  20. List<User> users = userMapper.selectByMap(map);
  21. users.forEach(System.out::println);
  22. }

MyBatis Plus - 图17

MyBatis Plus - 图18

MyBatis Plus - 图19

MyBatis Plus - 图20

分页查询

分页在网站使用的十分之多!

1、原始的limit进行分页
2、pageHelper 第三方插件
3、MP其实也内置了分页插件!

如何使用!

1、配置拦截器组件即可

  1. //分页插件
  2. @Bean
  3. public PaginationInterceptor paginationInterceptor() {
  4. return new PaginationInterceptor();
  5. }

2、直接使用Page对象即可

  1. //测试分页查询
  2. @Test
  3. public void testPage(){
  4. // 参数一:当前页
  5. // 参数二:页面大小
  6. // 使用了分页插件之后,所有的分页操作也变得简单的!
  7. Page<User> page = new Page<>(1,5);
  8. userMapper.selectPage(page,null);
  9. page.getRecords().forEach(System.out::println);
  10. System.out.println(page.getTotal());//总数
  11. }

效率其实并不高

MyBatis Plus - 图21

MyBatis Plus - 图22

Delete 删除操作

基本的删除操作

  1. //测试删除
  2. @Test
  3. public void testDeleteById(){
  4. userMapper.deleteById(1319488871841923074L);
  5. }
  6. //测试批量删除
  7. @Test
  8. public void testDeleteByBatchId(){
  9. userMapper.deleteBatchIds(Arrays.asList(1319306794110586882L,1319306816189394945L));
  10. }
  11. //测试通过map删除
  12. @Test
  13. public void testDeleteMap(){
  14. HashMap<String, Object> map = new HashMap<>();
  15. map.put("name","6b92d6");
  16. userMapper.deleteByMap(map);
  17. }

MyBatis Plus - 图23

MyBatis Plus - 图24

MyBatis Plus - 图25

逻辑删除

物理删除:从数据库中直接移除 deleted = 0
逻辑删除:再数据库中没有被移除,而是通过一个变量来让他失效! deleted = 0 => deleted = 1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

测试一下:
1、在数据表中增加一一个deleted字段

MyBatis Plus - 图26

2、实体类中增加属性

  1. /**
  2. * 逻辑删除
  3. */
  4. @TableLogic //逻辑删除
  5. private Integer deleted;

3、配置!

  1. //逻辑删除组件
  2. @Bean
  3. public ISqlInjector sqlInjector(){
  4. return new LogicSqlInjector();
  5. }
  1. # 配置逻辑删除
  2. mybatis-plus.global-config.db-config.logic-delete-value=1
  3. mybatis-plus.global-config.db-config.logic-not-delete-value=0

4、测试

MyBatis Plus - 图27

记录依旧在数据库,但是值确已经变化了MyBatis Plus - 图28

查询不到(查询的时候会自动过滤被逻辑删除的字段)

MyBatis Plus - 图29


性能分析插件

我们在平时的开发中,会遇到- -些慢sq|。测试! druid….

作用:性能分析拦截器,用于输出每条SQL语句及其执行时间

MP也提供性能分析插件,如果超过这个时间就停止运行!

1、导入插件

  1. /**
  2. *
  3. SQL执行效率插件
  4. */
  5. @Bean
  6. @Profile({"dev" , "test"})//设置dev test环境开启,保证我们的效率
  7. public PerformanceInterceptor performanceInterceptor() {
  8. PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
  9. // 在工作中, 不允许用户等待
  10. performanceInterceptor.setMaxTime(100); //ms 没置sql执行的最大时间,如果超过了则不执行
  11. performanceInterceptor.setFormat(true); //开启sql格式化
  12. return performanceInterceptor;
  13. }

记住,要在SpringBoot中配置环境为dev或者test环境!

  1. # 设置开发环境
  2. spring.profiles.active=dev

2、测试使用!

MyBatis Plus - 图30

使用性能分析插件,可以帮助我们提高效率!

条件构造器

记得查看输出的SQL进行分析

测试一:

  1. @Test
  2. void contextLoads() {
  3. // 查询name不为空的用户,并且邮箱不为空,年龄大于等于12岁
  4. QueryWrapper<User> wrapper = new QueryWrapper<>();
  5. wrapper
  6. .isNotNull("name")
  7. .isNotNull("email")
  8. .ge("age",12);
  9. userMapper.selectList(wrapper).forEach(System.out::println); //与map对比
  10. }

测试二:

  1. @Test
  2. void test2(){
  3. //查询名字dafran
  4. QueryWrapper<User> wrapper = new QueryWrapper<>();
  5. wrapper.eq("name","dafran");
  6. User user = userMapper.selectOne(wrapper); //查询一个数据,出现多个结果使用List或者Map
  7. System.out.println(user);
  8. }

测试三:

  1. @Test
  2. void test3(){
  3. //查询年龄在20~30岁之间的用户
  4. QueryWrapper<User> wrapper = new QueryWrapper<>();
  5. wrapper.between("age",20,30); //区间
  6. Integer count = userMapper.selectCount(wrapper); //查询结果数
  7. System.out.println(count);
  8. }

测试四:

  1. @Test
  2. void test4(){
  3. //模糊查询
  4. QueryWrapper<User> wrapper = new QueryWrapper<>();
  5. wrapper
  6. .notLike("name","e")
  7. .like("email",'t');
  8. List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
  9. maps.forEach(System.out::println);
  10. }

测试五:

  1. @Test
  2. void test5(){
  3. QueryWrapper<User> wrapper = new QueryWrapper<>();
  4. //id在子查询中查出来
  5. wrapper.inSql("id","select id from user where id<3");
  6. List<Object> objects = userMapper.selectObjs(wrapper);
  7. objects.forEach(System.out::println);
  8. }

测试六:

  1. @Test
  2. void test6(){
  3. QueryWrapper<User> wrapper = new QueryWrapper<>();
  4. //通过id进行排序
  5. wrapper.orderByDesc("id");
  6. List<User> users = userMapper.selectList(wrapper);
  7. users.forEach(System.out::println);
  8. }

代码自动生成器

AutoGenerator是MyBatis-Plus的代码生成器,通过AutoGenerator可以快速生成Entity、Mapper、 Mapper XML、Service、
Controller等各个模块的代码, 极大的提升了开发效率。

  1. package cn.dafran;
  2. import com.baomidou.mybatisplus.annotation.DbType;
  3. import com.baomidou.mybatisplus.annotation.FieldFill;
  4. import com.baomidou.mybatisplus.annotation.IdType;
  5. import com.baomidou.mybatisplus.generator.AutoGenerator;
  6. import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
  7. import com.baomidou.mybatisplus.generator.config.GlobalConfig;
  8. import com.baomidou.mybatisplus.generator.config.PackageConfig;
  9. import com.baomidou.mybatisplus.generator.config.StrategyConfig;
  10. import com.baomidou.mybatisplus.generator.config.po.TableFill;
  11. import com.baomidou.mybatisplus.generator.config.rules.DateType;
  12. import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
  13. import javax.lang.model.type.ArrayType;
  14. import java.util.ArrayList;
  15. /**
  16. * @author Administrator
  17. * @Classname DafranCode
  18. * @Description TODO
  19. * @Date 2020-10-28 17:54
  20. * @Version V1.0
  21. */
  22. //代码自动生成器
  23. public class DafranCode {
  24. public static void main(String[] args) {
  25. //需要构建一个代码自动生成器对象
  26. AutoGenerator mpg = new AutoGenerator();
  27. //配置策略
  28. //1、全局配置
  29. GlobalConfig gc= new GlobalConfig();
  30. String projectPath = System.getProperty("user.dir"); //获取当前系统路径
  31. gc.setOutputDir(projectPath+"/src/main/java"); //自动输出目录
  32. gc.setAuthor("6b92d6"); //作者
  33. gc.setOpen(false); //是否打开资源管理器
  34. gc.setFileOverride(false); //是否覆盖原先生成的
  35. gc.setServiceName("%sService"); //去Service的I前缀
  36. gc.setIdType(IdType.ID_WORKER); //生成策略、默认初始算法
  37. gc.setDateType(DateType.ONLY_DATE); //日期类型
  38. gc.setSwagger2(true); //是否配置Swagger文档
  39. mpg.setGlobalConfig(gc);
  40. //2、设置数据源
  41. DataSourceConfig dsc = new DataSourceConfig();
  42. dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8");
  43. dsc.setDriverName("com.mysql.cj.jdbc.Driver");
  44. dsc.setUsername("root");
  45. dsc.setPassword("123456");
  46. dsc.setDbType(DbType.MYSQL);
  47. mpg.setDataSource(dsc);
  48. //3、包的配置
  49. PackageConfig pc = new PackageConfig();
  50. pc.setModuleName("blog");
  51. pc.setParent("cn.dafran");
  52. pc.setEntity("entity");
  53. pc.setMapper("mapper");
  54. pc.setController("controller");
  55. mpg.setPackageInfo(pc);
  56. //4.策略配置
  57. StrategyConfig strategy = new StrategyConfig();
  58. strategy.setInclude("user"); // 设置要映射的表名 可以同时多个表
  59. strategy.setNaming(NamingStrategy.underline_to_camel);
  60. strategy.setColumnNaming(NamingStrategy.underline_to_camel);
  61. strategy.setEntityLombokModel(true); // 自动生成Lombok;
  62. strategy.setLogicDeleteFieldName("deleted"); // 逻辑删除
  63. //自动填充配置
  64. TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
  65. TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
  66. ArrayList<TableFill> tableFills = new ArrayList<>();
  67. tableFills.add(gmtCreate);
  68. tableFills.add(gmtModified);
  69. strategy.setTableFillList(tableFills);
  70. //乐观锁
  71. strategy.setVersionFieldName("version");
  72. strategy.setRestControllerStyle(true); //启动驼峰命名
  73. strategy.setControllerMappingHyphenStyle(true);
  74. // Localhost:8080/hello_id_2 、controller字段下划线命名
  75. mpg.setStrategy(strategy);
  76. mpg.execute(); //执行代码构造器
  77. }
  78. }