目录

1、mybatis框架概述

2、直接使用jdbc连接数据库带来的问题

3、mybatis连接池

3.1、mybatis连接池yml配置

3.2、mybatis连接池xml配置

4、一个简单的mybatis框架demo(XML配置)

4.1、maven项目目录结构如下:

4.2、代码

4.3、mybatis代码架构分析

5、一个简单的mybatis框架demo(annotation配置)

5.1、maven项目目录结构如下

5.2、mybatis注解使用

6、mybatis总结

7、参考资料


文章中所涉及的代码源码下载地址:https://gitee.com/wulinchun/ssm-learning.git

1、mybatis框架概述

mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注sql 语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。 mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行sql 并将结果映射为 java 对象并返回。 采用ORM思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。 为了我们能够更好掌握框架运行的内部过程,并且有更好的体验,下面我们将从自定义 Mybatis 框架开始来 学习框架。此时我们将会体验框架从无到有的过程体验,也能够很好的综合前面阶段所学的基础。

2、直接使用jdbc连接数据库带来的问题

  1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
  2. Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。
  3. 使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。
  4. 对结果集解析存在硬编码(查询列名),sql 变化导致解析代码变化,系统不易维护,如果能将数据库记 录封装成 pojo 对象解析比较方便。

(projo对象就是简单的java对象,可以理解为实体类与数据库中表一一映射的对象,可以参考https://blog.csdn.net/kobexiaol/article/details/78195856

3、mybatis连接池

连接池就是用于存储连接对象的一个容器。而容器就是一个集合,且必须是线程安全的,即两个线程不能拿到同一个连接对象。同时还要具备队列的特性:先进先出原则。

   使用连接池的好处:避免频繁创建和关闭数据库连接造成的开销,节省系统资源。

3.1、mybatis连接池yml配置

server:
port: 8080
spring:
datasource:
name: erp
url: jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Hongkong
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml #注意:一定要对应mapper映射xml文件的所在路径
type-aliases-package: com.mybatis_demo.domain # 注意:对应实体类的路径jetbrains://idea/navigate/reference?project=DataBase_conn&fqn=com.example.demo.Entity

3.2、mybatis连接池xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- mybatis的主配置文件 -->
<configuration> <properties url="file:///C:/Users/Administrator/Desktop/ssm框架/mybatis_demo/src/main/resources/jdbcConfig.properties">
</properties>
<!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
<typeAliases>
<!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
<package name="com.mybatis_demo.domain"></package>
</typeAliases>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments> <!-- 配置映射文件位置 -->
<mappers>
<package name="com.mybatis_demo.dao"></package>
</mappers>
</configuration>

4、一个简单的mybatis框架demo(XML配置)

建立一个maven工程

eclipse配置maven可参考 https://blog.csdn.net/wcc27857285/article/details/81812304

eclipse建立maven工程可参考 https://jingyan.baidu.com/article/2fb0ba40a2b22b00f2ec5faf.html

4.1、maven项目目录结构如下:

4.2、代码

IUserDao.java

package com.mybatis_demo.dao;

import com.mybatis_demo.domain.User;

import java.util.List;

/**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:13
*/ public interface IUserDao {
/**
*查询所有
* @return
*/
List<User> findAll(); /**
* 根据id查询
* @param id
* @return
*/
List<User> findByUid(Integer uid); /**
* 根据name模糊查询
* @param userName
* @return
*/
List<User> findByName(String userName); /**
* 根据id删除
* @param id
* @return
*/
int deleteUser(Integer uid); /**
* 添加
* @param user
* @return
*/
int saveUser(User user); /**
* 修改
* @param user
* @return
*/
int updateUser(User user);
}

User.java

package com.mybatis_demo.domain;

import java.io.Serializable;
import java.sql.Date; /**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:08
*/ public class User implements Serializable {
private Integer uid;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress; public User() {
} public User(Integer uid, String userName, Date userBirthday, String userSex, String userAddress) {
this.uid = uid;
this.userName = userName;
this.userBirthday = userBirthday;
this.userSex = userSex;
this.userAddress = userAddress;
} public Integer getUid() {
return uid;
} public void setUid(Integer uid) {
this.uid = uid;
} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public Date getUserBirthday() {
return userBirthday;
} public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
} public String getUserSex() {
return userSex;
} public void setUserSex(String userSex) {
this.userSex = userSex;
} public String getUserAddress() {
return userAddress;
} public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
} @Override
public String toString() {
return "User{" +
"uid=" + uid +
", userName='" + userName + '\'' +
", userBirthday=" + userBirthday +
", userSex='" + userSex + '\'' +
", userAddress='" + userAddress + '\'' +
'}';
}
}

IUserDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis_demo.dao.IUserDao"> <!-- 配置 查询结果的列名和实体类的属性名的对应关系 -->
<resultMap id="userMap" type="com.mybatis_demo.domain.User">
<!--property是实体类中的字段,column是数据库表中相应列名 -->
<!-- 主键字段的对应 -->
<id property="uid" column="id"></id>
<!--非主键字段的对应 -->
<result property="userName" column="username"></result>
<result property="userAddress" column="address"></result>
<result property="userSex" column="sex"></result>
<result property="userBirthday" column="birthday"></result>
</resultMap>
<!--配置查询所有 -->
<!-- <select id="findAll" resultType="com.mybatis_demo.domain.User"> select
* from user </select> -->
<select id="findAll" resultMap="userMap">
select id ,username ,address ,sex ,birthday from user;
/*select * from user*/
</select> <!-- 保存用户 -->
<insert id="saveUser" parameterType="user">
insert into
user(id,username,address,sex,birthday)values(#{uid},#{userName},#{userAddress},#{userSex},#{userBirthday})
</insert> <!--删除用户 -->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{uid}
</delete> <!--根据uid查询用户 -->
<select id="findByUid" parameterType="java.lang.Integer"
resultMap="userMap">
select * from user where id=#{uid}
</select> <!--根据userName模糊查询 -->
<select id="findByName" parameterType="String"
resultMap="userMap">
select * from user where username like #{userName}
</select> <update id="updateUser"
parameterType="user">
update user set username=#{userName},address=#{userAddress},sex=#{userSex},birthday=#{userBirthday} where id=#{uid}
</update>
</mapper>

IUserDao.xml中的映射配置需要注意!!!

jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
#mysql5.7以下版本,则可以直接这样写
#jdbc.url=jdbc:mysql://localhost:3306/ssm
#注意url这里,如果是mysql5.7及以上的要在后面设置useUnicode=true&characterEncoding=UTF-8
#否则会出现中文显示?
jdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456

SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- mybatis的主配置文件 -->
<configuration>
<!-- 配置properties
可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
resource属性: 常用的
用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
url属性:
是要求按照Url的写法来写地址
URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
它的写法:
http://localhost:8080/mybatisserver/demo1Servlet
协议 主机 端口 URI URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
--> <properties url="file:///C:/Users/Administrator/Desktop/ssm框架/mybatis_demo/src/main/resources/jdbcConfig.properties">
</properties>
<!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
<typeAliases>
<!-- 用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
<package name="com.mybatis_demo.domain"></package>
</typeAliases>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments> <!-- 配置映射文件位置 -->
<mappers>
<package name="com.mybatis_demo.dao"></package>
</mappers>
</configuration>

MybatisTest.java

package com.mybatis_demo.test;

import com.mybatis_demo.dao.IUserDao;
import com.mybatis_demo.domain.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test; import java.io.InputStream;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List; /**
* @description:
* @author: wu linchun
* @time: 2020/12/30 22:25
*/ public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private IUserDao userDao;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); @Before//用于在测试方法执行之前执行
public void init() throws Exception {
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.获取SqlSession对象
sqlSession = factory.openSession();
//4.获取dao的代理对象
userDao = sqlSession.getMapper(IUserDao.class);
} @After//用于在测试方法执行之后执行
public void destroy() throws Exception {
//提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
} /**
* 测试查询所有
*/
@Test
public void testFindAll(){
List<User> userList = userDao.findAll();
for(User user : userList){
System.out.println(user);
}
} /**
* 测试添加用户
* @throws ParseException
*/
@Test
public void testSaveUser() throws ParseException {
java.util.Date bir=sdf.parse("2020-01-04");
java.sql.Date bir_sql=new java.sql.Date(bir.getTime());
User user=new User(11,"test11", bir_sql,"男","testAddress");
userDao.saveUser(user);
} /**
* 测试删除用户
*/
@Test
public void testDeleteUser(){
userDao.deleteUser(7);
} /**
* 测试根据uid查找
*/
@Test
public void testFindByUid(){
List<User> userList = userDao.findByUid(6);
for(User user : userList){
System.out.println(user);
} } /**
* 测试根据userName模糊查询
*/
@Test
public void testFindByName(){
List<User> userList=userDao.findByName("%t%");
for(User user : userList){
System.out.println(user);
}
} /**
* 测试修改
* @throws ParseException
*/
@Test
public void testUpdateUser() throws ParseException {
java.util.Date bir=sdf.parse("2020-01-04");
java.sql.Date bir_sql=new java.sql.Date(bir.getTime());
User user=new User(5,"test5",bir_sql,"男","testAddress");
userDao.updateUser(user);
} /**
* 入门案例
* @param args
*/
/*public static void main(String[] args) throws Exception {
//1.读取配置文件D:\学习资料\后端\ssm代码\mybatis_demo\src\main\resources\SqlMapConfig.xml
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}*/
}

