MyBatis Generator 配置文件详解

MyBatis Generator (MBG) 是由一个XML配置文件驱动的。这个配置文件中会声明以下内容:

  1. 如何连接数据库
  2. 要生成什么对象,以及如何生成它们
  3. 哪些表需要应用于对象生成。

根元素 generatorConfiguration 和 DOCTYPE 信息

generatorConfiguration 元素是配置文件的根元素。该元素没有任何属性,但下面包含以下子元素。

  1. properties (0个或1个)
  2. classPathEntry (0个或多个)
  3. context (1个或多个)

注:MyBatis Generator 文件需要包含内容如下的 DOCTYPE 信息:

<!DOCTYPE generatorConfiguration PUBLIC
  " -  // mybatis.org//DTD MyBatis Generator Configuration 1.0 // EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

classPathEntry

classPathEntry 元素用于将一个path添加到MBG运行时的classpath中。classPathEntry元素是generatorConfiguration元素的可选子元素。如果配置了这个元素,MBG在以下情况下会从这个path下加载类库:

  1. 当加载 JDBC 驱动内省数据库时
  2. 当加载根类中的 JavaModelGenerator 检查重写的方法时

这个元素是可选的,而且如果您给MGB安装了类路径,您就不需要这个元素(例如 使用java命令时使用参数-cp)。

注意:在加载MBG的扩展类,或者是实现了MBG接口的类时,不会从这个参数所指定的路径下加载。这种情况必须使用外部类加载方法(如java命令的 -pc参数)进行加载。

重要说明

classPathEntry只在下面这两种情况下才有效:

  1. 当加载 JDBC 驱动内省数据库时
  2. 当加载根类中的 JavaModelGenerator 检查重写的方法时

因此,如果你需要加载其他用途的jar包,classPathEntry起不到作用,不能这么写,解决的办法就是将你用的jar包添加到类路径中,在Eclipse等IDE中运行的时候,添加jar包比较容易。当从命令行执行的时候,需要用java -cp xx.jar,xx2.jar xxxMainClass这种方式在-cp后面指定来使用(注意-jar会导致-cp无效)。

必填属性 location

要添加到classpath中的 JAR/ZIP 文件的完整路径名称或要添加到类路径中的目录。

properties

properties 元素用于指定一个存储了外部配置信息的、符合java属性文件格式的"配置文件"。在“MyBatis Generator 配置文件”中可以使用${property} 的形式获取该"配置文件"中的值。如果在“配置文件”中所指定的属性与系统属性之间存在名称冲突,则以系统属性优先。

properties 元素是 generatorConfiguration元素的子元素。

必填属性

下面表格中的两个属性,在properties元素中需要且仅需要有一个。

属性 描述
resource 属性文件的限定名称。当指定此属性时,会搜索类路径以查找属性文件。因此当此属性指定为com/myproject/generatorConfig.properties时 则在com.myproject包中必须存在名为generatorConfig.properties 的文件。
url 属性文件的URL。使用此属可以在文件系统中指定属性文件file:///C:/myfolder/generatorConfig.properties

context

context 元素用于指定生成一组对象的上下文环境。它包括很多子元素(后面会一一介绍),这些子元素有些用于指定数据库连接,有些用于指定要生成对象的类型,还有些用于指定需要内省的表。

context 元素是generatorConfiguration的子元素,一个generatorConfiguration元素可以包含多个context元素,但最少需要包含一个context元素。第一个context 元素代表一个生成对象的上下文。

必填属性 id

id属性是必需的,用于指定当前上下文的唯一标识。在错误信息的显示时,会用到这个id属性的值。

可选属性 defaultModelType

该属性用于为生成的模型类型设置默认值。模型类型定义了MBG如何生成domain类。对于某些模型类型,MBG将为每个表生成一个单独的domain类,其他类型的MBG可能会根据表的结构生成几个不同的类。该属性支持的值如下:

  1. conditional : 此值为defaultModelType属性的默认值。这个类型的model 与 hierarchical 类型的 model 类似,唯一的区别在于 如果分离出来的“主键类”中只有一个字段则不会生成单独的“主键类”。所以如果一个表只有一个主键字段,则会把这个主键合并到 基本记录 类中。
  2. flat :这种类型的model会为每个表生成唯一的一个类,这个类中会包含表中所有的字段。
  3. hierarchical :这种类型的model 会为包含主键的表单独生成一个主键类,并为包含BLOB类型的表中所有BLOB类型字段生成一个类,其他所有字段再单独生成一个类。这些类之间会生成对应的继承关系。

