日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

【Java萌新】MyBatis-Plus案例

發(fā)布時間:2024/9/30 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java萌新】MyBatis-Plus案例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

MyBatis-Plus是什么?

https://baomidou.com/#/
Mybatis-Plus(簡稱MP)是一個 Mybatis 的增強(qiáng)工具,在 Mybatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡化開發(fā)、提高效率而生。這是官方給的定義,關(guān)于mybatis-plus的更多介紹及特性,可以參考mybatis-plus官網(wǎng)。那么它是怎么增強(qiáng)的呢?其實就是它已經(jīng)封裝好了一些crud方法,我們不需要再寫xml了,直接調(diào)用這些方法就行,就類似于JPA。

特性

  • 無侵入 :只做增強(qiáng)不做改變,引入它不會對現(xiàn)有工程產(chǎn)生影響,如絲般順滑
  • 損耗小 :啟動即會自動注入基本 CURD,性能基本無損耗,直接面向?qū)ο蟛僮? BaseMapper
  • 強(qiáng)大的 CRUD 操作 :內(nèi)置通用 Mapper、通用 Service,僅僅通過少量配置即可實現(xiàn)單表大部分 CRUD 操作,更有強(qiáng)大的條件構(gòu)造器,滿足各類使用需求, 以后的簡單的增刪改查, 它不用自己寫了!
  • 支持 Lambda 形式調(diào)用 :通過 Lambda 表達(dá)式,方便的編寫各類查詢條件,無需再擔(dān)心字段寫錯
  • 支持主鍵自動生成 :支持多達(dá) 4 種主鍵策略(內(nèi)含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問題
  • 支持 ActiveRecord 模式 :支持 ActiveRecord 形式調(diào)用,實體類只需繼承 Model 類即可進(jìn)行強(qiáng)大的 CRUD 操作
  • 支持自定義全局通用操作 :支持全局通用方法注入( Write once, use anywhere )
  • 內(nèi)置代碼生成器 :采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來使用,可插拔的方式(自動幫你生成代碼)
  • 內(nèi)置分頁插件 :基于 MyBatis 物理分頁,開發(fā)者無需關(guān)心具體操作,配置好插件之后,寫分頁等同于普通 List 查詢
  • 分頁插件支持多種數(shù)據(jù)庫 :支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種數(shù)據(jù)庫
  • 內(nèi)置性能分析插件 :可輸出 Sql 語句以及其執(zhí)行時間,建議開發(fā)測試時啟用該功能,能快速揪出慢查詢
  • 內(nèi)置全局?jǐn)r截插件 :提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規(guī)則,預(yù)防誤操作

快速入門

地址: https://baomidou.com/guide/quick-start.html
使用第三方組件

  • 導(dǎo)入對應(yīng)依賴
  • 研究如何讓編寫配置
  • 代碼如何編寫
  • 提高拓展

步驟

創(chuàng)建數(shù)據(jù)庫

mybatis_plus

創(chuàng)建 user表

DROP TABLE IF EXISTS user;CREATE TABLE user (id BIGINT(20) NOT NULL COMMENT '主鍵ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年齡',email VARCHAR(50) NULL DEFAULT NULL COMMENT '郵箱',PRIMARY KEY (id) );真實開發(fā)過程中, version(樂觀鎖)、delete(邏輯刪除)、gmt_create、gm_modified

其對應(yīng)的數(shù)據(jù)庫 Data 腳本如下:

DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com');

創(chuàng)建SpringBoot項目

mybatis_plus

導(dǎo)入依賴

<!--數(shù)據(jù)庫驅(qū)動--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--mybatis-plus-boot-starter是自己開發(fā)的, 并非官方--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency>

說明: 我們使用mybatis-plus可以節(jié)省我們大量代碼, 盡量不要導(dǎo)入mybtis和mybatis-plus! 版本差異

連接數(shù)據(jù)庫

spring.datasource.username=root spring.datasource.data-password=123456 spring.datasource.url=jdbc:mysql://cdb-q9atzwrq.bj.tencentcdb.com:10167/mybatis_plus?useSSL=false&amp;useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # serverTimezone=GMT 時區(qū) 8.0以上版本需要添加否則會報錯

傳統(tǒng)項目結(jié)構(gòu)對比使用mybatis-plus之后

  • pojo-dao(連接mybatis, 配置mapper.xml文件)service-controller
  • 使用mybatis-plus之后
  • pojo
  • mapper接口
