IDEA项目实践——创建Java项目以及创建Maven项目案例、使用数据库连接池创建项目简介
IDEWA项目实践——mybatis的一些基本原理以及案例
IDEA项目实践——动态SQL、关系映射、注解开发
IDEA创建项目的操作步骤以及在虚拟机里面创建Scala的项目简单介绍_intellij 创建scala
文章目录
系列文章目录
前言
一 动态SQL
1.1 动态SQL概述
1.2 if元素
1.3 where 、set 、trim元素
1.3.1 where元素
1.3.2 set 元素
1.3.3 trim 元素
1.元素模拟元素
2. 元素模拟元素
1.4 choose 、when 、 otherwise 元素
1.5 foreach元素
foreach标签
1.6 bind 元素
二 关系映射
2.1 关联关系概述
2.2 一对一级联查询
2.2.1 准备工作(依赖和工具类)
2.2.2 创建数据库的表与实体类
2.2.3 编写MyBatis配置文件与数据库配置文件
2.2.4 创建Mapper接口与映射文件
2.2.5 创建测试类
2.3 一对多级联查询
2.3.1 准备工作(依赖和工具类)
2.3.2 创建实体类和表
2.3.3 编写MyBatis配置文件与数据库配置文件
2.3.4 创建Mapper接口与映射文件
2.3.5 创建测试类
2.4 多对多级联查询
2.4.1 准备工作(依赖和工具类)
2.4.2 创建实体类和表
2.4.3 编写MyBatis配置文件与数据库配置文件
2.4.4 创建Mapper接口与映射文件
2.4.5 创建测试类
2.5 三种关联映射总结
三 注解开发
3.1 注解开发概述
3.2 案例的实现步骤
3.2.1 导入依赖和工具类
3.2.2 创建MyBatis配置文件和数据库配置文件
3.2.3 创建实体类
3.2.4 创建StudentMapper接口
3.2.5 编写测试类
总结
本文主要介绍MyBatis当中的动态SQL、关系映射、注解开发,以及相关的案例讲解。
动态SQL,即通过MyBatis 提供的各种标签对条件作出判断已实现动态拼接SQL语句。条件判断使用的表达式为OGNL表达式。
在项目开发中,动态SQL可以解决很多不确定因素导致的SQL语句不同的问题。动态SQL可以简单高效的进行编码。
注意事项
在mapper的动态SQL中如出现大于号,小于号,大于等于号,小于等于号,最好将其转换为实体符号,否则,XML可能会出现解析出错问题,特别是小于号 (<),在XML中绝对不能出现 ,否则一定出错
官方文档:mybatis – MyBatis 3 | 动态 SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
动态SQL是MyBatis提供的拼接SQL语句的强大机制。
元素 | 说明 |
---|---|
判断某个条件是否符合,符合则拼接此SQL语句 | |
判断多个条件是否符合,符合则拼接此SQL语句 | |
限定语句,用于限制SQL语句的格式 | |
循环语句,用于循环拼接SQL语句 | |
命名元素,用于创建一个变量,以便后续重复使用 |
不确定多条件查询—— if、where 标签
- if 标签:条件判断
- test 属性:逻辑表达式
- where 标签
- 作用:
- 替换where关键字
- 会动态的去掉第一个条件前的 and
- 如果所有的参数没有值则不加where关键字
- 注意:需要给每个条件前都加上 and 关键字
示例:
select * from tb_user where name = #{name} and age = #{age}
如果name属性与age属性有其中一个为空时,查询语句就会报错,为解决此问题,需要判断name与age属性是否为空,如果为空则不附加对应的筛选条件。利用
使用Junit单元测试,同时通过日志,测试各种情况。
以下为小的模块讲解
此处的if里面的判断条件,可以多写个and,需要在where条件里面补充1=1恒等式解决只输入性别SQL语句错误的情况。
对1.2 里面的if元素那块代码的一种优化方法
update tb_user
name = #{name},
age = #{age},
where id = #{id}
两个字段之间使用逗号隔开,判断条件并不是书写的最后一个,通过set动态的删除最后设置的那个逗号。
通过
update tb_user
name = #{name},
age = #{age},
where id = #{id}
通过
不确定单个条件查询——choose (when, otherwise) 标签
查询到的数据作为集合返回
循环里面传进去的参数为集合
映射文件传参的时候,单个是任意的字符可能会找不到,通过添加注解@param("list") 获取
如果为string类型,也需要加入注解@param("keyword")
oreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值
foreach 标签:用来迭代任何可迭代的对象(如数组,集合)。
表与表之间的关系可以分为三种,分别为"一对一",“一对多"和“多对多”。
在"一对一”的关系中:A表中的一条数据只能与B表中的一条数据关联,反过来同样成立,比如学生卡与学生。
在”一对多”"的关系中,A表中的一条数据可以与B表中多条数据关联,但是B表中的每个数据都只能有A表中的一条记录对应。比如班级和学生,每个班级对应多个学生,但是每个学生只能对应一个班级。
在"多对多"的关系中,A表中的一条数据可以与B表中的多条数据关联,B表中的每个数据可以与A表中的多条记录对应。比如老师和学生,一个学生可以对应多个老师,一个老师也可以对应多个学生。
【关联映射:本质上是告诉你多表查询的字段,如何映射到实体类的属性上。】
案例实现步骤
pom.xml:
4.0.0
com.ambow
mybatis07
1.0-SNAPSHOT
8
8
1.8
org.mybatis
mybatis
3.4.6
mysql
mysql-connector-java
5.1.6
org.projectlombok
lombok
1.18.24
junit
junit
4.12
test
src/main/java
**/*.xml
定义一个MyBatisUtil工具类:
package com.ambow.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisUtil {
private static SqlSessionFactoryBuilder builder;
private static SqlSessionFactory sqlSessionFactory;
//静态代码块 - 类加载的时候,只执行一次
static {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
//获取SqlSessionFactory - 工厂对象
builder = new SqlSessionFactoryBuilder();
System.out.println(builder);
sqlSessionFactory = builder.build(inputStream);
System.out.println(sqlSessionFactory);
}
//获取SqlSession
public static SqlSession getSqlSession(){
//获取SqlSession - 连接对象
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
}
//关闭SqlSession
public static void closeSqlSession(SqlSession session){
if (session != null) {
session.close();
}
}
}
创建表和实体类
card表的建表语句:
-- ----------------------------
-- Table structure for card
-- ----------------------------
DROP TABLE IF EXISTS `card`;
CREATE TABLE `card` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`card_number` int(11) DEFAULT NULL,
`sid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of card
-- ----------------------------
INSERT INTO `card` VALUES ('1', '178283992', '3');
INSERT INTO `card` VALUES ('2', '123624573', '2');
INSERT INTO `card` VALUES ('3', '234122212', '1');
student表的建表语句:
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`cid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张三', '3');
INSERT INTO `student` VALUES ('2', '李四', '2');
INSERT INTO `student` VALUES ('3', '王五', '1');
Card类:
package com.ambow.pojo;
import lombok.Data;
@Data
public class Card {
Integer id;
String cardNumber;
}
Student类:
package com.ambow.pojo;
import lombok.Data;
@Data
public class Student {
Integer id;
String name;
Card card; //每个学生都有一个学生卡 card
//Integer cid;
}
mybatis-config.xml:
jdbc.properties:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
username=root
password=root
StudentMapper接口:
package com.ambow.mapper;
import com.ambow.pojo.Student;
import java.util.List;
public interface StudentMapper {
/*查询*/
List selectStudent();
}
StudentMapper.xml:
package com.ambow.test;
import com.ambow.mapper.StudentMapper;
import com.ambow.pojo.Student;
import com.ambow.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class AssociateTest {
@Test
public void test01(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List students = mapper.selectStudent();
for (Student student : students) {
System.out.println(student);
}
sqlSession.close();
}
}
案例实现步骤
pom.xml:
同上一案例MyBatisUtil:
同上一案例
MyClass类:
package com.ambow.pojo;
import lombok.Data;
import java.util.List;
@Data
public class MyClass {
Integer id;
String className;
List student;
}
Student类:
package com.ambow.pojo;
import lombok.Data;
@Data
public class Student {
Integer id;
String name;
}
myclass表的建表语句:
-- ----------------------------
-- Table structure for myclass
-- ----------------------------
DROP TABLE IF EXISTS `myclass`;
CREATE TABLE `myclass` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`class_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of myclass
-- ----------------------------
INSERT INTO `myclass` VALUES ('1', '一班');
INSERT INTO `myclass` VALUES ('2', '二班');
INSERT INTO `myclass` VALUES ('3', '三班');
student表的建表语句:
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`cid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张三', '1');
INSERT INTO `student` VALUES ('2', '李四', '2');
INSERT INTO `student` VALUES ('3', '王五', '1');
INSERT INTO `student` VALUES ('4', '赵六', '3');
INSERT INTO `student` VALUES ('5', '蜀七', '1');
INSERT INTO `student` VALUES ('6', '魏八', '3');
mybatis-config.xml:
同上一案例
jdbc.properties:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
username=root
password=root
MyClassMapper接口:
package com.ambow.mapper;
import com.ambow.pojo.MyClass;
import java.util.List;
public interface MyClassMapper {
/*查询*/
List selectMyClass();
}
MyClassMapper.xml:
package com.ambow.test;
import com.ambow.mapper.MyClassMapper;
import com.ambow.pojo.MyClass;
import com.ambow.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class CollectionTest {
@Test
public void test01(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
MyClassMapper mapper = sqlSession.getMapper(MyClassMapper.class);
List myClasses = mapper.selectMyClass();
for (MyClass myClass : myClasses) {
System.out.println(myClass);
}
sqlSession.close();
}
}
案例实现步骤
pom.xml:
同上一案例MyBatisUtil:
同上一案例
Student类:
package com.ambow.pojo;
import lombok.Data;
import java.util.List;
@Data
public class Student {
Integer id;
String name;
List teachers;
}
Teacher类:
package com.ambow.pojo;
import lombok.Data;
import java.util.List;
@Data
public class Teacher {
Integer id;
String courseName;
String name;
List students;
}
student表的建表语句:
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '张三');
INSERT INTO `student` VALUES ('2', '李四');
INSERT INTO `student` VALUES ('3', '王五');
teacher表的建表语句:
-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`course_name` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES ('1', '语文', '刘伟');
INSERT INTO `teacher` VALUES ('2', '语文', '张帅');
INSERT INTO `teacher` VALUES ('3', '数学', '赵凯');
INSERT INTO `teacher` VALUES ('4', '英语', '刘波');
INSERT INTO `teacher` VALUES ('5', '英语', '英丽');
student_teacher表的建表语句:
-- ----------------------------
-- Table structure for student_teacher
-- ----------------------------
DROP TABLE IF EXISTS `student_teacher`;
CREATE TABLE `student_teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`t_id` int(11) DEFAULT NULL,
`s_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student_teacher
-- ----------------------------
INSERT INTO `student_teacher` VALUES ('1', '1', '1');
INSERT INTO `student_teacher` VALUES ('2', '3', '1');
INSERT INTO `student_teacher` VALUES ('3', '5', '1');
INSERT INTO `student_teacher` VALUES ('4', '2', '2');
INSERT INTO `student_teacher` VALUES ('5', '3', '2');
INSERT INTO `student_teacher` VALUES ('6', '4', '2');
INSERT INTO `student_teacher` VALUES ('7', '1', '3');
INSERT INTO `student_teacher` VALUES ('8', '3', '3');
INSERT INTO `student_teacher` VALUES ('9', '4', '3');
mybatis-config.xml:
同上一案例
jdbc.properties:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
username=root
password=root
StudentMapper接口:
package com.ambow.mapper;
import com.ambow.pojo.Student;
import java.util.List;
public interface StudentMapper {
/*查询*/
List selectStudent();
}
StudentMapper.xml:
package com.ambow.test;
import com.ambow.mapper.StudentMapper;
import com.ambow.pojo.Student;
import com.ambow.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class CollectionTest {
@Test
public void test01(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List students = mapper.selectStudent();
for (Student student : students) {
System.out.println(student);
}
sqlSession.close();
}
}
三种关联映射的实体类创建是不同,对应的查询条件是不一样的。
对于一对一关系,使用的是下面这一段,需要用到association和javatype来编写。
对于一对多和多对多他们两者采用的是下面的这一段,使用的是collection和oftype来书写。
这是两者的区别。
还有一点在于创建实体类的时候,不同的对应关系创建的实体类是不同的,编写代码时要注意这两点区别与不同。
在MyBatis当中,除了XML映射文件创建SQL语句的方式,还可以通过注解直接编写SQL语句。使用注解开发时,无需创建映射文件,直接在Mapper接口文件的方法上通过注解编写SQL语句即可。MyBatis提供了若干注解来支持注解开发。
注解 | 说明 |
---|---|
@Select | 查询操作注解 |
@Insert | 插入操作注解 |
@Update | 更新操作注解 |
@Delete | 删除操作注解 |
@Param | 标注传入参数名称 |
在注解开发中,将注解直接放在Mapper接口文件的方法上,代表此方法对应的操作。
使用@Select注解完成查询功能的编写,查询的SQL语句直接写在注解中,其他注解,如修改、增加和删除注解,使用方法与@Select注解相同。
向SQL语句中传参的方式有三种:
传入对象:SQL语句通过对象中的属性名取值;
传入Map集合:SQL语句通过Map集合中的键来取值;
传入基本数据类型的参数,并通过@Param注解标注参数名:SQL语句通过@Param注解标注的参数名来取值;
只有一个参数的时候:sql语句在取值的时候,参数名可以任意
如果有两个参数,则参数的默认命名规则,如下:
默认参数名:arg0,arg1,...
默认参数名:param1,param2,...
在此需要注意的是,MyBatis注解开发除了简单的增删改查外,还有一对多,多对多等级联查询的映射方法,因为一对多,多对多等问题需要复杂的配置,一般使用XML映射文件编写,在实际开发中,SQL语句比较复杂时,一般将注解方式与XML方式混合使用,复杂SQL使用XML映射文件编写,简单SQL使用注解开发。
总结:
简单SQL使用注解开发
复杂SQL使用XML映射文件编写
pom.xml:
8
8
1.8
org.mybatis
mybatis
3.4.6
mysql
mysql-connector-java
5.1.6
org.projectlombok
lombok
1.18.24
junit
junit
4.12
test
src/main/java
**/*.xml
工具类:
package com.ambow.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisUtil {
private static SqlSessionFactoryBuilder builder;
private static SqlSessionFactory sqlSessionFactory;
//静态代码块 - 类加载的时候,只执行一次
static {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
//获取SqlSessionFactory - 工厂对象
builder = new SqlSessionFactoryBuilder();
System.out.println(builder);
sqlSessionFactory = builder.build(inputStream);
System.out.println(sqlSessionFactory);
}
//获取SqlSession
public static SqlSession getSqlSession(){
//获取SqlSession - 连接对象
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
}
//关闭SqlSession
public static void closeSqlSession(SqlSession session){
if (session != null) {
session.close();
}
}
}
mybatis-config.xml
jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test3
username=root
password=root
package com.ambow.pojo;
import lombok.Data;
@Data
public class Student {
Integer id;
String name;
}
package com.ambow.dao;
import com.ambow.pojo.Student;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;
public interface StudentMapper {
/*查询*/
@Select("select * from student")
List getAllStudent();
/*查询单个记录*/
/*
只有一个参数的时候:sql语句在取值的时候,参数名可以任意
*/
@Select("select * from student where id = #{testId}")
Student getStudentById(int testId);
//@Select("select * from student where id = #{id}")
//Student getStudentById(@Param("id") int testId);
/*新增*/
@Insert("insert into student (name) values(#{name})")
int addStudent(Student student);
/*修改*/
/*
如果有两个参数,则参数的默认命名规则,如下:
默认参数名:arg0,arg1,...
默认参数名:param1,param2,...
*/
//@Update("update student set name = #{arg1} where id = #{arg0}")
//@Update("update student set name = #{param2} where id = #{param1}")
//int updateStudent(int id,String name);
@Update("update student set name = #{name} where id = #{id}")
//int updateStudent(@Param("id") int id,@Param("name") String name);
int updateStudent(Map map);
/*删除*/
@Delete("delete from student where id = #{id}")
int deleteStudent(@Param("id") int id);
}
package com.ambow.test;
import com.ambow.dao.StudentMapper;
import com.ambow.pojo.Student;
import com.ambow.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
public class AnnotationTest {
@Test
public void test01(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List students = mapper.getAllStudent();
for (Student student : students) {
System.out.println(student);
}
sqlSession.close();
}
@Test
public void test02(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.getStudentById(1);
System.out.println(student);
sqlSession.close();
}
@Test
public void test03(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = new Student();
student.setName("Tom");
mapper.addStudent(student);
sqlSession.commit();
sqlSession.close();
}
@Test
public void test04(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//mapper.updateStudent(5,"Tom");
HashMap map = new HashMap();
map.put("id",3);
map.put("name","Cat");
mapper.updateStudent(map);
sqlSession.commit();
sqlSession.close();
}
@Test
public void test05(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
mapper.deleteStudent(5);
sqlSession.commit();
sqlSession.close();
}
}
以上就是今天的内容~
欢迎大家点赞,收藏⭐,转发,
如有问题、建议,请您在评论区留言哦。
最后:转载请注明出处!!!