可选属性defaultModelType 的 默认值为 conditional。

可选属性 targetRuntime

targetRuntime属性用于指定生成代码的运行时环境。该属性支持以下值:

  1. MyBatis3 :此值为targetRuntime属性的默认值。使用这个值,MBG将生成与 “Mybatis v3.0及以上版本 和 JSE 5.0 及以上版本”相兼容的对象(例如,Java模型和映射器接口将使用泛型类型)。在这些生成的对象中,"by example" 方法支持几乎所有的动态子句。此外,使用这些生成的java对象还支持 JSE 5.0特性,包括泛型和注解。
  2. MyBatis3Simple:使用这个值,MBG将生成与 “Mybatis v3.0 及以上版本 和 JSE 5.0 及以上版本”相兼容的对象(例如,Java模型和映射器接口将使用泛型类型,接口中将使用默认方法等)。不同的是,使用这个targetRuntime生成的映射器是非常基本的CRUD操作,没有“by example”方法,仅支持很少的动态SQL。使用这些生成的java对象支持 JSE 5.0特性,包括泛型和注解。
  3. MyBatis3DynamicSql:使用这个值,MBG将生成与 “Mybatis v3.4.2 及以上版本 和 Java 8 及以上版本”相兼容的对象(例如,Java模型和映射器接口将使用泛型类型)。targetRuntime使用此值时,还有以下内容需要注意:
    1. 无论为“defaultModelType”指定什么,model对象都以“flat”模式生成。这也意味着没有“with BLOBs”和“without BLOBs”方法。
    2. 不管为<javaClientGenerator>的“type”指定为什么,映射器都会生成为带注解的映射器。
    3. 不会生成XML。<sqlMapGenerator>不是必需的,如果指定将被忽略。
    4. MyBatis Dynamic SQL以“per query”方式支持表别名,而不是“all or nothing”方式。出于这个原因,配置的表别名被忽略。
    5. 使用MyBatis3DynamicSql 生成的Java代码依赖于“MyBatis Dynamic SQL”支持库。
  4. Ibatis2Java2: 已经过时了,不做介绍
  5. Ibatis2Java5: 已经过时了,不做介绍

可选属性 targetRuntime 的默认值是 MyBatis3。

如果你想创建一个自己的代码生成器,你的类需要继承org.mybatis.generator.api.IntrospectedTable。然后使用这个值指定类的完全限定名称。这样你就可以把自己的代码生成器插入到代码生成引擎中。

可选属性 introspectedColumnImpl

使用此值可指定一个继承自org.mybatis.generator.api.IntrospectedColumn的类的完全限定名称。如果您想要在计算列信息时更改代码生成器的行为,请使用此选项。

子元素

需要注意一下,在context元素中,子元素出现的顺序是有要求的。必须按如下顺序出现。

  1. property (0个或多个)
  2. plugin (0个或多个)
  3. commentGenerator (0个或1个)
  4. connectionFactory (connectionFactory 或jdbcConnection 必有其一)
  5. jdbcConnection (connectionFactory 或jdbcConnection 必有其一)
  6. javaTypeResolver (0个或1个)
  7. javaModelGenerator (1个必填)
  8. sqlMapGenerator (0个或1个)
  9. javaClientGenerator (0个或1个)
  10. table (1个或多个)

支持的属性

下表列出了在context元素下支持的使用property子元素指定的属性。

