Mybatis-plus进阶版使用
创始人
2024-05-30 12:35:11
0

一、ActiveRecord:

Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。ActiveRecord 一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 作为准静态语言,对于 ActiveRecord 往往只能感叹其优雅,所以 MP 也在 AR 道路上进行了一定的探索,仅仅需要让实体类继承 Model 类且实现主键指定方法,即可开启 AR 之旅。接下来看具体代码:

1、entity:

@Data
public class User extends Model {private Integer id;private String name;private Integer age;private Integer gender;//重写这个方法,return当前类的主键@Overrideprotected Serializable pkVal() {return id;}
}

注:实体类继承Model类,重写pkVal方法。

2、mapper:

public interface UserDao extends BaseMapper {
}

注:虽然AR模式用不到该接口,但是一定要定义,否则使用AR时会报空指针异常。

3、使用AR:

(1)、AR插入操作:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring/spring-dao.xml"})
public class TestAR {@Testpublic void testArInsert(){User user = new User();user.setName("林青霞");user.setAge(22);user.setGender(1);boolean result = user.insert();System.out.println(result);}
}

注:可以看到我们并不需要注入mapper接口,不过正如刚才所说,不使用但还是要定义,否则会报错。AR操作是通过对象本身调用相关方法,比如要insert一个user,那就用这个user调用insert方法即可。返回值为布尔类型,由上图可看到返回了true,是操作成功的。

(2)、AR更新操作:

    @Testpublic void testArUpdate(){User user = new User();user.setId(1);user.setName("刘亦菲");boolean result = user.updateById();System.out.println(result);}

注:user调用updateById方法,将id为1的用户进行更新。

