<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Springboot怎么整合Mybatis-plus???

          共 14845字,需瀏覽 30分鐘

           ·

          2020-11-02 05:06

          點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達(dá)

          ? 作者?|??碼農(nóng)BookSea

          來源 |? urlify.cn/A3AVZb

          66套java從入門到精通實戰(zhàn)課程分享

          一、添加依賴pom.xml


          ????mysql
          ????mysql-connector-java


          ????com.alibaba
          ????druid-spring-boot-starter
          ????1.1.20


          ????com.baomidou
          ????mybatis-plus-boot-starter
          ????3.3.2



          ????com.baomidou
          ????mybatis-plus-generator
          ????3.3.2



          ????org.freemarker
          ????freemarker


          二、application.yml添加配置

          spring:
          ??#數(shù)據(jù)庫配置
          ??datasource:
          ????url:?jdbc:mysql://127.0.0.1:3306/user_role?useUnicode=true&useSSL=false&characterEncoding=utf-8
          ????username:?root
          ????password:?root
          ????#?使用druid數(shù)據(jù)源
          ????type:?com.alibaba.druid.pool.DruidDataSource
          ????driver-class-name:?com.mysql.jdbc.Driver


          三、application配置@MapperScan

          @SpringBootApplication
          @MapperScan("cn.com.vicente.demo.mapper")
          public?class?BdDemoApplication?{

          ????public?static?void?main(String[]?args)?{
          ????????SpringApplication.run(BdDemoApplication.class,?args);
          ????}

          }


          到這里就引入了MyBatis-Plus了。

          四、代碼生成器
          很多時候,都不想寫entity,mapper等文件,這個時候就可以使用代碼生成器來自動生成對應(yīng)的文件了。
          需要修改幾個地方:

          1、數(shù)據(jù)庫連接
          2、文件需要放置的文件夾地址。

          具體代碼:

          package?cn.com.bluemoon.demo.generator;

          import?com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
          import?com.baomidou.mybatisplus.core.toolkit.StringPool;
          import?com.baomidou.mybatisplus.core.toolkit.StringUtils;
          import?com.baomidou.mybatisplus.generator.AutoGenerator;
          import?com.baomidou.mybatisplus.generator.InjectionConfig;
          import?com.baomidou.mybatisplus.generator.config.*;
          import?com.baomidou.mybatisplus.generator.config.po.TableInfo;
          import?com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
          import?com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

          import?java.util.ArrayList;
          import?java.util.List;
          import?java.util.Scanner;

          // 演示例子,執(zhí)行 main 方法控制臺輸入模塊表名回車自動生成對應(yīng)項目目錄中

          public?class?CodeGenerator?{

          ????/**
          ?????*?


          ?????*?讀取控制臺內(nèi)容
          ?????*?


          ?????*/
          ????public?static?String?scanner(String?tip)?{
          ????????Scanner?scanner?=?new?Scanner(System.in);
          ????????StringBuilder?help?=?new?StringBuilder();
          ????????help.append("請輸入"?+?tip?+?":");
          ????????System.out.println(help.toString());
          ????????if?(scanner.hasNext())?{
          ????????????String?ipt?=?scanner.next();
          ????????????if?(StringUtils.isNotEmpty(ipt))?{
          ????????????????return?ipt;
          ????????????}
          ????????}
          ????????throw?new?MybatisPlusException("請輸入正確的"?+?tip?+?"!");
          ????}

          ????public?static?void?main(String[]?args)?{
          ????????//?代碼生成器
          ????????AutoGenerator?mpg?=?new?AutoGenerator();

          ????????//?全局配置
          ????????GlobalConfig?gc?=?new?GlobalConfig();
          ????????String?projectPath?=?System.getProperty("user.dir");
          ????????gc.setOutputDir(projectPath?+?"/src/main/java");
          ????????gc.setAuthor("vicente");
          ????????gc.setOpen(false);
          ????????//?service?命名方式
          ????????gc.setServiceName("%sService");
          ????????//?service?impl?命名方式
          ????????gc.setServiceImplName("%sServiceImpl");
          ????????//?自定義文件命名,注意?%s?會自動填充表實體屬性!
          ????????gc.setMapperName("%sMapper");
          ????????gc.setXmlName("%sMapper");
          ????????gc.setFileOverride(true);
          ????????gc.setActiveRecord(true);
          ????????//?XML?二級緩存
          ????????gc.setEnableCache(false);
          ????????//?XML?ResultMap
          ????????gc.setBaseResultMap(true);
          ????????//?XML?columList
          ????????gc.setBaseColumnList(false);
          ????????//?gc.setSwagger2(true);?實體屬性?Swagger2?注解
          ????????mpg.setGlobalConfig(gc);

          ????????//?數(shù)據(jù)源配置
          ????????DataSourceConfig?dsc?=?new?DataSourceConfig();
          ????????dsc.setUrl("jdbc:mysql://127.0.0.1:3306/user_role?useUnicode=true&useSSL=false&characterEncoding=utf-8");
          ????????//?dsc.setSchemaName("public");
          ????????dsc.setDriverName("com.mysql.jdbc.Driver");
          ????????dsc.setUsername("root");
          ????????dsc.setPassword("root");
          ????????mpg.setDataSource(dsc);

          ????????//?包配置
          ????????PackageConfig?pc?=?new?PackageConfig();
          ????????//pc.setModuleName(scanner("模塊名"));
          ????????pc.setParent("cn.com.vicente.demo");
          ????????pc.setEntity("entity");
          ????????pc.setService("service");
          ????????pc.setServiceImpl("service.impl");
          ????????mpg.setPackageInfo(pc);

          ????????//?自定義配置
          ????????InjectionConfig?cfg?=?new?InjectionConfig()?{
          ????????????@Override
          ????????????public?void?initMap()?{
          ????????????????//?to?do?nothing
          ????????????}
          ????????};

          ????????//?如果模板引擎是?freemarker
          ????????String?templatePath?=?"/templates/mapper.xml.ftl";
          ????????//?如果模板引擎是?velocity
          ????????//?String?templatePath?=?"/templates/mapper.xml.vm";

          ????????//?自定義輸出配置
          ????????List?focList?=?new?ArrayList<>();
          ????????//?自定義配置會被優(yōu)先輸出
          ????????focList.add(new?FileOutConfig(templatePath)?{
          ????????????@Override
          ????????????public?String?outputFile(TableInfo?tableInfo)?{
          ????????????????//?自定義輸出文件名?,?如果你?Entity?設(shè)置了前后綴、此處注意?xml?的名稱會跟著發(fā)生變化!!
          ????????????????String?moduleName?=?pc.getModuleName()==null?"":pc.getModuleName();
          ????????????????return?projectPath?+?"/src/main/resources/mapper/"?+?moduleName
          ????????????????????????+?"/"?+?tableInfo.getEntityName()?+?"Mapper"?+?StringPool.DOT_XML;
          ????????????}
          ????????});
          ????????/*
          ????????cfg.setFileCreate(new?IFileCreate()?{
          ????????????@Override
          ????????????public?boolean?isCreate(ConfigBuilder?configBuilder,?FileType?fileType,?String?filePath)?{
          ????????????????//?判斷自定義文件夾是否需要創(chuàng)建
          ????????????????checkDir("調(diào)用默認(rèn)方法創(chuàng)建的目錄");
          ????????????????return?false;
          ????????????}
          ????????});
          ????????*/
          ????????cfg.setFileOutConfigList(focList);
          ????????mpg.setCfg(cfg);

          ????????//?配置模板
          ????????TemplateConfig?templateConfig?=?new?TemplateConfig();

          ????????//?配置自定義輸出模板
          ????????//指定自定義模板路徑,注意不要帶上.ftl/.vm,?會根據(jù)使用的模板引擎自動識別
          ????????//?templateConfig.setEntity("templates/entity2.java");
          ????????//?templateConfig.setService();
          ????????//?templateConfig.setController();

          ????????templateConfig.setXml(null);
          ????????mpg.setTemplate(templateConfig);

          ????????//?策略配置
          ????????StrategyConfig?strategy?=?new?StrategyConfig();
          ????????strategy.setNaming(NamingStrategy.underline_to_camel);
          ????????strategy.setColumnNaming(NamingStrategy.underline_to_camel);
          ????????//strategy.setSuperEntityClass("cn.com.bluemoon.demo.entity");
          ????????strategy.setEntityLombokModel(true);
          ????????strategy.setRestControllerStyle(true);
          ????????//?公共父類
          ????????//strategy.setSuperControllerClass("cn.com.bluemoon.demo.controller");
          ????????//?寫于父類中的公共字段
          ????????//strategy.setSuperEntityColumns("id");
          ????????strategy.setInclude(scanner("表名,多個英文逗號分割").split(","));
          ????????strategy.setControllerMappingHyphenStyle(true);
          ????????strategy.setTablePrefix(pc.getModuleName()?+?"_");
          ????????mpg.setStrategy(strategy);
          ????????mpg.setTemplateEngine(new?FreemarkerTemplateEngine());
          ????????mpg.execute();
          ????}

          }


          五、添加測試
          這里主要是Mybatis-Plus的CURD等方法。

          @RunWith(SpringRunner.class)
          @SpringBootTest
          public?class?SampleTest?{

          ????private?static?Logger?log?=?LoggerFactory.getLogger(SampleTest.class);

          ????@Autowired
          ????private?MpUserService?mpUserService;

          ????@Test
          ????public?void?test1()?{
          ????????//?插入新記錄
          ????????MpUser?mpUser?=?new?MpUser();
          ????????//mpUser.setId(1L);
          ????????mpUser.setEmail("[email protected]");
          ????????mpUser.setAge(22);
          ????????mpUser.setName("David?Hong");
          ????????mpUserService.save(mpUser);
          ????????//?或者
          ????????mpUser.insertOrUpdate();
          ????????//?更新完成后,mpUser對象的id會被補全
          ????????log.info("mpUser={}",?mpUser.toString());

          ????}

          ????@Test
          ????public?void?test2()?{
          ????????//?通過主鍵id查詢
          ????????MpUser?mpUser?=?mpUserService.getById(1);
          ????????log.info("mpUser={}",?mpUser.toString());
          ????}

          ????@Test
          ????public?void?test3()?{
          ????????//?條件查詢,下面相當(dāng)于xml中的?select?*?from?mp_user?where?name?=?'Tom'?and?age?=?'28'?limit?1
          ????????MpUser?mpUser?=?mpUserService.getOne(new?QueryWrapper().eq("name",?"Tom").eq("age",?"28").last("limit?1"));
          ????????log.info("mpUser={}",?mpUser.toString());
          ????????//?批量查詢
          ????????List?mpUserList?=?mpUserService.list();
          ????????System.out.println("------------------------------all");
          ????????mpUserList.forEach(System.out::println);
          ????????//?分頁查詢?
          ????????int?pageNum?=?1;
          ????????int?pageSize?=?10;
          ????????IPage?mpUserIPage?=?mpUserService.page(new?Page<>(pageNum,?pageSize),?new?QueryWrapper().gt("age",?"20"));
          ????????//?IPage?to?List
          ????????List?mpUserList1?=?mpUserIPage.getRecords();
          ????????System.out.println("------------------------------page");
          ????????mpUserList1.forEach(System.out::println);
          ????????//?總頁數(shù)
          ????????long?allPageNum?=?mpUserIPage.getPages();
          ????????System.out.println("------------------------------allPageNum");
          ????????System.out.println(allPageNum);
          ????}

          ?????@Test
          ????public?void?test4()?{
          ????????MpUser?mpUser?=?mpUserService.getById(2);
          ????????//?修改更新
          ????????mpUser.setName("廣東廣州");
          ????????//mpUserService.updateById(mpUser);
          ????????//?或者
          ????????mpUser.insertOrUpdate();
          ????????//?通過主鍵id刪除
          ????????mpUserService.removeById(1);
          ????????//?或者
          ????????//mpUser.deleteById();
          ????}


          }


          六、數(shù)據(jù)分頁
          1、簡單分頁方法

          int?pageNum?=?1;
          int?pageSize?=?10;
          IPage?mpUserIPage?=?mpUserService.page(new?Page<>(pageNum,?pageSize),?new?QueryWrapper().gt("age",?"20"));


          上面的分頁其實是調(diào)用BaseMapper的selectPage方法,這樣的分頁返回的數(shù)據(jù)確實是分頁后的數(shù)據(jù),但在控制臺打印的SQL語句上看到其實并沒有真正的物理分頁,而是通過緩存來獲得全部數(shù)據(jù)中再進(jìn)行的分頁,這樣對于大數(shù)據(jù)量操作時是不可取的,那么接下來就敘述一下,真正實現(xiàn)物理分頁的方法。

          2、 物理分頁方法
          新建一個MybatisPlusConfig配置類文件

          //Spring?boot方式
          @EnableTransactionManagement
          @Configuration
          @MapperScan("com.baomidou.cloud.service.*.mapper*")
          public?class?MybatisPlusConfig?{

          ????@Bean
          ????public?PaginationInterceptor?paginationInterceptor()?{
          ????????PaginationInterceptor?paginationInterceptor?=?new?PaginationInterceptor();
          ????????//?設(shè)置請求的頁面大于最大頁后操作,?true調(diào)回到首頁,false?繼續(xù)請求??默認(rèn)false
          ????????//?paginationInterceptor.setOverflow(false);
          ????????//?設(shè)置最大單頁限制數(shù)量,默認(rèn)?500?條,-1?不受限制
          ????????//?paginationInterceptor.setLimit(500);
          ????????return?paginationInterceptor;
          ????}
          }

          重新調(diào)用mpUserService.page可以看到數(shù)據(jù)有物理分頁

          3、XML自定義分頁

          UserMapper.java?方法內(nèi)容
          public?interface?UserMapper{//可以繼承或者不繼承BaseMapper
          ????/**
          ?????*?


          ?????*?查詢?:?根據(jù)state狀態(tài)查詢用戶列表,分頁顯示
          ?????*?注意!!:?如果入?yún)⑹怯卸鄠€,需要加注解指定參數(shù)名才能在xml中取值
          ?????*?


          ?????*
          ?????*?@param?page?分頁對象,xml中可以從里面進(jìn)行取值,傳遞參數(shù)?Page?即自動分頁,必須放在第一位(你可以繼承Page實現(xiàn)自己的分頁對象)
          ?????*?@param?state?狀態(tài)
          ?????*?@return?分頁對象
          ?????*/
          ????IPage?selectPageVo(Page?page,?@Param("age")?Integer?age);
          }
          UserMapper.xml?等同于編寫一個普通?list?查詢,mybatis-plus?自動替你分頁
          "1.0"?encoding="UTF-8"?>
          "-//mybatis.org//DTD?Mapper?3.0//EN"?"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
          "cn.com.bluemoon.demo.mapper.MpUserMapper">
          ????"selectPageVo"?resultType="cn.com.bluemoon.demo.entity.MpUser">
          ??????SELECT?*?FROM?mp_user?WHERE?age=#{age}
          ????



          UserServiceImpl.java 調(diào)用分頁方法

          public?IPage?selectUserPage(Page?page,?Integer?state)?{
          ????//?不進(jìn)行?count?sql?優(yōu)化,解決?MP?無法自動優(yōu)化?SQL?問題,這時候你需要自己查詢?count?部分
          ????//?page.setOptimizeCountSql(false);
          ????//?當(dāng)?total?為小于?0?或者設(shè)置?setSearchCount(false)?分頁插件不會進(jìn)行?count?查詢
          ????//?要點!!?分頁返回的對象與傳入的對象是同一個
          ????return?baseMapper.selectPageVo(page,?state);
          }

          4、測試自定義方法

          ?@Test
          ????public?void?test5()?{
          ????????Page?mpUserPage?=?new?Page<>(1,2);
          ????????IPage?iPage?=?mpUserService.selectUserPage(mpUserPage,22);
          ????????System.out.println("總頁數(shù):"+iPage.getPages());
          ????????System.out.println("總記錄數(shù):"+iPage.getTotal());
          ????????List?mpUserList1?=?iPage.getRecords();
          ????????mpUserList1.forEach(System.out::println);
          ????}


          七、打印sql日志
          為了方便排查錯誤,很多時候需要打印mybatis生成的sql語句,這時候就需要打印日志了。
          在application.yml中添加:

          ?Logger?Config
          logging:
          ??level:
          ????cn.com.vicente.demo:?debug


          或者

          mybatis-plus:
          ??configuration:
          ????log-impl:?org.apache.ibatis.logging.stdout.StdOutImpl


          八、邏輯刪除
          很多時候需要表的數(shù)據(jù)雖然刪除了,但是還是希望不是真正刪除數(shù)據(jù),數(shù)據(jù)還是留在數(shù)據(jù)庫中,只需要使用一個字段來做標(biāo)志為即可,這時候就需要邏輯刪除功能。

          SpringBoot 配置方式:

          application.yml 加入配置(如果你的默認(rèn)值和mp默認(rèn)的一樣,該配置可無):

          mybatis-plus:
          ??global-config:
          ????db-config:
          ??????logic-delete-value:?1?#?邏輯已刪除值(默認(rèn)為?1)
          ??????logic-not-delete-value:?0?#?邏輯未刪除值(默認(rèn)為?0)


          注冊 Bean(3.1.1開始不再需要這一步):

          import?com.baomidou.mybatisplus.core.injector.ISqlInjector;
          import?com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
          import?org.springframework.context.annotation.Bean;
          import?org.springframework.context.annotation.Configuration;

          @Configuration
          public?class?MyBatisPlusConfiguration?{

          ????@Bean
          ????public?ISqlInjector?sqlInjector()?{
          ????????return?new?LogicSqlInjector();
          ????}
          }


          實體類字段上加上@TableLogic注解

          @TableField(select = false)注解,可以不查詢出deleted字段

          @TableLogic
          //@TableField(select = false)
          private Integer deleted;
          效果: 使用mp自帶方法刪除和查找都會附帶邏輯刪除功能 (自己寫的xml不會)

          example
          刪除時 update user set deleted=1 where id =1 and deleted=0
          查找時 select * from user where deleted=0
          附件說明

          邏輯刪除是為了方便數(shù)據(jù)恢復(fù)和保護數(shù)據(jù)本身價值等等的一種方案,但實際就是刪除。
          如果你需要再查出來就不應(yīng)使用邏輯刪除,而是以一個狀態(tài)去表示。

          九、主鍵策略
          mybatis-plus 的主鍵生成的類型 默認(rèn)類型 是 IdType.ID_WORKER全局唯一ID,內(nèi)容為空自動填充(默認(rèn)配置),雪花算法

          1,局部主鍵策略實現(xiàn)

          在實體類中 ID屬性加注解

          @TableId(type?=?IdType.AUTO)?主鍵自增?數(shù)據(jù)庫中需要設(shè)置主鍵自增
          private?Long?id;

          @TableId(type?=?IdType.NONE)?默認(rèn)跟隨全局策略走
          private?Long?id;

          @TableId(type?=?IdType.UUID)?UUID類型主鍵
          private?Long?id;

          @TableId(type?=?IdType.ID_WORKER)?數(shù)值類型數(shù)據(jù)庫中也必須是數(shù)值類型?否則會報錯
          private?Long?id;

          @TableId(type?=?IdType.ID_WORKER_STR)?字符串類型???數(shù)據(jù)庫也要保證一樣字符類型
          private?Long?id;

          @TableId(type?=?IdType.INPUT)?用戶自定義了??數(shù)據(jù)類型和數(shù)據(jù)庫保持一致就行
          private?Long?id;


          2,全局主鍵策略實現(xiàn)

          需要在application.yml文件中添加

          mybatis-plus:
          ??global-config:
          ????db-config:
          ??????id-type:?uuid/none/input/id_worker/id_worker_str/auto


          表示全局主鍵都采用該策略(如果全局策略和局部策略都有設(shè)置,局部策略優(yōu)先級高)
          十、自動填充
          很多時候表中都需要添加創(chuàng)建時間,創(chuàng)建人,修改時間,修改人來跟蹤數(shù)據(jù)的來源和變動,但每次插入數(shù)據(jù)和修改數(shù)據(jù)的時候都要set這幾個字段又感覺很麻煩,這個時候就系統(tǒng)系統(tǒng)能自動填充這幾個字段了。

          字段必須聲明TableField注解,屬性fill選擇對應(yīng)策略,該申明告知 Mybatis-Plus 需要預(yù)留注入 SQL 字段

          @TableField(fill = FieldFill.INSERT)
          private LocalDateTime createTime;

          @TableField(fill?=?FieldFill.INSERT_UPDATE)
          private?LocalDateTime?updateTime;


          屬性fill有四種對應(yīng)策略,分別為:

          public?enum?FieldFill?{
          ????/**
          ?????*?默認(rèn)不處理
          ?????*/
          ????DEFAULT,
          ????/**
          ?????*?插入填充字段
          ?????*/
          ????INSERT,
          ????/**
          ?????*?更新填充字段
          ?????*/
          ????UPDATE,
          ????/**
          ?????*?插入和更新填充字段
          ?????*/
          ????INSERT_UPDATE
          }


          自定義實現(xiàn)類 MyMetaObjectHandler:

          @Component
          public?class?MyMetaObjectHandler?implements?MetaObjectHandler?{

          ????private?static?final?Logger?LOGGER?=?LoggerFactory.getLogger(MyMetaObjectHandler.class);

          ????@Override
          ????public?void?insertFill(MetaObject?metaObject)?{
          ????????LOGGER.info("start?insert?fill?....");
          ????????//this.setFieldValByName("createTime",?LocalDateTime.now(),?metaObject);
          ????????this.setInsertFieldValByName("createTime",?LocalDateTime.now(),?metaObject);
          ????????this.setInsertFieldValByName("updateTime",?LocalDateTime.now(),?metaObject);
          ????}

          ????@Override
          ????public?void?updateFill(MetaObject?metaObject)?{
          ????????LOGGER.info("start?update?fill?....");
          ????????this.setUpdateFieldValByName("updateTime",?LocalDateTime.now(),?metaObject);
          ????}
          }


          測試使用

          ?@Test
          ????public?void?testInsert()?{
          ????????//?插入新記錄
          ????????MpUser?mpUser?=?new?MpUser();
          ????????mpUser.setEmail("[email protected]");
          ????????mpUser.setAge(28);
          ????????mpUser.setName("王蒙");
          ????????mpUserService.save(mpUser);
          ????????log.info("mpUser={}",?mpUser.toString());
          ????}

          ?@Test
          ????public?void?testUpdate()?{
          ????????//?更新記錄
          ????????MpUser?mpUser?=?new?MpUser();
          ????????mpUser.setId(1182478087497998337L);
          ????????MpUser?newUser?=?mpUser.selectById();
          ????????System.out.println(mpUser?==?newUser);
          ????????mpUser.setName("王天");
          ????????mpUser.updateById();
          ????????log.info("mpUser={}",?mpUser.toString());
          ????????log.info("newUser={}",?newUser.toString());
          ????}


          自動填充優(yōu)化

          insertFill方法每次插入的時候都會調(diào)用,如果不存在createTime屬性的話,每次插入都會白白調(diào)用了,浪費資源,所以可以判斷是否存在該屬性

          boolean?hasCreateTime?=?metaObject.hasSetter(“createTime”);
          if?(hasCreateTime){
          this.setInsertFieldValByName(“createTime”,?LocalDateTime.now(),?metaObject);
          }

          希望,當(dāng)更新時有設(shè)定時間,就用更新時設(shè)定的時間,當(dāng)沒有設(shè)定時就自動填充更新時間,可以這樣設(shè)置

          Object?fieldValue?=?getFieldValByName(“updateTime”,?metaObject);
          if?(fieldValue?==?null){
          this.setUpdateFieldValByName(“updateTime”,?LocalDateTime.now(),?metaObject);/
          }






          粉絲福利:實戰(zhàn)springboot+CAS單點登錄系統(tǒng)視頻教程免費領(lǐng)取

          ???

          ?長按上方微信二維碼?2 秒
          即可獲取資料



          感謝點贊支持下哈?

          瀏覽 49
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  蜜芽成人在线观看 | 黄片视频在线观看免费 | 欧美偷拍精品 | 波多野结衣免费网站 | 亚洲欧美电影 |