属性名称 属性值
autoDelimitKeywords 如果为true,那么MBG将分隔SQL关键字(如果它们用作表中的列名称)。MBG为许多不同的数据库维护一个SQL关键字列表(可能并不全)。如果某个关键字不在MBG的列表中,则可以强制使用<columnOverride>进行分隔 。
有关 MBG识别的关键字列表,请参阅org.mybatis.generator.internal.db.SqlReservedWords类的源代码 。
默认值是false。
beginningDelimiter 分隔符的起始字符。如果标识符包含空格,MBG将自动分隔SQL标识符。如果在<table>或<columnOverride>配置中进行了配置,MBG也会分隔SQL标识符。默认值是双引号"
endingDelimiter 分隔符的结束字符。如果标识符包含空格,MBG将自动分隔SQL标识符。如果在<table>或<columnOverride>配置中进行了配置,MBG也会分隔SQL标识符。默认值是双引号"
javaFileEncoding 使用此属性可指定生成Java文件的编码。新生成的Java文件将以此编码写入文件系统,并在执行合并时使用此编码读取现有的Java文件。如果未指定,则将使用平台默认编码。有关有效编码的信息,请参阅java.nio.charset.Charset。
javaFormatter 使用此属性来指定生成Java文件所使用formater的完整类名。该类必须实现org.mybatis.generator.api.JavaFormatter, 并且必须有一个默认(无参数)构造函数。每个context元素都包含Java格式化程序的单个实例。默认的Java格式化程序是 org.mybatis.generator.api.dom.DefaultJavaFormatter。默认格式化程序使用内置于Java DOM类中的格式。
xmlFormatter 使用此属性来指定生成XML文件所使用formater的完整类名。该类必须实现org.mybatis.generator.api.XmlFormatter, 并且必须有一个默认(无参数)构造函数。每个context元素包含XML格式化程序的单个实例。默认的XML格式化程序是 org.mybatis.generator.api.dom.DefaultXmlFormatter。默认格式化程序使用内置到XML DOM类中的格式。

context 小结

一般情况下,我们使用如下的配置即可:

<context id="Mysql" defaultModelType="flat">

如果你希望不生成和Example查询有关的内容,那么可以按照如下进行配置:

<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">

使用MyBatis3Simple可以避免在后面的<table>中逐个进行配置(后面会提到)。

plugin

该元素可以配置0个或者多个,不受限制。

plugin元素用来定义一个插件。插件用于扩展或修改通过MyBatis Generator (MBG)代码生成器生成的代码。

插件将按在配置中配置的顺序执行。

必选属性 type

实现接口org.mybatis.generator.api.Plugin的类的完全限定名的插件。该类必须实现org.mybatis.generator.api.Plugin接口 , 且必须有一个公开默认的构造函数。注意,继承 org.mybatis.generator.api.PluginAdapter 这个适配器类比实现org.mybatis.generator.api.Plugin接口更容易扩展。

commentGenerator

commentGenerator元素是可选的,并且在context元素中最多只能存在一个。

commentGenerator 元素用于配置注释生成器的属性。在MBG中注释生成器用于生成 Java文件和XML文件中的注释。默认的注释生成器将JavaDoc 注释添加到生成的Java元素和XML元素上。注释的目的是要告诉用户这个元素是自动生成的,并且有可能重新生成(也就是说这部分内容不应该被用户修改)。

默认的实现类是 org.mybatis.generator.internal.DefaultCommentGenerator。

可选属性 type

指定用户提供的注释生成器类。 这个类必须继承org.mybatis.generator.api.CommentGenerator接口。 而且必须有一个默认的构造函数。 这个属性接收指定特殊的值 DEFAULT,这将会使用默认的实现类(这和不指定该属性的效果一样)。

支持的属性 property

下表中列出了commentGenerator 元素中可能通过property子元素进行设置的属性:

属性名 属性值
suppressAllComments 这个属性用来指定MBG生成的代码中是否包含注释。 这个属性有以下可选值:
1. false 这是默认值
当这个属性是false或者没有指定时,所有生成的元素都会包含用来说明这是生成元素的注释。
2. true 当这个属性是true时,不会往生成的元素中添加任何注释。
注意:如果您将这个值设为true,那么所有的代码合并都会被禁用。
suppressDate 这个元素用来指定生成的注释中是否包含生成的日期。 这个属性有以下可选值:
1. false 这是默认值
当这个属性是false或者没有指定时,所有元素生成注释时都会带着生成时间。
2. true 当这个属性是true时,注释中不会添加生成时间。

示例

下面这段代码指定了我们希望生成的注释中不包含时间戳:

<commentGenerator>
  <property name="suppressDate" value="true" />
</commentGenerator>

jdbcConnection

jdbcConnection元素用于指定数据库连接所需的的属性。 每一个context元都必须有且仅有一个jdbcConnection元素。配置该元素需要注意如果JDBC驱动不在classpath下,就需要通过<classPathEntry>元素引入jar包,这里推荐将jar包放到classpath下。