package cn.com.codingce.mapper;import cn.com.codingce.pojo.User; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository;/*** 在對應(yīng)的Mapper上實現(xiàn)基本接口BaseMapper* @author xzMa*/ @Mapper @Repository public interface UserMapper extends BaseMapper<User> {//所有的CRUD操作都已經(jīng)編寫完成 }
  • 使用
package cn.com.codingce;import cn.com.codingce.mapper.UserMapper; import cn.com.codingce.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest class MybatisPlusApplicationTests {@Autowiredprivate UserMapper userMapper;/*wrapper條件構(gòu)造器, 這里我們先不用 null//查詢?nèi)坑脩?/@Testvoid contextLoads() {List<User> users = userMapper.selectList(null);users.forEach(System.out::println);}}

思考問題

  • SQL誰幫我們寫好了? MyBatis-Plus都寫好了
    方法哪里來? MyBatis-Plus都寫好了

配置日志

我們所有的SQL是不可見的, 我們希望知道它是怎么執(zhí)行的, 所以我們必須要看日志
(真正上線, 在下)

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

CRUD拓展

Insert

@Testvoid testInsert() {User user = new User();user.setName("掌上編程");user.setAge(19);user.setEmail("2460798168@qq.com");userMapper.insert(user);}

數(shù)據(jù)庫插入的id的默認(rèn)值為:全局的唯一id

主鍵的策略

分布式系統(tǒng)唯一id生成:

默認(rèn)@TableId(type = IdType.ID_WORKER)private Long id;

雪花算法:snowflake是Twitter開源的分布式ID生成算法,結(jié)果是一個long型的ID。其核心思想是:使用41bit作為毫秒數(shù),10bit作為機(jī)器的ID(5個bit是數(shù)據(jù)中心,5個bit的機(jī)器ID),12bit作為毫秒內(nèi)的流水號(意味著每個節(jié)點(diǎn)在每毫秒可以產(chǎn)生 4096 個 ID),最后還有一個符號位,永遠(yuǎn)是0。具體實現(xiàn)的代碼可以參看https://github.com/twitter/snowflake。

主鍵自增

我們需要配置主鍵自增

  • 實體類字段上 @TableId(type = IdType.AUTO)

  • 數(shù)據(jù)庫字段一定要自增!

  • 再次測試插入即可

其他源碼檢測

public enum IdType {AUTO(0), //數(shù)據(jù)庫id自增NONE(1), //未設(shè)置主鍵INPUT(2), //手動輸入ID_WORKER(3),//默認(rèn)的全局idUUID(4), //全局唯一id uuidID_WORKER_STR(5); //ID_WORKER 字符串表示法private int key;private IdType(int key) {this.key = key;}public int getKey() {return this.key;} }

更新操作

@Testvoid testUpdate() {User user = new User();//通過條件自動拼接動態(tài)sqluser.setId(1L);user.setEmail("21211@qq.com");int i = userMapper.updateById(user);System.out.println(i);}

自動填充

創(chuàng)建時間、更改時間! 這些操作一遍都是自動化完成的, 我們不希望手動更新!
阿里巴巴開發(fā)手冊:所有的數(shù)據(jù)表:gm_create、 gmt_modified 幾乎所有的表都需要配置上!而且需要自動化!

方式一 數(shù)據(jù)庫級別

  • 在表中新增字段create_time、 update_time

package cn.com.codingce.pojo;import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.util.Date;/*** @author xzMa*/ @Data @AllArgsConstructor @NoArgsConstructor public class User {@TableId(type = IdType.AUTO)private Long id;private String name;private Integer age;private String email;private Date createTime;private Date updateTime;}

方式二:代碼級別

數(shù)據(jù)庫的時間默認(rèn)值去掉

直接在實體類中

package cn.com.codingce.pojo;import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.util.Date;/*** @author xzMa*/ @Data @AllArgsConstructor @NoArgsConstructor public class User {@TableId(type = IdType.AUTO)private Long id;private String name;private Integer age;private String email;@TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;}

MyMetaObjectHandler

package cn.com.codingce.handler;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component;import java.util.Date;/*** 自己寫的處理器* @author xzMa*/ @Slf4j @Component //一定不要把我們的處理器加到IOC中 public class MyMetaObjectHandler implements MetaObjectHandler {//插入時的填充策略@Overridepublic void insertFill(MetaObject metaObject) {log.info("Start insert fill ...");//String fieldName, Object fieldVal, MetaObject metaObjectthis.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);}//更新時的填充策略@Overridepublic void updateFill(MetaObject metaObject) {log.info("Start update fill ...");this.setFieldValByName("updateTime", new Date(), metaObject);} }

樂觀鎖

在面試過程中, 我們經(jīng)常會被問到的樂觀鎖, 悲觀鎖! 這個其實非常簡單!

樂觀鎖:樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖假設(shè)認(rèn)為數(shù)據(jù)一般情況下不會造成沖突,所以在數(shù)據(jù)進(jìn)行提交更新的時候,才會正式對數(shù)據(jù)的沖突與否進(jìn)行檢測,如果發(fā)現(xiàn)沖突了,則讓返回用戶錯誤的信息,讓用戶決定如何去做。
故名思意十分樂觀, 它總是認(rèn)為不會出現(xiàn)問題, 無論干什么都不去上鎖! 如果出現(xiàn)問題, 再次更新新值測試(version new version)

悲觀鎖:故名思意十分悲觀, 它總認(rèn)為總是出現(xiàn)問題, 無論干什么都會上鎖! 再去操作!

樂觀鎖機(jī)制:

  • 取出記錄記錄, 獲取當(dāng)前version
  • 更新時, 帶上這個version
  • 執(zhí)行更新時, set version = new Version where version = oldVersion
  • 如果version不對, 就更新失敗
---A update user set name = "zhangshangbiancheng", version = version + 1 where id = 2 and version = 1---B 線程搶先完成, 這個時候 version = 2 會導(dǎo)致A修改失敗! update user set name = "zhangshangbiancheng", version = version + 1 where id = 2 and version = 1

測試MP樂觀鎖插件

  • 給數(shù)據(jù)庫中添加version字段

  • 我們對實體類添加對應(yīng)的字段
@Version //樂觀鎖Version注解private Integer version;
  • 注冊組件
package cn.com.codingce.config;import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement;@EnableTransactionManagement //掃描我們的mapper文件夾 @MapperScan("cn.com.codingce.mapper") @Configuration //配置類 public class MyBatisPlusConfig {//注冊樂觀鎖插件@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();}}
  • 測試
@Testvoid testOptimisticLocker() {//查詢用戶信息User user = userMapper.selectById(1L);//修改用戶信息user.setName("xzMhehe");user.setEmail("codingce@ce.com");//執(zhí)行更新操作userMapper.updateById(user);}/*** 測試樂觀鎖失敗 多線程下*/@Testvoid testOptimisticLocker2() {//線程1User user = userMapper.selectById(1L);user.setName("xzMhehe111");user.setEmail("codingce@ce.com");//模擬另外一個線程執(zhí)行了插隊操作User user2 = userMapper.selectById(1L);user2.setName("xzMhehe222");user2.setEmail("codingce@ce.com");userMapper.updateById(user2);//自旋鎖來多次嘗試提交userMapper.updateById(user); //如果沒有樂觀鎖就會覆蓋插隊線程的值!}

查詢操作

@Testpublic void select() {User user = userMapper.selectById(1L);System.out.println(user);}@Testpublic void selectBatchIds() {List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L));users.forEach(System.out::println);}//條件查詢 map@Testpublic void testSelectByBathIds() {HashMap<String, Object> map = new HashMap<>();//自定義要查詢map.put("name", "xzMhehe222");map.put("age", 12);List<User> userList = userMapper.selectByMap(map);userList.forEach(System.out::println);}

分頁查詢

分頁在網(wǎng)站使用的十分之多

  • 原始的limit進(jìn)行分頁
  • pageHelper第三方插件
  • MP其實也內(nèi)置了分頁插件

如何使用

配置攔截器組件

//Spring boot方式 @Configuration @MapperScan("com.baomidou.cloud.service.*.mapper*") public class MybatisPlusConfig {@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();} }
  • 直接使用Page插件即可
/*** 測試分頁*/@Testpublic void testPage() {//current參數(shù)一:當(dāng)前頁//參數(shù)二:頁面大小Page<User> page = new Page<>(1, 5);IPage<User> userIPage = userMapper.selectPage(page, null);page.getRecords().forEach(System.out::println);}

基本刪除操作

//真刪@Testpublic void testDelete() {userMapper.deleteById(1L);}//批量刪除@Testpublic void testDeleteBatchId() {userMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L));}//通過map刪除@Testpublic void testDeleteMap() {HashMap<String, Object> map = new HashMap<>();map.put("name", "xzMhehe");userMapper.deleteByMap(map);}

我們在工作中會遇到一些問題:邏輯刪除

邏輯刪除

物理刪除:從數(shù)據(jù)庫中直接刪除
邏輯刪除:在數(shù)據(jù)庫中沒有移除,而是通過一個變量讓他失效! deleted = 0 =>deleted = 1
管理員可以查看刪除記錄!防止數(shù)據(jù)丟失,類似于回收站

  • 在數(shù)據(jù)庫中添加deleted字段

  • 在實體類中添加屬性
@TableField //邏輯刪除private Integer deleted;
  • 配置
//邏輯刪除組件@Beanpublic ISqlInjector sqlInjector() {return new LogicSqlInjector();} mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0

性能分析插件

在平時開發(fā)中, 會遇到一些慢sql. 測試!druid
MP也提供性能分析插件, 如果超過這個時間停止運(yùn)行!

  • 導(dǎo)入插件
@Bean@Profile({"dev", "test"}) //設(shè)置 dev text 環(huán)境開啟, 保障我們的效率public PerformanceInterceptor performanceInterceptor() {PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();// 在工作中, 不允許用戶等待performanceInterceptor.setMaxTime(500); //ms 設(shè)置sql執(zhí)行的最大時間, 如果超過了則不執(zhí)行performanceInterceptor.setFormat(true); //開啟格式化輸出return performanceInterceptor;}
  • 測試使用

條件構(gòu)造器

十分重要 Wrapper

  • 測試1
@Testvoid contextLoads() {//查詢條件name和郵箱不為空的用戶, 年齡大于等于12的用戶QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name").isNotNull("email").ge("age", 12);userMapper.selectList(wrapper).forEach(System.out::println); //對比Map}
  • 測試2
@Testpublic void Test() {//查詢名字 全棧自學(xué)社區(qū)QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name", "全棧自學(xué)社區(qū)");userMapper.selectList(wrapper).forEach(System.out::println);} @Testpublic void Test3() {//年齡在20~30歲之間的人QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.between("age", 20, 30);Integer count = userMapper.selectCount(wrapper);System.out.println(count);userMapper.selectList(wrapper).forEach(System.out::println);}@Testpublic void Test4() {//名字中不包含QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLike("name", "e").likeRight("email", "t"); //左和右 %t% likeRight("email", "t") t%List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);maps.forEach(System.out::println);}@Testpublic void Test5() {//id在子查詢查出來QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.inSql("id", "select id from user where id < 3");List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);maps.forEach(System.out::println);}@Testpublic void Test6() {//排序QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByDesc("id");List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);maps.forEach(System.out::println);}

代碼自動生成器

dao pojo service controller 都是自動生成

package cn.com.codingce.generator;import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.po.TableFill; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;import java.util.ArrayList;public class CodeGenerator {public static void main(String[] args) {// 1、創(chuàng)建代碼生成器AutoGenerator mpg = new AutoGenerator();// 2、全局配置GlobalConfig gc = new GlobalConfig();//當(dāng)前的項目路徑String projectPath = System.getProperty("user.dir");//所有代碼都會生成到 /src/main/java 路徑下gc.setOutputDir(projectPath + "/src/main/java");gc.setAuthor("小馬Coding");gc.setOpen(false); //生成后是否打開資源管理器gc.setFileOverride(false); //重新生成時文件是否覆蓋gc.setServiceName("%sService"); //去掉Service接口的首字母Igc.setIdType(IdType.ID_WORKER_STR); //主鍵策略gc.setDateType(DateType.ONLY_DATE);//定義生成的實體類中日期類型gc.setSwagger2(true);//開啟Swagger2模式mpg.setGlobalConfig(gc);// 3、數(shù)據(jù)源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://cdb-q9atzwrq.bj.tencentcdb.com:10167/codingstudy?useUnicode=true&characterEncoding=utf-8&useSSL=false");dsc.setDriverName("com.mysql.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("123456");dsc.setDbType(DbType.MYSQL);mpg.setDataSource(dsc);// 4、包配置PackageConfig pc = new PackageConfig();pc.setModuleName("blog");pc.setParent("cn.com.codingce");pc.setController("controller");pc.setEntity("pojo");pc.setService("service");pc.setMapper("mapper");mpg.setPackageInfo(pc);// 5、策略配置StrategyConfig strategy = new StrategyConfig();//strategy.setInclude("ze_user");//設(shè)置要映射的表名//strategy.setInclude("ze_user", "ze_course");//可設(shè)置多個strategy.setInclude("ze_user");//設(shè)置要映射的表名strategy.setNaming(NamingStrategy.underline_to_camel);//數(shù)據(jù)庫表映射到實體的命名策略strategy.setTablePrefix("ze_");//設(shè)置表前綴不生成strategy.setColumnNaming(NamingStrategy.underline_to_camel);//數(shù)據(jù)庫表字段映射到實體的命名策略strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter鏈?zhǔn)讲僮?/span>strategy.setRestControllerStyle(true); //restful api風(fēng)格控制器strategy.setControllerMappingHyphenStyle(true); //url中駝峰轉(zhuǎn)連字符//strategy.setLogicDeleteFieldName("deleted"); //邏輯刪除字段//自動填充配置//TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);//TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);//ArrayList<TableFill> tableFills = new ArrayList<>();//tableFills.add(gmtCreate);//tableFills.add(gmtModified);//strategy.setTableFillList(tableFills);mpg.setStrategy(strategy);// 6、執(zhí)行mpg.execute();} }

項目地址

https://github.com/xzMhehe/codingce-java/tree/master/mybatis_plus

總結(jié)

以上是生活随笔為你收集整理的【Java萌新】MyBatis-Plus案例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。