4.3、mybatis代码架构分析

5、一个简单的mybatis框架demo(annotation配置)

5.1、maven项目目录结构如下

5.2、mybatis注解使用

IUserDao.java

package com.mybatis_demo_ann.dao;

import com.mybatis_demo_ann.domain.User;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import java.util.List; /**
* @description:
* @author: wu linchun
* @time: 2020/12/29 23:08
*/
public interface IUserDao { /**
* 查询所有操作
*
* @return
*/
@Select("select * from user")
//映射转换,将实体类中的字段与数据库表的列名一一对应起来
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
List<User> findAll(); /**
* 插入操作
* @param user
* @return
*/
@Insert("insert into user (id,username,birthday,sex,address) values (#{uid},#{userName},#{userBirthday},#{userSex},#{userAddress})")
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
int saveUser(User user); /**
* 更新操作
* @param user
* @return
*/
@Update("update user set username=#{userName},birthday=#{userBirthday},sex=#{userSex},address=#{userAddress} where id=#{uid}")
@Results(id = "userMap", value = {
// id字段默认为false,表示不是主键
// column表示数据库表字段,property表示实体类属性名。
@Result(id = true, column = "id", property = "uid"), @Result(column = "username", property = "userName"),
@Result(column = "birthday", property = "userBirthday"), @Result(column = "sex", property = "userSex"),
@Result(column = "address", property = "userAddress"), })
int updateUser(User user); /**
* 模糊查询
* @param username
* @return
*/
@Select("select * from user where username like #{username}")
List<User> findByName(String username); /**
* 删除用户
* @param id
* @return
*/
@Delete("delete from user where id=#{id}")
int deleteUser(int id);
}

注意!!!使用注解开发时,要求实体类数据中属性必须和 mysql 中的属性名一致(除非你进行映射转换的配置),可以忽略大小写。

可参考文章:https://blog.csdn.net/guan_sir/article/details/104561362       https://blog.csdn.net/weixin_44149454/article/details/90373036

6、mybatis总结

7、参考资料

  1. https://www.bilibili.com/video/BV1mE411X7yp?from=search
  2. https://blog.csdn.net/IT_CREATE/article/details/86564305
  3. https://www.cnblogs.com/arrows/p/10531808.html
  4. https://blog.csdn.net/dwenxue/article/details/82351120
  5. https://blog.csdn.net/writedew/article/details/94459863
  6. https://blog.csdn.net/although1/article/details/103719383
  7. https://www.cnblogs.com/king0207/p/13578912.html
  8. https://blog.csdn.net/weixin_44149454/article/details/90373036
  9. https://blog.csdn.net/guan_sir/article/details/104561362
  10. https://blog.csdn.net/chpllp/article/details/81945600
  11. https://www.cnblogs.com/jpfss/p/7681420.html
  12. https://blog.csdn.net/sinat_24230393/article/details/97006106
  13. https://www.cnblogs.com/jtlgb/p/8780594.html
  14. https://bbs.csdn.net/topics/380189849
  15. https://blog.csdn.net/qq_34902437/article/details/105041210
  16. https://jingyan.baidu.com/article/2fb0ba40a2b22b00f2ec5faf.html
  17. https://blog.csdn.net/zj420964597/article/details/84564440
  18. https://bbs.csdn.net/topics/391027203?list=lz
  19. https://blog.csdn.net/cc41798520101/article/details/52411401
  20. https://blog.csdn.net/qq_40645822/article/details/101844675
  21. https://developer.aliyun.com/article/619693
  22. https://blog.csdn.net/weixin_33716557/article/details/92423934
  23. https://www.cnblogs.com/softidea/p/5773191.html
  24. https://blog.csdn.net/csdn1428208016/article/details/85243863
  25. https://blog.csdn.net/u013412772/article/details/73648537
  26. https://www.itdaan.com/blog/2008/08/20/8aa0deb865221baa90f4259603ad2f64.html
  27. https://www.cnblogs.com/chongaizhen/p/11170595.html