该元素有两个必选属性:

  1. driverClass:访问数据库的JDBC驱动程序的完全限定类名
  2. connectionURL:访问数据库的JDBC连接URL

该元素还有两个可选属性:

  1. userId:访问数据库的用户ID
  2. password:访问数据库的密码

此外该元素还可以接受多个<property>子元素,配置的<property>属性都会添加到JDBC驱动的属性中。

这个元素配置起来最容易,这里举个简单例子:

<jdbcConnection driverClass="com.mysql.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost:3306/test"
            userId="root"
            password="">
</jdbcConnection>

javaTypeResolver

该元素是可选的,在context元素中最多可以配置一个。

这个元素的配置用来指定JDBC类型和Java类型之间如何转换。

该元素提供了一个可选的属性type,和<commentGenerator>比较类似,提供了默认的实现DEFAULT,一般情况下使用默认即可,需要特殊处理的情况可以通过其他元素配置来解决,不建议修改该属性。

javaTypeResolver元素可以包含0个或多个property元素。但目录仅有一个配置(forceBigDecimals)可用,forceBigDecimals属性可以控制是否强制DECIMAL和NUMERIC类型的字段转换为Java类型的java.math.BigDecimal,默认值为false,一般不需要配置。
默认情况下的转换规则为:

  1. 如果精度>0或者长度>18,就会使用java.math.BigDecimal

  2. 如果精度=0并且10<=长度<=18,就会使用java.lang.Long

  3. 如果精度=0并且5<=长度<=9,就会使用java.lang.Integer

  4. 如果精度=0并且长度<5,就会使用java.lang.Short

  5. 如果设置为true,那么一定会使用java.math.BigDecimal,配置示例如下:

    <javaTypeResolver >
    <property name="forceBigDecimals" value="true" />
    </javaTypeResolver>

javaModelGenerator

javaModelGenerator 元素在context元素中必须有、且只能有一个。

该元素用来控制生成的实体类,根据context中配置的defaultModelType,一个表可能会对应生成多个不同的实体类。一个表对应多个类实际上并不方便,所以前面也推荐使用flat,这种情况下一个表对应一个实体类。

该元素只有两个属性,都是必选的。

  1. targetPackage:生成实体类存放的包名。一般就是放在该包下,实际还会受到其他配置的影响(<table>中会提到)。
  2. targetProject:指定目标项目路径,使用的是文件系统的绝对路径。

javaModelGenerator 元素支持以下几个property子元素属性:

  1. constructorBased:该属性只对MyBatis3有效,如果true就会使用构造方法入参,如果false就会使用setter方式。默认为false。
  2. enableSubPackages:如果true,MBG会根据catalog和schema来生成子包。如果false就会直接用targetPackage属性。默认为false。
  3. immutable:该属性用来配置实体类属性是否可变,如果设置为true,那么constructorBased不管设置成什么,都会使用构造方法入参,并且不会生成setter方法。如果为false,实体类属性就可以改变。默认为false。
  4. rootClass:设置所有实体类的基类。如果设置,需要使用类的全限定名称。并且如果MBG能够加载rootClass,那么MBG不会覆盖和父类中完全匹配的属性。匹配规则:
    • 属性名完全相同
    • 属性类型相同
    • 属性有getter方法
    • 属性有setter方法
  5. trimStrings:是否对数据库查询结果进行trim操作,如果设置为true就会生成类似这样public void setUsername(String username) {this.username = username == null ? null : username.trim();}的setter方法。默认值为false。

配置示例如下:

<javaModelGenerator targetPackage="test.model" targetProject="E:\MyProject\src\main\java">
  <property name="enableSubPackages" value="true" />
  <property name="trimStrings" value="true" />
</javaModelGenerator>

sqlMapGenerator

该元素可选,在context中最多配置一个。但是有如下两种必选的特殊情况:

  1. 如果targetRuntime目标是iBATIS2,该元素必须配置一个。
  2. 如果targetRuntime目标是MyBatis3,只有当<javaClientGenerator>需要XML时,该元素必须配置一个。 如果没有配置 <javaClientGenerator>,则使用以下的规则:
    • 如果指定了一个<sqlMapGenerator>,那么MBG将只生成XML的SQL映射文件和实体类。
    • 如果没有指定<sqlMapGenerator>,那么MBG将只生成实体类。