(3)、AR查询操作:

    @Testpublic void testArSelect(){User user = new User();//1、根据id查询//user = user.selectById(1);//或者这样用//user.setId(1);//user = user.selectById();//2、查询所有//List users = user.selectAll();//3、根据条件查询//List users = user.selectList(new EntityWrapper().like("name","刘"));//4、查询符合条件的总数int result = user.selectCount(new EntityWrapper().eq("gender",1));System.out.println(result);}

注:上面的代码涉及到了四个不同的查询操作,其实用法与MP的BaseMapper提供的方法的用法差不多,只不过这里是实体对象调用。

(4)、AR删除操作:

@Testpublic void testArDelete(){User user = new User();//删除数据库中不存在的数据也是返回true//1、根据id删除数据//boolean result = user.deleteById(1);//或者这样写//user.setId(1);//boolean result = user.deleteById();//2、根据条件删除boolean result = user.delete(new EntityWrapper().like("name","玲"));System.out.println(result);}

注:这里介绍了两个删除方法,代码中已有注释说明。需要注意的是,删除数据库中不存在的数据,结果也是true。

(5)、AR分页操作:

@Testpublic void testArPage(){User user = new User();Page page =user.selectPage(new Page<>(1,4),new EntityWrapper().like("name","刘"));List users = page.getRecords();System.out.println(users);}

注:这个分页方法和BaseMapper提供的分页一样都是内存分页,并非物理分页,因为sql语句中没用limit,和BaseMapper的selectPage方法一样,配置了分页插件后就可以实现真正的物理分页。AR的分页方法与BaseMapper提供的分页方法不同的是,BaseMapper的selectPage方法返回值是查询到的记录的list集合,而AR的selectPage方法返回的是page对象,该page对象封装了查询到的信息,可以通过getRecords方法获取信息。

二、插件的配置:

MP提供了很多好用的插件,而且配置简单,使用方便。接下来一起看看MP的插件如何使用。

1、分页插件:
之前就有说到,BaseMapper的selectPage方法和AR提供的selectPage方法都不是物理分页,需要配置分页插件后才是物理分页,那么现在就来看看如何配置这个插件。


注:在sqlSessionFactory这个bean中,通过配置插件,接下来的所有插件都配置在这个list中。

@Testpublic void testPage() {//配置了分页插件后,还是和以前一样的使用selectpage方法,//但是现在就是真正的物理分页了,sql语句中有limit了Page page = new Page<>(1, 2);List employeeList =emplopyeeDao.selectPage(page, null);System.out.println(employeeList);System.out.println("================= 相关的分页信息 ==================");System.out.println("总条数:" + page.getTotal());System.out.println("当前页码:" + page.getCurrent());System.out.println("总页数:" + page.getPages());System.out.println("每页显示条数:" + page.getSize());System.out.println("是否有上一页:" + page.hasPrevious());System.out.println("是否有下一页:" + page.hasNext());//还可以将查询到的结果set进page对象中page.setRecords(employeeList);}

由图可知,sql语句中已经有了limit,是物理分页了。

也可以通过page调用相关方法获取到相关的分页信息,而且还可以把查询到的结果set回page对象中,方便前端使用。

2、性能分析插件:
在plugin的list中添加如下bean即可开启性能分析插件:

 

注:这个性能分析插件配置了两个属性,第一个是格式化sql语句,设置为true后,sql语句格式就像上面的截图中的一样;第二个属性是sql语句执行的最大时间,超过value值就会报错,这里表示超过1000毫秒就会停止执行sql语句。

3、执行分析插件:




注:这个插件配置了一个属性,stopProceed设置为true后,如果执行的是删除表中全部内容,那就会抛出异常,终止该操作。该插件主要是防止手抖误删数据。

@Test
public void testSqlExplain(){//条件为null,就是删除全表,执行分析插件会终止该操作emplopyeeDao.delete(null);
}

运行该junit测试,可以看到报如下错误,说明该插件生效了。

三、MP的逆向工程:

MyBatis 的代码生成器基于xml文件进行生成,可生成: 实体类、Mapper 接口、Mapper 映射文件。
MP 的代码生成器基于Java代码进行生成,可生成: 实体类(可以选择是否支持 AR)、Mapper 接口、Mapper 映射文件、 Service 层、Controller 层。
1、添加依赖:

        mysqlmysql-connector-java5.1.37com.baomidoumybatis-plus2.3org.apache.velocityvelocity-engine-core2.0

注:上面是必须的三个依赖,为了可以在控制台直观的看到生成情况,可以添加日志包(slf4j-api和slf4j-log4j2),为了让生成的代码不会报错,还可以根据情况添加spring相关的依赖、lombok依赖等。

2、生成器示例代码:

/*** @author: zhu* @date: 2018/8/20 11:17* mybatis-plus逆向工程示例代码*/
public class test {@Testpublic void testGenerator(){//1、全局配置GlobalConfig config = new GlobalConfig();config.setActiveRecord(true)//开启AR模式.setAuthor("zhu")//设置作者//生成路径(一般都是生成在此项目的src/main/java下面).setOutputDir("E:\\develop\\Java\\workspace\\ideaworkspace\\mpg\\src\\main\\java").setFileOverride(true)//第二次生成会把第一次生成的覆盖掉.setIdType(IdType.AUTO)//主键策略.setServiceName("%sService")//生成的service接口名字首字母是否为I,这样设置就没有I.setBaseResultMap(true)//生成resultMap.setBaseColumnList(true);//在xml中生成基础列//2、数据源配置DataSourceConfig dataSourceConfig = new DataSourceConfig();dataSourceConfig.setDbType(DbType.MYSQL)//数据库类型.setDriverName("com.mysql.jdbc.Driver").setUrl("jdbc:mysql:///数据库名").setUsername("数据库用户名").setPassword("数据库密码");//3、策略配置StrategyConfig strategyConfig = new StrategyConfig();strategyConfig.setCapitalMode(true)//开启全局大写命名.setDbColumnUnderline(true)//表名字段名使用下划线.setNaming(NamingStrategy.underline_to_camel)//下划线到驼峰的命名方式.setTablePrefix("tb_")//表名前缀.setEntityLombokModel(true)//使用lombok.setInclude("表1","表2");//逆向工程使用的表//4、包名策略配置PackageConfig packageConfig = new PackageConfig();packageConfig.setParent("com.zhu.mpg")//设置包名的parent.setMapper("mapper").setService("service").setController("controller").setEntity("entity").setXml("mapper");//设置xml文件的目录//5、整合配置AutoGenerator autoGenerator = new AutoGenerator();autoGenerator.setGlobalConfig(config).setDataSource(dataSourceConfig).setStrategy(strategyConfig).setPackageInfo(packageConfig);//6、执行autoGenerator.execute();}
}

注:以上便是示例代码,只要运行该junit测试,就会生成entity、mapper接口、mapper的xml文件、service、serviceImpl、controller代码。每一个设置代码中均有详细注释,此处不再赘述。

四、自定义全局操作:

(一)、AutoSqlInjector :

BaseMapper提供了17个常用方法,但是有些需求这些方法还是不能很好的实现,那么怎么办呢?大家肯定会想到是在xml文件中写sql语句解决。这样确实可以,因为MP是只做增强不做改变,我们完全可以按照mybatis的原来的方式来解决。不过MP也提供了另一种解决办法,那就是自定义全局操作。所谓自定义全局操作,也就是我们可以在mapper中自定义一些方法,然后通过某些操作,让自定义的这个方法也能像BaseMapper的内置方法,供全局调用。接下来就看看如何实现(以deleteAll方法为例)。
1、在mapper接口中定义方法:

public interface EmplopyeeDao extends BaseMapper {int deleteAll();
}

public interface UserDao extends BaseMapper {int deleteAll();
}

在这两个mapper接口中都定义了deleteAll方法。

2、编写自定义注入类:

public class MySqlInjector extends AutoSqlInjector {@Overridepublic void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class mapperClass, Class modelClass, TableInfo table) {/* 添加一个自定义方法 */deleteAllUser(mapperClass, modelClass, table);System.out.println(table.getTableName());}public void deleteAllUser(Class mapperClass, Class modelClass, TableInfo table) {/* 执行 SQL ,动态 SQL 参考类 SqlMethod */String sql = "delete from " + table.getTableName();/* mapper 接口方法名一致 */String method = "deleteAll";SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);this.addDeleteMappedStatement(mapperClass, method, sqlSource);}
}

注:该类继承AutoSqlInjector,重写inject方法。然后编写sql语句,指定mapper接口中的方法,最后调用addDeleteMappedStatement方法即可。

3、在spring配置文件中配置:




注:先把刚才自定义的类注册成bean,然后在全局策略配置的bean中引用自定义类的bean即可。

4、测试:

@Test
public void testMySqlInjector(){Integer result = userDao.deleteAll();System.out.println(result);
}@Test
public void testMySqlInjector2(){Integer result = emplopyeeDao.deleteAll();System.out.println(result);
}

注:经测试,当userDao调用deleteAll方法时,会删除tb_user表的所有数据,employeeDao调用deleteAll方法时,会删除tb_employee表的所有数据。说明deleteAll方法是有效的。不过在运行这两个测试时,由于是全表删除操作,所有要先把执行分析插件关了。

(二)、逻辑删除:

其实数据并不会轻易的删除掉,毕竟数据收集不易,所以就有了逻辑删除。逻辑删除: 并不会真正的从数据库中将数据删除掉,而是将当前被删除的这条数据中的一个逻辑删除字段置为删除状态,比如该数据有一个字段logic_flag,当其值为1表示未删除,值为-1表示删除,那么逻辑删除就是将1变成-1。
1、数据表:
在数据表中需要添加逻辑删除字段(logic_flag)。

2、实体类:

@Data
public class User{private Integer id;private String name;private Integer age;private Integer gender;@TableLogic //标记逻辑删除属性private Integer logicFlag;
}

注:数据库中逻辑删除字段是logic_flag,所以实体类中的logicFlag需要用@TableLogic注解标记。

3、mapper:

public interface UserDao extends BaseMapper {
}

4、配置逻辑删除:
需要在spring-dao.xml中做如下配置:
首先定义逻辑删除的bean:



再在全局配置的bean中注入逻辑删除以及逻辑删除值:


注:因为逻辑删除实际上也是一个sqlInjector,所以先要把刚才做自定义全局操作时注入的自定义全局操作注释掉,上面代码中已有详细注释说明。

6、测试:

@Testpublic void testLogicDelete(){Integer result = userDao.deleteById(1);System.out.println(result);//User user = userDao.selectById(1);//System.out.println(user);}

注:运行该测试,执行删除操作的时候,真正执行的sql语句是UPDATE tb_user SET logic_flag=-1 WHERE id=?,就是把逻辑删除字段的值设置为-1;当逻辑删除字段的值是-1时再执行查询操作,sql是SELECT ... FROM tb_user WHERE id=? AND logic_flag=1,所以查询结果是null。
 

五、公共字段自动填充:

我们知道,当我们进行插入或者更新操作时,没有设置值的属性,那么在数据表中要么是为null,要么是保留原来的值。有的时候我们我们没有赋值但是却不想让其为空,比如name属性,我们插入时会默认赋上“林志玲”,更新时会默认赋值上“朱茵”,那么就可以用公共字段自动填充。
1、使用@TableField注解标记填充字段

@TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充private String name;

2、编写公共字段填充处理器类:

public class MyMetaObjectHandler extends MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {Object fieldValue = getFieldValByName("name",metaObject); //获取需要填充的字段if(fieldValue == null){   //如果该字段没有设置值setFieldValByName("name","林志玲",metaObject); //那就将其设置为"林志玲"}}@Overridepublic void updateFill(MetaObject metaObject) {Object fieldValue = getFieldValByName("name",metaObject);//获取需要填充的字段if(fieldValue == null){ //如果该字段没有设置值setFieldValByName("name","朱茵",metaObject);  //那就将其设置为"朱茵"}}
}

注:该类继承了MetaObjectHandler类,重写了insertFill和updateFill方法,在这两个方法获取需要填充的字段以及默认填充的值。

3、在spring-dao.xml中配置:




注:和配置逻辑删除一样,都是先将自定义的类注册成bean,再在全局策略配置中引用这个bean即可。

4、测试:

@Test
public void testHandlerInsert() {User user = new User();user.setGender(1);user.setAge(22);user.setLogicFlag(1);userDao.insert(user);
}


注:可以看到,虽然我们并没有给name赋值,但是已经自动把“林志玲”传进去了。更新时也一样有效,此处就不将测试代码贴出来了。

好了 进阶版到这就结束了

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...