Spring Boot 中使用 tkMapper

打印 上一主题 下一主题

主题 644|帖子 644|积分 1932

说明:基于 MyBatis 有很多第三方功能插件,这些插件可以完成数据操作方法的封装、数据库逆向工程的生成等。
tkMapper 和 MyBatis-plus 都是基于 MyBatis 提供的第三方插件,功能类似,下面介绍 tkMapper 的使用。
简介

tkMapper 就是一个 MyBatis 插件,基于 MyBatis 提供很多工具,提高开发效率,主要有以下两个功能。

  • 提供针对单表通用的数据库操作方法
  • 逆向工程(根据数据表自动生成实体类、Dao 接口、Mapper 映射文件)
MyBatis 基础环境

tkMapper 的使用需要基于 MyBatis。

  • 创建 Spring Boot 项目,选中 Lombok、Spring Web、MyBatis Framework、MySQL Driver 依赖
  • application.yml 配置文件中配置相关信息
    1. spring:
    2.   datasource:
    3.     driver-class-name: com.mysql.jdbc.Driver
    4.     url: jdbc:mysql://localhost:3306/springdb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
    5.     username: root
    6.     password: luis
    7. mybatis:
    8.   type-aliases-package: com.luis.beans
    9.   mapper-locations: classpath:mappers/*Mapper.xml
    复制代码
    注意:配置后,手动创建 beans 和 mappers 文件夹
  • 创建 dao 文件夹,在启动类上添加 dao 的包扫描器 @MapperScan(basePackages = {"com.luis.dao"})
tkMapper 环境搭建


  • 添加依赖
    1. <dependency>
    2.     <groupId>tk.mybatis</groupId>
    3.     <artifactId>mapper-spring-boot-starter</artifactId>
    4.     <version>2.1.5</version>
    5. </dependency>
    复制代码
    如果自己在 maven 仓库中搜索,注意搜索关键词:mapper starter

    PS:添加后,注意手动刷新 pom
  • 更换启动类上 dao 包的包扫描器来源,不使用原先的 @MapperScan,要使用新添加的 tkMapper 的 @MapperScan
    1. import tk.mybatis.spring.annotation.MapperScan;
    2. @SpringBootApplication
    3. @MapperScan(basePackages = {"com.luis.dao"}) //使用tkMapper的包扫描器注解
    4. public class SpringbootTkMapperDemoApplication {
    5.     public static void main(String[] args) {
    6.         SpringApplication.run(SpringbootTkMapperDemoApplication.class, args);
    7.     }
    8. }
    复制代码
    PS:注意注解的包来源 import tk.mybatis.spring.annotation.MapperScan
  • 以上,tkMapper 环境已经搭建完成
tkMapper 对数据的通用操作

tkMapper 提供针对单表通用的数据库操作方法。
数据准备

1. 创建数据库表
  1. DROP TABLE IF EXISTS `users`;
  2. CREATE TABLE `users`  (
  3.   `user_id` int(11) NOT NULL AUTO_INCREMENT,
  4.   `user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  5.   `user_pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  6.   `user_realname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  7.   `user_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  8.   PRIMARY KEY (`user_id`) USING BTREE
  9. ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
复制代码
2. 创建实体类
  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. @Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系!
  5. public class User {
  6.     @Id //指定主键
  7.     private Integer userId;
  8.     private String userName;
  9.     private String userPwd;
  10.     private String userRealname;
  11.     private String userImg;
  12. }
复制代码
3. 创建 Dao 接口【重点】

注意:创建的 Dao 接口需要继承 tkMapper 中提供的 Mapper 和 MySqlMapper 两个接口,这两个接口提供了对单表的通用操作。
  1. public interface UserDao extends Mapper<User>, MySqlMapper<User> {
  2. }
复制代码
可选优化策略【建议使用】:
如果不想每次创建 dao 接口时都继承 tkMapper  中的两个接口,可以自己写一个通用的接口模板,只需要让这个通用的接口模板继承 tkMapper  中的两个接口,然后自己创建的 dao 接口只需要继承这个通用的接口模板即可!
但是,需要注意的是,这个通用的接口模板千万不能写在 dao 目录下!因为 dao 目录下的接口会被扫描到,有固定的功能用处;而我们自定义的通用接口模板只是为了继承,没有其他特殊功能!
使用示例:
1、可在 dao 目录同级创建 general 目录,在 general 目录下创建 GeneralDao 接口,并继承 tkMapper  中的两个接口。
  1. package com.luis.general;
  2. import tk.mybatis.mapper.common.Mapper;
  3. import tk.mybatis.mapper.common.MySqlMapper;
  4. /**
  5. * @Author: Luis
  6. * @date: 2022/11/9 14:39
  7. * @description: 自定义的通用接口模板
  8. */
  9. public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
  10. }