ssm——mybatis整理的更多相关文章

  1. ssm知识点整理

    第1章 resultType和resultMap的区别是什么?  MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType ...

  2. SSM Mybatis将新增数据写入数据库时出现的500状态码:Error updating database.的可能

    关于maven下ssm整合的项目推荐这篇博客:https://www.cnblogs.com/yiye/p/5969157.html 今日在ssm下的将新增数据写回数据库时遇到不少的问题,现作记录 如 ...

  3. Mybatis整理_01

    Mybatis专题 Mybaits介绍 Mybatis是一个持久化框架,它有不同语言的版本,比如.NET和Java都有Mybatis对应的类库:它有大多数ORM框架都具有的功能,比如自定义的SQL语句 ...

  4. [原] MyBatis 整理

    花了一上午的时间,先整理一个脑图.

  5. Mybatis整理系列(01)————传入参数方式以及#{}与${}的区别

    一.在MyBatis的select.insert.update.delete这些元素中都提到了parameterType这个属性.MyBatis现在可以使用的parameterType有基本数据类型和 ...

  6. SSM - Mybatis SQL映射文件

    MyBatis 真正的力量是在映射语句中.和对等功能的jdbc来比价,映射文件节省很多的代码量.MyBatis的构建就是聚焦于sql的. sql映射文件有如下几个顶级元素:(按顺序) cache配置给 ...

  7. mybatis整理笔记

    以下是idea2018辑编器 新建 Maven工程 1  file ->new ->project 新建后编程器在右下角加载插件.,这个时候需要会儿,  加载好后,软件目录会多一个ja包 ...

  8. SSM+MyBatis框架详解

  9. 【Mybatis架构】 延迟加载

    在上一篇博客中,我们提到过有关于Mybatis输出映射中resultMap能够实现延迟加载的事,然而真的是所有的resultMap都能实现延迟加载还是咋地啊?现在我们就来对那一句话做一下阐述和实例说明 ...

  10. 【Mybatis框架】查询缓存(二级缓存)

    继上一篇博客,我们讲述了mybatis的一级缓存,接下来,我们来学习一下mybatis的二级缓存 博客链接地址: http://blog.csdn.NET/liweizhong193516/artic ...

随机推荐

  1. web share api 分享

    概述 Navigator.share()  方法通过调用本机的共享机制作为 Web Share API 的一部分.如果不支持 Web Share API,则此方法为 undefined. 此项功能仅在 ...

  2. golang中的socket编程

    0.1.索引 https://waterflow.link/articles/1664591292871 1.tcp的3次握手(建立连接) 客户端的协议栈向服务器端发送了 SYN 包,并告诉服务器端当 ...

  3. JavaScript函数式编程之函子

    函子(Functor) 函子是一个特殊的容器,通过一个普通对象来实现,该对象具有map方法,map方法可以运行一个函数对值进行处理(变形关系),容器包含值和值变形关系(这个变形关系就是函数).函数式编 ...

  4. 【原创】i.MXRT J-Flash烧写算法使能eFuse熔丝位写入

    ​       临近年底,终于又憋了一篇文章出来,本来年初的时候是有计划把去年总结的一些东西整理下发布出来的,结果还是被工作和生活上各种琐事给耽搁了.哎,今年刚过了自己35岁的生日,眼瞅着这个人生节点 ...

  5. MySQL的下载、安装、配置

    下载 官方下载地址:下载地址: 找到免费社区版本 进入到下面页面的时候,下载对应的MySQL,我这里选择Windows. 点击Download ,如下图: 后面他会提示你登录注册啥的,我们选择不需要, ...

  6. Python基础部分:9、数据的类型和内置方法

    目录 一.数据类型内置方法理论 1.什么是数据内置方法 2.如何调用数据内置方法 二.整型(int)内置方法与操作 1.类型转换 2.进制数转换 三.浮点型(float)内置方法与操作 1.类型转换 ...

  7. Day16自定义异常

    package com.exception.demo02;//自定义的异常类public class MyException extends Exception{ //传递数字>10抛出异常 p ...

  8. .net 温故知新:【9】.NET日志记录 ILogger使用和原理

    日志 日志作为我们程序记录的"黑匣子"是不论什么系统都会使用到的,比如我们经常使用的log4net就是第三方日志记录提供程序.NET 支持使用各种内置和第三方日志记录提供程序的日志 ...

  9. <四>构造函数初始化列表

    示例代码1 点击查看代码 class CDate{ public: CDate(int _year,int _month, int _day){ this->year=_year; this-& ...

  10. perl中 use strict会出现“requires explicit package name”错误

    转载 perl中use strict的用法 如果你使用 use strict 的话,它会强迫你用 my 声明变量,否则将会报上述错误.