该元素只有两个属性(和前面提过的<javaModelGenerator>的属性含义一样),都是必选的。

  1. targetPackage:生成实体类存放的包名,一般就是放在该包下。实际还会受到其他配置的影响(<table>中会提到)。
  2. targetProject:指定目标项目路径,使用的是文件系统的绝对路径。

该元素支持<property>子元素,只有一个可以配置的属性:

  1. enableSubPackages:如果true,MBG会根据catalog和schema来生成子包。如果false就会直接用targetPackage属性。默认为false。

配置示例:

<sqlMapGenerator targetPackage="test.xml"  targetProject="E:\MyProject\src\main\resources">
  <property name="enableSubPackages" value="true" />
</sqlMapGenerator>

javaClientGenerator

javaClientGenerator元素可选,在context元素中最多配置一个。如果不配置该元素,就不会生成Mapper接口。

javaClientGenerator元素有3个必选属性:

  1. type:该属性用于选择一个预定义的客户端代码(可以理解为Mapper接口)生成器,用户可以自定义实现,需要继承org.mybatis.generator.codegen.AbstractJavaClientGenerator类,必选有一个默认的构造方法。 该属性提供了以下预定的代码生成器,首先根据<context>的targetRuntime分成三类:
    1. MyBatis3:
      • ANNOTATEDMAPPER:基于注解的Mapper接口,不会有对应的XML映射文件
      • MIXEDMAPPER:XML和注解的混合形式,(上面这种情况中的)SqlProvider注解方法会被XML替代。
      • XMLMAPPER:所有的方法都在XML中,接口调用依赖XML文件。
    2. MyBatis3Simple:
      • ANNOTATEDMAPPER:基于注解的Mapper接口,不会有对应的XML映射文件
      • XMLMAPPER:所有的方法都在XML中,接口调用依赖XML文件。
      • Ibatis2Java2或Ibatis2Java5:
    3. IBATIS:生成的对象符合iBATIS的DAO框架(不建议使用)。
      • GENERIC-CI:生成的对象将只依赖于SqlMapClient,通过构造方法注入。
      • GENERIC-SI:生成的对象将只依赖于SqlMapClient,通过setter方法注入。
      • SPRING:生成的对象符合Spring的DAO接口
  2. targetPackage:生成实体类存放的包名,一般就是放在该包下。实际还会受到其他配置的影响(<table>中会提到)。
  3. targetProject:指定目标项目路径,使用的是文件系统的绝对路径。

javaClientGenerator元素还有一个可选属性:

  1. implementationPackage:如果指定了该属性,实现类就会生成在这个包中。

javaClientGenerator元素支持<property>子元素设置的属性:

  1. enableSubPackages
  2. exampleMethodVisibility
  3. methodNameCalculator
  4. rootInterface
  5. useLegacyBuilder

这几个属性不太常用,具体作用请看完整的文档,这里对rootInterface做个简单介绍。

rootInterface用于指定一个所有生成的接口都继承的父接口。 这个值可以通过<table>配置的rootInterface属性覆盖。这个属性对于通用Mapper来说,可以让生成的所有接口都继承该接口。

配置示例:

<javaClientGenerator type="XMLMAPPER" targetPackage="test.dao"
          targetProject="E:\MyProject\src\main\java"/>

table

table 元素在context元素中最少要配置一个,可以配置多个。由于table元素非常复杂,并且还包括多个复杂的子元素,所以单独一篇进行介绍,请移步:MyBatis Generator 配置文件详解 之 table 元素

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 相关链接:MyBatis Generator 配置文件详解 开篇说明 此篇主要说明MyBatis Generato...
    JSON_NULL阅读 20,575评论 0 4
  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,422评论 0 4
  • 很快,我们就进入了第三周,这周我又有了很大的收获,诗的丰富多彩(单独发),还有我的挑战……都很精彩,让我们一起来看...
    橄榄树颢阅读 250评论 1 2
  • 在连续上7天班,累得神魂颠倒没有任何形象灰头土脸的挤着公交回家,我终于迎来了周一的休息日。关掉闹钟,可是依旧早上6...
    肥喵警长阅读 285评论 0 0