复制代码
2、创建 dao 接口,继承 GeneralDao 即可!
  1. public interface UserDao extends GeneralDao<User> {
  2. }
复制代码
4. 测试

添加 Junit 和 springboot test 两个测试依赖:
  1. <dependency>
  2.     <groupId>junit</groupId>
  3.     <artifactId>junit</artifactId>
  4.     <scope>test</scope>
  5. </dependency>
  6. <dependency>
  7.     <groupId>org.springframework.boot</groupId>
  8.     <artifactId>spring-boot-starter-test</artifactId>
  9. </dependency>
复制代码
写测试类进行测试:
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
  3. public class UserDaoTest {
  4.     @Autowired
  5.     private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
  6.     @Test
  7.     public void test() {
  8.         User user = new User();
  9.         user.setUserName("mike");
  10.         user.setUserPwd("123");
  11.         user.setUserRealname("zhangsan");
  12.         user.setUserImg("user/default.jpg");
  13.         int i = userDao.insert(user);
  14.         System.out.println("========> i = " + i);
  15.     }
  16. }
复制代码
tkMapper 常用方法之增删改


  • insert:普通添加
  • insertUseGeneratedKeys:可返回自增 id 的添加
  • updateByPrimaryKey:根据主键修改
  • deleteByPrimaryKey:根据主键删除
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
  3. public class UserDaoTest {
  4.     @Autowired
  5.     private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
  6.     @Test
  7.     public void testInsert() {
  8.         User user = new User();
  9.         user.setUserName("juno4");
  10.         user.setUserPwd("321");
  11.         user.setUserRealname("lin");
  12.         user.setUserImg("user/default.jpg");
  13.         /**
  14.          * insert: 添加(自增的id不会返回)
  15.          */
  16.         int i = userDao.insert(user);
  17.         System.out.println("========> i = " + i);
  18.         System.out.println(user.getUserId()); //null
  19.     }
  20.     @Test
  21.     public void testInsertUseGeneratedKeys() {
  22.         User user = new User();
  23.         user.setUserName("juno3");
  24.         user.setUserPwd("321");
  25.         user.setUserRealname("lin");
  26.         user.setUserImg("user/default.jpg");
  27.         /**
  28.          * insertUseGeneratedKeys: 添加(自增的id可以返回)
  29.          * 注意:
  30.          *  1. 数据库中主键字段需要设置为自增
  31.          *  2. 实体类中主键属性需要使用@Id注解指定;并且需要使用包装类型Integer,不要使用int
  32.          */
  33.         int i = userDao.insertUseGeneratedKeys(user);
  34.         System.out.println("========> i = " + i);
  35.         System.out.println(user.getUserId()); //10
  36.     }
  37.     @Test
  38.     public void testUpdateByPrimaryKey() {
  39.         User user = new User();
  40.         user.setUserId(10); //必须指定要修改的id
  41.         user.setUserName("juno new");
  42.         user.setUserPwd("000");
  43.         user.setUserRealname("lin new");
  44.         user.setUserImg("new.jpg");
  45.         /**
  46.          * updateByPrimaryKey:根据主键修改
  47.          */
  48.         int i = userDao.updateByPrimaryKey(user);
  49.         System.out.println("========> i = " + i);
  50.         System.out.println(user);
  51.     }
  52.     @Test
  53.     public void testDeleteByPrimaryKey() {
  54.         /**
  55.          * deleteByPrimaryKey:根据主键删除
  56.          */
  57.         int i = userDao.deleteByPrimaryKey(9);
  58.         System.out.println("========> i = " + i);
  59.     }
  60. }
