您好,登錄后才能下訂單哦!
這篇文章主要介紹“mybatis-plus的使用方法”,在日常操作中,相信很多人在mybatis-plus的使用方法問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”mybatis-plus的使用方法”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
關(guān)于mybatis-plus的簡(jiǎn)介以及基本使用,我在《mybatis-plus的使用 ------ 入門》一文中已做介紹,此處不再贅述。本文主要對(duì)mybatis-plus的AR模式、插件、逆向工程、自定義全局操作、公共字段自動(dòng)填充等知識(shí)點(diǎn)進(jìn)行講解。
Active Record(活動(dòng)記錄),是一種領(lǐng)域模型模式,特點(diǎn)是一個(gè)模型類對(duì)應(yīng)關(guān)系型數(shù)據(jù)庫中的一個(gè)表,而模型類的一個(gè)實(shí)例對(duì)應(yīng)表中的一行記錄。ActiveRecord 一直廣受動(dòng)態(tài)語言( PHP 、 Ruby 等)的喜愛,而 Java 作為準(zhǔn)靜態(tài)語言,對(duì)于 ActiveRecord 往往只能感嘆其優(yōu)雅,所以 MP 也在 AR 道路上進(jìn)行了一定的探索,僅僅需要讓實(shí)體類繼承 Model 類且實(shí)現(xiàn)主鍵指定方法,即可開啟 AR 之旅。接下來看具體代碼:
1、entity:
@Data public class User extends Model<User> { private Integer id; private String name; private Integer age; private Integer gender; //重寫這個(gè)方法,return當(dāng)前類的主鍵 @Override protected Serializable pkVal() { return id; } }
注:實(shí)體類繼承Model類,重寫pkVal方法。
2、mapper:
public interface UserDao extends BaseMapper<User> { }
注:雖然AR模式用不到該接口,但是一定要定義,否則使用AR時(shí)會(huì)報(bào)空指針異常。
3、使用AR:
(1)、AR插入操作:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"classpath:spring/spring-dao.xml"}) public class TestAR { @Test public void testArInsert(){ User user = new User(); user.setName("林青霞"); user.setAge(22); user.setGender(1); boolean result = user.insert(); System.out.println(result); } }
image.png
注:可以看到我們并不需要注入mapper接口,不過正如剛才所說,不使用但還是要定義,否則會(huì)報(bào)錯(cuò)。AR操作是通過對(duì)象本身調(diào)用相關(guān)方法,比如要insert一個(gè)user,那就用這個(gè)user調(diào)用insert方法即可。返回值為布爾類型,由上圖可看到返回了true,是操作成功的。
(2)、AR更新操作:
@Test public void testArUpdate(){ User user = new User(); user.setId(1); user.setName("劉亦菲"); boolean result = user.updateById(); System.out.println(result); }
注:user調(diào)用updateById方法,將id為1的用戶進(jìn)行更新。
(3)、AR查詢操作:
@Test public void testArSelect(){ User user = new User(); //1、根據(jù)id查詢 //user = user.selectById(1); //或者這樣用 //user.setId(1); //user = user.selectById(); //2、查詢所有 //List<User> users = user.selectAll(); //3、根據(jù)條件查詢 //List<User> users = user.selectList(new EntityWrapper<User>().like("name","劉")); //4、查詢符合條件的總數(shù) int result = user.selectCount(new EntityWrapper<User>().eq("gender",1)); System.out.println(result); }
注:上面的代碼涉及到了四個(gè)不同的查詢操作,其實(shí)用法與MP的BaseMapper提供的方法的用法差不多,只不過這里是實(shí)體對(duì)象調(diào)用。
(4)、AR刪除操作:
@Test public void testArDelete(){ User user = new User(); //刪除數(shù)據(jù)庫中不存在的數(shù)據(jù)也是返回true //1、根據(jù)id刪除數(shù)據(jù) //boolean result = user.deleteById(1); //或者這樣寫 //user.setId(1); //boolean result = user.deleteById(); //2、根據(jù)條件刪除 boolean result = user.delete(new EntityWrapper<User>().like("name","玲")); System.out.println(result); }
注:這里介紹了兩個(gè)刪除方法,代碼中已有注釋說明。需要注意的是,刪除數(shù)據(jù)庫中不存在的數(shù)據(jù),結(jié)果也是true。
(5)、AR分頁操作:
@Test public void testArPage(){ User user = new User(); Page<User> page = user.selectPage(new Page<>(1,4), new EntityWrapper<User>().like("name","劉")); List<User> users = page.getRecords(); System.out.println(users); }
注:這個(gè)分頁方法和BaseMapper提供的分頁一樣都是內(nèi)存分頁,并非物理分頁,因?yàn)閟ql語句中沒用limit,和BaseMapper的selectPage方法一樣,配置了分頁插件后就可以實(shí)現(xiàn)真正的物理分頁。AR的分頁方法與BaseMapper提供的分頁方法不同的是,BaseMapper的selectPage方法返回值是查詢到的記錄的list集合,而AR的selectPage方法返回的是page對(duì)象,該page對(duì)象封裝了查詢到的信息,可以通過getRecords方法獲取信息。
MP提供了很多好用的插件,而且配置簡(jiǎn)單,使用方便。接下來一起看看MP的插件如何使用。
1、分頁插件:
之前就有說到,BaseMapper的selectPage方法和AR提供的selectPage方法都不是物理分頁,需要配置分頁插件后才是物理分頁,那么現(xiàn)在就來看看如何配置這個(gè)插件。
<!-- 3、配置mybatisplus的sqlSessionFactory --> <bean id="sqlSessionFactory">
注:在sqlSessionFactory這個(gè)bean中,通過<property name="plugins">
配置插件,接下來的所有插件都配置在這個(gè)list中。
@Test public void testPage() { //配置了分頁插件后,還是和以前一樣的使用selectpage方法, //但是現(xiàn)在就是真正的物理分頁了,sql語句中有l(wèi)imit了 Page<Employee> page = new Page<>(1, 2); List<Employee> employeeList = emplopyeeDao.selectPage(page, null); System.out.println(employeeList); System.out.println("================= 相關(guān)的分頁信息 =================="); System.out.println("總條數(shù):" + page.getTotal()); System.out.println("當(dāng)前頁碼:" + page.getCurrent()); System.out.println("總頁數(shù):" + page.getPages()); System.out.println("每頁顯示條數(shù):" + page.getSize()); System.out.println("是否有上一頁:" + page.hasPrevious()); System.out.println("是否有下一頁:" + page.hasNext()); //還可以將查詢到的結(jié)果set進(jìn)page對(duì)象中 page.setRecords(employeeList); }
image.png
由圖可知,sql語句中已經(jīng)有了limit,是物理分頁了。
image.png
也可以通過page調(diào)用相關(guān)方法獲取到相關(guān)的分頁信息,而且還可以把查詢到的結(jié)果set回page對(duì)象中,方便前端使用。
2、性能分析插件:
在plugin的list中添加如下bean即可開啟性能分析插件:
<!-- 輸出每條SQL語句及其執(zhí)行時(shí)間,生產(chǎn)環(huán)境不建議使用該插件 --> <bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor"> <property name="format">
注:這個(gè)性能分析插件配置了兩個(gè)屬性,第一個(gè)是格式化sql語句,設(shè)置為true后,sql語句格式就像上面的截圖中的一樣;第二個(gè)屬性是sql語句執(zhí)行的最大時(shí)間,超過value值就會(huì)報(bào)錯(cuò),這里表示超過1000毫秒就會(huì)停止執(zhí)行sql語句。
3、執(zhí)行分析插件:
<!-- 如果是對(duì)全表的刪除或更新操作,就會(huì)終止該操作 --> <bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor"> <property name="stopProceed" value="true"/> </bean>
注:這個(gè)插件配置了一個(gè)屬性,stopProceed設(shè)置為true后,如果執(zhí)行的是刪除表中全部?jī)?nèi)容,那就會(huì)拋出異常,終止該操作。該插件主要是防止手抖誤刪數(shù)據(jù)。
@Test public void testSqlExplain(){ //條件為null,就是刪除全表,執(zhí)行分析插件會(huì)終止該操作 emplopyeeDao.delete(null); }
運(yùn)行該junit測(cè)試,可以看到報(bào)如下錯(cuò)誤,說明該插件生效了。
image.png
MyBatis 的代碼生成器基于xml文件進(jìn)行生成,可生成: 實(shí)體類、Mapper 接口、Mapper 映射文件。
MP 的代碼生成器基于Java代碼進(jìn)行生成,可生成: 實(shí)體類(可以選擇是否支持 AR)、Mapper 接口、Mapper 映射文件、 Service 層、Controller 層。
1、添加依賴:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.37</version> </dependency> <!-- mp 依賴 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>2.3</version> </dependency> <!-- mybatisplus逆向工程需要模板引擎,用freemaker也行 --> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.0</version> </dependency>
注:上面是必須的三個(gè)依賴,為了可以在控制臺(tái)直觀的看到生成情況,可以添加日志包(slf4j-api和slf4j-log4j2),為了讓生成的代碼不會(huì)報(bào)錯(cuò),還可以根據(jù)情況添加spring相關(guān)的依賴、lombok依賴等。
2、生成器示例代碼:
/** * @author: zhu * @date: 2018/8/20 11:17 * mybatis-plus逆向工程示例代碼 */ public class test { @Test public void testGenerator(){ //1、全局配置 GlobalConfig config = new GlobalConfig(); config.setActiveRecord(true)//開啟AR模式 .setAuthor("zhu")//設(shè)置作者 //生成路徑(一般都是生成在此項(xiàng)目的src/main/java下面) .setOutputDir("E:\\develop\\Java\\workspace\\ideaworkspace\\mpg\\src\\main\\java") .setFileOverride(true)//第二次生成會(huì)把第一次生成的覆蓋掉 .setIdType(IdType.AUTO)//主鍵策略 .setServiceName("%sService")//生成的service接口名字首字母是否為I,這樣設(shè)置就沒有I .setBaseResultMap(true)//生成resultMap .setBaseColumnList(true);//在xml中生成基礎(chǔ)列 //2、數(shù)據(jù)源配置 DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MYSQL)//數(shù)據(jù)庫類型 .setDriverName("com.mysql.jdbc.Driver") .setUrl("jdbc:mysql:///數(shù)據(jù)庫名") .setUsername("數(shù)據(jù)庫用戶名") .setPassword("數(shù)據(jù)庫密碼"); //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")//設(shè)置包名的parent .setMapper("mapper") .setService("service") .setController("controller") .setEntity("entity") .setXml("mapper");//設(shè)置xml文件的目錄 //5、整合配置 AutoGenerator autoGenerator = new AutoGenerator(); autoGenerator.setGlobalConfig(config) .setDataSource(dataSourceConfig) .setStrategy(strategyConfig) .setPackageInfo(packageConfig); //6、執(zhí)行 autoGenerator.execute(); } }
注:以上便是示例代碼,只要運(yùn)行該junit測(cè)試,就會(huì)生成entity、mapper接口、mapper的xml文件、service、serviceImpl、controller代碼。每一個(gè)設(shè)置代碼中均有詳細(xì)注釋,此處不再贅述。
(一)、AutoSqlInjector :
BaseMapper提供了17個(gè)常用方法,但是有些需求這些方法還是不能很好的實(shí)現(xiàn),那么怎么辦呢?大家肯定會(huì)想到是在xml文件中寫sql語句解決。這樣確實(shí)可以,因?yàn)镸P是只做增強(qiáng)不做改變,我們完全可以按照mybatis的原來的方式來解決。不過MP也提供了另一種解決辦法,那就是自定義全局操作。所謂自定義全局操作,也就是我們可以在mapper中自定義一些方法,然后通過某些操作,讓自定義的這個(gè)方法也能像BaseMapper的內(nèi)置方法,供全局調(diào)用。接下來就看看如何實(shí)現(xiàn)(以deleteAll方法為例)。
1、在mapper接口中定義方法:
public interface EmplopyeeDao extends BaseMapper<Employee> { int deleteAll(); }
public interface UserDao extends BaseMapper<User> { int deleteAll(); }
在這兩個(gè)mapper接口中都定義了deleteAll方法。
2、編寫自定義注入類:
public class MySqlInjector extends AutoSqlInjector { @Override public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) { /* 添加一個(gè)自定義方法 */ deleteAllUser(mapperClass, modelClass, table); System.out.println(table.getTableName()); } public void deleteAllUser(Class<?> mapperClass, Class<?> modelClass, TableInfo table) { /* 執(zhí)行 SQL ,動(dòng)態(tài) SQL 參考類 SqlMethod */ String sql = "delete from ">
注:該類繼承AutoSqlInjector,重寫inject方法。然后編寫sql語句,指定mapper接口中的方法,最后調(diào)用addDeleteMappedStatement方法即可。
3、在spring配置文件中配置:
<!-- 定義自定義注入器 --> <bean class="com.zhu.mybatisplus.injector.MySqlInjector" id="mySqlInjector"/>
<!-- 5、mybatisplus的全局策略配置 --> <bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration"> <property name="idType" value="0"/> <property name="tablePrefix" value="tb_"/> <!-- 注入自定義全局操作 --> <property name="sqlInjector" ref="mySqlInjector"/> </bean>
注:先把剛才自定義的類注冊(cè)成bean,然后在全局策略配置的bean中引用自定義類的bean即可。
4、測(cè)試:
@Test public void testMySqlInjector(){ Integer result = userDao.deleteAll(); System.out.println(result); } @Test public void testMySqlInjector2(){ Integer result = emplopyeeDao.deleteAll(); System.out.println(result); }
注:經(jīng)測(cè)試,當(dāng)userDao調(diào)用deleteAll方法時(shí),會(huì)刪除tb_user表的所有數(shù)據(jù),employeeDao調(diào)用deleteAll方法時(shí),會(huì)刪除tb_employee表的所有數(shù)據(jù)。說明deleteAll方法是有效的。不過在運(yùn)行這兩個(gè)測(cè)試時(shí),由于是全表刪除操作,所有要先把執(zhí)行分析插件關(guān)了。
(二)、邏輯刪除:
其實(shí)數(shù)據(jù)并不會(huì)輕易的刪除掉,畢竟數(shù)據(jù)收集不易,所以就有了邏輯刪除。邏輯刪除: 并不會(huì)真正的從數(shù)據(jù)庫中將數(shù)據(jù)刪除掉,而是將當(dāng)前被刪除的這條數(shù)據(jù)中的一個(gè)邏輯刪除字段置為刪除狀態(tài),比如該數(shù)據(jù)有一個(gè)字段logic_flag,當(dāng)其值為1表示未刪除,值為-1表示刪除,那么邏輯刪除就是將1變成-1。
1、數(shù)據(jù)表:
在數(shù)據(jù)表中需要添加邏輯刪除字段(logic_flag)。
image.png
2、實(shí)體類:
@Data public class User{ private Integer id; private String name; private Integer age; private Integer gender; @TableLogic //標(biāo)記邏輯刪除屬性 private Integer logicFlag; }
注:數(shù)據(jù)庫中邏輯刪除字段是logic_flag,所以實(shí)體類中的logicFlag需要用@TableLogic注解標(biāo)記。
3、mapper:
public interface UserDao extends BaseMapper<User> { }
4、配置邏輯刪除:
需要在spring-dao.xml中做如下配置:
首先定義邏輯刪除的bean:
<!-- 邏輯刪除 --> <bean class="com.baomidou.mybatisplus.mapper.LogicSqlInjector">
再在全局配置的bean中注入邏輯刪除以及邏輯刪除值:
<!-- 5、mybatisplus的全局策略配置 --> <bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration"> <!-- 此處省略其他全局配置 --> <!-- 注入自定義全局操作,做邏輯刪除時(shí)需要先注釋掉 --> <!--<property name="sqlInjector" ref="mySqlInjector"/>--> <!-- 注入邏輯刪除,先要把自定義的注釋掉 --> <property name="sqlInjector" ref="logicSqlInjector"/> <!-- 注入邏輯刪除值 --> <property name="logicDeleteValue" value="-1"/><!-- -1是刪除狀態(tài) --> <property name="logicNotDeleteValue" value="1"/><!-- 1是未刪除狀態(tài) --> </bean>
注:因?yàn)檫壿媱h除實(shí)際上也是一個(gè)sqlInjector,所以先要把剛才做自定義全局操作時(shí)注入的自定義全局操作注釋掉,上面代碼中已有詳細(xì)注釋說明。
6、測(cè)試:
@Test public void testLogicDelete(){ Integer result = userDao.deleteById(1); System.out.println(result); //User user = userDao.selectById(1); //System.out.println(user); }
注:運(yùn)行該測(cè)試,執(zhí)行刪除操作的時(shí)候,真正執(zhí)行的sql語句是UPDATE tb_user SET logic_flag=-1 WHERE id=?
,就是把邏輯刪除字段的值設(shè)置為-1;當(dāng)邏輯刪除字段的值是-1時(shí)再執(zhí)行查詢操作,sql是SELECT ... FROM tb_user WHERE id=? AND logic_flag=1
,所以查詢結(jié)果是null。
我們知道,當(dāng)我們進(jìn)行插入或者更新操作時(shí),沒有設(shè)置值的屬性,那么在數(shù)據(jù)表中要么是為null,要么是保留原來的值。有的時(shí)候我們我們沒有賦值但是卻不想讓其為空,比如name屬性,我們插入時(shí)會(huì)默認(rèn)賦上“林志玲”,更新時(shí)會(huì)默認(rèn)賦值上“朱茵”,那么就可以用公共字段自動(dòng)填充。
1、使用@TableField注解標(biāo)記填充字段
@TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新時(shí)填充 private String name;
2、編寫公共字段填充處理器類:
public class MyMetaObjectHandler extends MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { Object fieldValue = getFieldValByName("name",metaObject); //獲取需要填充的字段 if(fieldValue == null){ //如果該字段沒有設(shè)置值 setFieldValByName("name","林志玲",metaObject); //那就將其設(shè)置為"林志玲" } } @Override public void updateFill(MetaObject metaObject) { Object fieldValue = getFieldValByName("name",metaObject);//獲取需要填充的字段 if(fieldValue == null){ //如果該字段沒有設(shè)置值 setFieldValByName("name","朱茵",metaObject); //那就將其設(shè)置為"朱茵" } } }
注:該類繼承了MetaObjectHandler類,重寫了insertFill和updateFill方法,在這兩個(gè)方法獲取需要填充的字段以及默認(rèn)填充的值。
3、在spring-dao.xml中配置:
<!-- 公共字段填充處理器 --> <bean class="com.zhu.mybatisplus.handler.MyMetaObjectHandler" id="myMetaObjectHandler"/>
<!-- 5、mybatisplus的全局策略配置 --> <bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration"> <!-- 此處省略其他配置 --> <!-- 注入公共字段填充處理器 --> <property name="metaObjectHandler" ref="myMetaObjectHandler"/> </bean>
注:和配置邏輯刪除一樣,都是先將自定義的類注冊(cè)成bean,再在全局策略配置中引用這個(gè)bean即可。
4、測(cè)試:
@Test public void testHandlerInsert() { User user = new User(); user.setGender(1); user.setAge(22); user.setLogicFlag(1); userDao.insert(user); }
image.png
注:可以看到,雖然我們并沒有給name賦值,但是已經(jīng)自動(dòng)把“林志玲”傳進(jìn)去了。更新時(shí)也一樣有效,此處就不將測(cè)試代碼貼出來了。
到此,關(guān)于“mybatis-plus的使用方法”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。