复制代码
PS:其实还有根据自定义条件修改或删除的方法(使用方法参考带条件的查询示例)
tkMapper 常用方法之查询


  • selectAll:查所有
  • selectByPrimaryKey:根据主键查所有
  • selectByExample:根据条件查所有
  • selectByRowBounds:分页查询
  • selectByExampleAndRowBounds:带条件的分页查询
  • selectCount:查总记录数
  • selectCountByExample:根据条件查总记录数
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
  3. public class UserDaoTest {
  4.     @Autowired
  5.     private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
  6.     @Test
  7.     public void testSelectAll() {
  8.         /**
  9.          * selectAll:查询所有
  10.          */
  11.         List<User> users = userDao.selectAll();
  12.         for (User user : users) {
  13.             System.out.println(user);
  14.         }
  15.     }
  16.     @Test
  17.     public void testSelectByPrimaryKey() {
  18.         /**
  19.          * selectByPrimaryKey:根据主键查询
  20.          */
  21.         User user = userDao.selectByPrimaryKey(10);
  22.         System.out.println(user);
  23.     }
  24.     @Test
  25.     public void testSelectByExample() {
  26.         //封装查询条件
  27.         Example example = new Example(User.class);
  28.         Example.Criteria criteria = example.createCriteria();
  29.         //条件信息(根据Criteria对象的各种方法进行设置)
  30.         criteria.andEqualTo("userRealname", "lin");
  31.         // criteria.orEqualTo("userPwd", "123");
  32.         // criteria.andLike("userName", "%i%");
  33.         /**
  34.          * selectByPrimaryKey:根据条件查询(PS:根据条件修改或删除与此类似)
  35.          *      注意:需要设置查询条件信息,并传入条件对象
  36.          */
  37.         List<User> users = userDao.selectByExample(example);
  38.         for (User user : users) {
  39.             System.out.println("========> " + user);
  40.         }
  41.     }
  42.     @Test
  43.     public void testSelectByRowBounds() {
  44.         //分页查询信息
  45.         int pageNum = 2; //第几页
  46.         int pageSize = 3; //每页显示多少行
  47.         int start = (pageNum - 1) * pageSize; //起始显示的下标
  48.         RowBounds rowBounds = new RowBounds(start, pageSize);
  49.         /**
  50.          * selectByRowBounds:查所有的分页查询
  51.          */
  52.         List<User> users = userDao.selectByRowBounds(new User(), rowBounds);
  53.         for (User user : users) {
  54.             System.out.println("========> " + user);
  55.         }
  56.         /**
  57.          * selectCount:查询总记录数
  58.          */
  59.         int count = userDao.selectCount(new User());
  60.         System.out.println("========> count = " + count);
  61.     }
  62.     @Test
  63.     public void testSelectByExampleAndRowBounds() {
  64.         //封装查询条件
  65.         Example example = new Example(User.class);
  66.         Example.Criteria criteria = example.createCriteria();
  67.         criteria.andEqualTo("userRealname", "lin");
  68.         //分页查询信息
  69.         int pageNum = 2; //第几页
  70.         int pageSize = 2; //每页显示多少行
  71.         int start = (pageNum - 1) * pageSize; //起始显示的下标
  72.         RowBounds rowBounds = new RowBounds(start, pageSize);
  73.         /**
  74.          * selectByExampleAndRowBounds:带条件的分页查询
  75.          */
  76.         List<User> users = userDao.selectByExampleAndRowBounds(example, rowBounds);
  77.         for (User user : users) {
  78.             System.out.println("========> " + user);
  79.         }
  80.         /**
  81.          * selectCountByExample:根据条件查询总记录数
  82.          */
  83.         int count = userDao.selectCountByExample(example);
  84.         System.out.println("========> count = " + count);
  85.     }
  86. }
复制代码
tkMapper 关联/多表查询

说明:所有的关联/多表查询都可以由多个单表查询组成
关联/多表查询实现方式:
方式一:多次使用单表查询,然后封装数据
方式二:自定义查询方法和 SQL
情景:基于以上的用户表,新添加一个订单表 orders,订单表中有订单信息,但是也有用户 id;
要求:在查询用户表的同时还要查询出用户的订单信息,这就涉及到了两张表的查询。
具体业务要求:根据用户名查询用户的所有信息,包括订单信息。
数据准备

新建订单表 orders:
  1. DROP TABLE IF EXISTS `orders`;
  2. CREATE TABLE `orders`  (
  3.   `order_id` int(11) NOT NULL AUTO_INCREMENT,
  4.   `user_id` int(11) NOT NULL,
  5.   `receiver_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  6.   `receiver_mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  7.   `receiver_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  8.   PRIMARY KEY (`order_id`) USING BTREE
  9. ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
  10. INSERT INTO `orders` VALUES (1, 1, 'luis', '13344445555', '湖北武汉');
复制代码
新建实体类 Order:
  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. @Table(name = "orders")
  5. public class Order {
  6.     @Id
  7.     private Integer orderId;
  8.     private Integer userId;
  9.     private String receiverName;
  10.     private String receiverMobile;
  11.     private String receiverAddress;
  12. }
复制代码
新建 dao 接口:
注意,此处 dao 接口继承的是自定义的通用接口模板,相关说明参见之前创建示例 UserDao 的步骤。
也可以直接继承 tkMapper 的两个接口。(注意灵活运用!)
  1. public interface OrderDao extends GeneralDao<Order> {
  2. }
复制代码
说明:进行关联/多表查询前,需要修改下之前的 User 实体类,在实体类中需要添加一个订单的字段,以便查询出用户所关联的订单信息。
  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. @Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系!
  5. public class User {
  6.     @Id //指定主键
  7.     private Integer userId;
  8.     private String userName;
  9.     private String userPwd;
  10.     private String userRealname;
  11.     private String userImg;
  12.    
  13.     //订单
  14.     private List<Order> orderList;
  15. }
复制代码
方式一:多次单表查询
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
  3. public class UserDaoTest {
  4.     @Autowired
  5.     private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
  6.     @Autowired
  7.     private OrderDao orderDao;
  8.     @Test
  9.     public void test() {
  10.         //根据用户名查询用户信息
  11.         Example example = new Example(User.class);
  12.         Example.Criteria criteria = example.createCriteria();
  13.         criteria.andEqualTo("userName", "luis");
  14.         //条件查询
  15.         List<User> users = userDao.selectByExample(example);
  16.         User user = users.get(0);
  17.         //根据用户id查询订单信息
  18.         Example example1 = new Example(Order.class);
  19.         Example.Criteria criteria1 = example.createCriteria();
  20.         criteria.andEqualTo("userId", user.getUserId());
  21.         //条件查询
  22.         List<Order> orders = orderDao.selectByExample(example1);
  23.         //将查询到的订单信息设置到user中
  24.         user.setOrderList(orders);
  25.         System.out.println("========> " + user);
  26.     }
  27. }   
复制代码
方式二:自定义连接查询


  • UserDao 接口中新建查询方法
    1. public interface UserDao extends GeneralDao<User> {
    2.     public User selectByUserName(String userName);
    3. }
    复制代码
  • mappers 目录下创建对应的 UserMapper.xml 文件,自定义查询 SQL
    1. <?xml version="1.0" encoding="UTF-8" ?>
    2. <!DOCTYPE mapper
    3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="com.luis.dao.UserDao">
    6.    
    7.     <resultMap id="userMap" type="com.luis.beans.User">
    8.         <id column="user_id" property="userId"/>
    9.         <result column="user_name" property="userName"/>
    10.         <result column="user_pwd" property="userPwd"/>
    11.         <result column="user_realname" property="userRealname"/>
    12.         <result column="user_img" property="userImg"/>
    13.         <collection property="orderList" ofType="com.luis.beans.Order">
    14.             <id column="order_id" property="orderId"/>
    15.             <result column="user_id" property="userId"/>
    16.             <result column="receiver_name" property="receiverName"/>
    17.             <result column="receiver_mobile" property="receiverMobile"/>
    18.             <result column="receiver_address" property="receiverAddress"/>
    19.         </collection>
    20.     </resultMap>
    21.     <select id="selectByUserName" resultMap="userMap">
    22.         select u.user_id,u.user_name,u.user_pwd,u.user_realname,u.user_img,
    23.                o.order_id,o.user_id,o.receiver_name,o.receiver_mobile,o.receiver_address
    24.         from users u inner join orders o
    25.         on u.user_id = o.user_id;
    26.   </select>
    27. </mapper>
    复制代码
  • 测试
    1. @RunWith(SpringRunner.class)
    2. @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
    3. public class UserDaoTest {
    4.     @Autowired
    5.     private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
    6.     @Autowired
    7.     private OrderDao orderDao;
    8.     @Test
    9.     public void test02() {
    10.         //使用自定义的查询方法
    11.         User user = userDao.selectByUserName("luis");
    12.         System.out.println("========> " + user);
    13.     }
    14. }   
    复制代码
逆向工程

所谓逆向工程,就是通过数据库表,来自动生成实体类、dao 接口和 mapper 文件。
需要注意的是,本逆向工程是最好配合 tkMapper 环境使用,因为,有一些配置和 tkMapper 相关,如生成的 dao 接口会继承自定义的通用接口模板,而该通用的接口模板就是继承了 tkMapper 中的两个接口,从而才能使用 tkMapper 提供的通用数据操作方法;还有,生成的实体类上的注解需要依赖 tkMapper 环境。
重要说明:本逆向工程使用的 mysql 版本是低版本 5.1.36!经测试,如果使用高版本如 8.xxx,很大概率会生成有问题!所以建议项目中统一使用低版本的 MySQL。

  • 在 pom.xml 中 build 的 plugins 下添加下列生成器插件
    1. <plugin>
    2.     <groupId>org.mybatis.generator</groupId>
    3.     <artifactId>mybatis-generator-maven-plugin</artifactId>
    4.     <version>1.3.6</version>
    5.    
    6.     <configuration>
    7.         <configurationFile>
    8.             ${basedir}/src/main/resources/generator/GeneratorConfig.xml
    9.         </configurationFile>
    10.     </configuration>
    11.    
    12.     <dependencies>
    13.         
    14.         <dependency>
    15.             <groupId>mysql</groupId>
    16.             <artifactId>mysql-connector-java</artifactId>
    17.             <version>5.1.36</version>
    18.         </dependency>
    19.         
    20.         <dependency>
    21.             <groupId>tk.mybatis</groupId>
    22.             <artifactId>mapper</artifactId>
    23.             <version>4.1.5</version>
    24.         </dependency>
    25.     </dependencies>
    26. </plugin>
    复制代码
    注意:推荐直接复制,但如果想自己在 maven 仓库中搜索,注意关键词:mybatis-generator-maven-plugin,并且,千万注意,你搜索到的肯定是依赖,而并非插件!此时,你只需要复制依赖的 gav 坐标,自己在 pom 中创建空 plugin 标签,将 gav 坐标复制进去即可!(如果相关依赖刷新添加失败,可以复制到 dependences 下,重新刷新添加试试,添加成功后复制回来即可)
  • 注意查看项目中是否自定义有通用接口模板 GeneralDao,使其继承 tkMapper 的两个接口;如果没有,则在 dao 同级目录,创建 general 目录,在 general 目录下创建自定义通用接口模板 GeneralDao,继承 tkMapper 的两个接口;
    1. public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
    2. }
    复制代码
  • 在 resources/generator 下添加 GeneratorConfig.xml 生成器配置(创建并复制后改主要配置即可)
    主要需要配置:配置数据库连接、配置实体类存放路径、配置 XML 存放路径、配置 DAO 存放路径、配置 GeneralDao
    注意:默认配置是生成指定数据库中所有表,也可以自定义的指定只生成哪些表
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <!DOCTYPE generatorConfiguration
    3.         PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
    4.         "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    5. <generatorConfiguration>
    6.    
    7.     <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
    8.         <property name="beginningDelimiter" value="`"/>
    9.         <property name="endingDelimiter" value="`"/>
    10.         
    11.         <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
    12.             <property name="mappers" value="com.luis.general.GeneralDao"/>
    13.         </plugin>
    14.         
    15.         <jdbcConnection driver
    16.                 connectionURL="jdbc:mysql://localhost:3306/springdb?serverTimezone=UTC"
    17.                 userId="root" password="luis">
    18.         </jdbcConnection>
    19.         
    20.         <javaModelGenerator targetPackage="com.luis.beans" targetProject="src/main/java"/>
    21.         
    22.         <sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/>
    23.         
    24.         <javaClientGenerator targetPackage="com.luis.dao" targetProject="src/main/java" type="XMLMAPPER"/>
    25.         
    26.         <table tableName="%">
    27.             
    28.         </table>
    29.     </context>
    30. </generatorConfiguration>
    复制代码
  • 打开 IDEA 右侧 Maven 窗口,找到项目--》Plugins--》mybatis-generator--》mybatis-generator:generate,双击执行逆向生成即可!
    示例图:

  • 查看 beans、dao、mappers 目录下的生成情况,看生成的相关接口是否符合开发要求,根据情况可做相关修改,然后进行相关测试。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表