MyBatis框架(二)之使用详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fightingXia/article/details/82317206

##概述

MyBatis是java项目持久层框架中比较优秀的一个,几乎满足项目中的一切需求。

MyBatis的核心是Mapper文件,Mapper文件中接收java对象参数,写sql语句,返回Java对象结果,所以下面讲解的知识都是在Mapper文件中的操作。

主要内容有:

  1. 基本使用说明。
  2. 传递参数。
  3. 返回值。
  4. insert时返回主键。
  5. jdbcType属性的使用。
  6. resultMap的使用。
  7. sql片段的使用。
  8. mapper.xml文件中特殊字符的处理。

##基本使用说明

在MyBatis的基本使用中,根据id查找对象的xml片段是:

    <select id="queryOne" parameterType="int" resultType="studentModel">
        select name,age
        from student WHERE id=#{id}
    </select>

说明:

  1. select:select是xml标签,表示查询。插入对应insert,更新对应update,删除对应delete.
  2. id:id是该xml片段的唯一标识,在同一个mapper文件中id不能重复。java程序根据该id找到对应的sql语句。
  3. parameterType:参数数据类型,参数类型需要写全类名或者写别名,int是框架自定义的别名。
  4. resultType:返回值数据类型,此与参数数据类型使用方法项目。
  5. sql语句:select标签中是sql语句。注意接收参数的形式:#{id}。

##传递参数

传递参数需要注意两点,一是设置参数类型,二是怎么接收参数。

一,设置参数类型

参数类型使用parameterType属性指定,参数类型需要写全类名或者写别名。

如果参数类型是int,全类名的写法如下:

parameterType="java.lang.Integer"

框架定义了常用类型的别名,java.lang.Integer的别名是int,所以int数据可以可以直接这么写:

parameterType="int" 

##框架中定义的别名有:

8个基本数据类型,string,map。

注意:java.util.List不是默认别名,需要写全类名。

二,自定义别名

如果参数是我们自定义的类,比如:com.honor.mybatis.model.StudentModel写法如下:

parameterType="com.honor.mybatis.model.StudentModel" 

这种写法比较麻烦,且此时是字符串,容易出错。所以此时需要自定义别名,然后使用别名即可。

MyBatis框架定义别名写在全局配置文件中(SqlMapConfig.xml)即可,如下:

    <typeAliases>
        <typeAlias type="com.honor.mybatis.model.StudentModel" alias="studentModel"/>
    </typeAliases>

此时在Mapper文件中使用别名即可,如下:

parameterType="studentModel"

三,传递基本数据参数

接收int参数示例如下:

    <select id="queryOne" parameterType="int" resultType="studentModel">
        select name,age
        from student WHERE id=#{id}
    </select>

说明:

  1. parameterType指定数据类型为int。
  2. 在sql中使用#{id}接收参数,此时id是行参,可以自定义,即可以是任意变量。

三,对象参数

接收com.honor.mybatis.model.StudentModel参数示例如下:

    <select id="queryList" parameterType="com.honor.mybatis.model.StudentModel" resultType="studentModel">
        select name,age
        from student WHERE name=#{name} AND age=#{age}
    </select>

说明:

  1. parameterType指定数据类型为com.honor.mybatis.model.StudentModel。如果定义了别名此时也可以使用别名。。
  2. 在sql中使用#{name}和#{age}接收参数,此时name和age必须与StudentModel的字段名对应,不能自定义。

四,List参数

1,接收List<int>参数示例如下:

    <select id="getObjectByIds" parameterType="java.util.List" resultType="studentModel">
        select name,age
        from student
        where id in
        <foreach collection="list" index="index" item="item" separator="," open="(" close=")">
            #{item}
        </foreach>
    </select>

说明:

  1. 此时是根据id集合查询student对象,所以要传递list参数。
  2. parameterType指定数据类型为java.util.List。
  3. foreach表示遍历,item表示集合中的元素。遍历后的结果相当于:(1,2,3,)。
  4. 取值使用#{item},此时的item与foreach标签的item属性值保持一致。

2,接收List<Student>参数示例如下:

    <select id="getObjectByIds" parameterType="java.util.List" resultType="studentModel">
        select name,age
        from student
        where id in
        <foreach collection="list" index="index" item="item" separator="," open="(" close=")">
            #{item.id}
        </foreach>
    </select>

说明:

  1. 此时parameterType仍然是java.util.List。
  2. 取值使用#{item.id},此时的item与foreach标签的item属性值保持一致,表示集合中的元素,即student对象,id表示student的id字段。

五,Map参数

Map<String,Object>参数示例如下:

    <select id="queryList" parameterType="map" resultType="studentModel">
        select name,age
        from student WHERE name=#{name} AND age=#{age}
    </select>

说明:

  1. 此时parameterType是map。
  2. 在sql中使用#{name}和#{age}接收参数,此时name和age必须与map的键对应,不能自定义。

当Map的value是Student时示例如下:

    <select id="queryList" parameterType="map" resultType="studentModel">
        select name,age
        from student WHERE name=#{student.name} AND age=#{student.age}
    </select>

说明:

  1. 此时parameterType是map。
  2. 在sql中使用#{student.name}和#{student.age}接收参数,此时student必须与map的键对应,name和age是Student的字段名。

##返回值

一,返回基本数据类型

查询数据条数的sql返回值都是int,示例如下:

    <select id="queryCount" parameterType="studentModel" resultType="int">
        SELECT COUNT(*) FROM student
        WHERE name=#{student.name} AND age=#{student.age}
    </select>

说明:

  1. 使用resultType定义返回值类型,此时使用int。
  2. 查询到的数量只有一个值,会自动返回。

返回string类型的数据。示例如下:

    <select id="queryOne" parameterType="int" resultType="string">
        select name
        from student WHERE id=#{id}
    </select>

二,返回对象

返回对象的标准写法如下:

    <select id="queryOne" parameterType="int" resultType="studentModel">
        select name as name,age as age
        from student WHERE id=#{id}
    </select>

说明:

  1. 使用resultType定义返回值类型,此时是studentModel类。
  2. sql语句中as前的name是数据库的字段,as后的name是StudentModel类的字段。

如果数据库表字段名和类的字段名相同,则可以简写:

    <select id="queryOne" parameterType="int" resultType="studentModel">
        select name ,age 
        from student WHERE id=#{id}
    </select>

三,返回List集合

返回List结合和返回单个对象在Mapper文件中的写法完全一样,返回值仍然写List中元素的类型,sql完全不变,只是sqlsession对象调用的方法不同。sqlsession的调用如下:

List<StudentModel> studentModelList = sqlSession.selectList("student.queryList", student);

四,返回Map对象

返回map对象示例如下:

    <select id="queryOne" parameterType="int" resultType="map">
        select name ,age
        from student WHERE id=#{id}
    </select>

注:此时返回的map对象的键分别是name和age,即与表字段名保持一直。

自定义map的key的写法如下:

    <select id="queryOne" parameterType="int" resultType="map">
        select name as name1 ,age as age1
        from student WHERE id=#{id}
    </select>

##insert时返回主键

在开发中很多情况下需要插入数据时返回主键,MyBatis中提供了该方法。但MySql和oracle数据库返回主键的方法不同。

一,MySql数据库insert时返回主键

具体如下:

    <insert id="insert" parameterType="studentModel" useGeneratedKeys="true" keyProperty="id">
        insert into student (name,age)
        values(#{name},#{age})
    </insert>

说明:

  1. useGeneratedKeys表示自动生成主键,keyProperty表示主键的字段。
  2. 返回的主键并不是在方法返回值中,而是在参数studentModel中。

sqlsession的代码如下:

            //row为影响的条数
            int row = sqlSession.insert("student.insert", student);
            //id为返回的主键id
            int id = student.getId();

二,Oracle数据库insert时返回主键

具体如下:

    <insert id="insertUser" parameterType="studentModel">
        <selectKey keyProperty="id" order="BEFORE" resultType="int">
            Select 序列名.nextval from dual
        </selectKey>
        insert into user(id,student,age)
        values(#{id},#{student},#{age})
    </insert>

注:因为roacle的主键id不是自增长的,所以一个表要关联一个序列号,获取下一个序列号的值当作表的主键。

##jdbcType属性的使用

一,jdbcType的使用

在上面的示例中sql语句都不是严格的写法,严格应该如下:

    <insert id="insert" parameterType="studentModel" useGeneratedKeys="true" keyProperty="id">
        insert into student (name,age)
        values(#{name,jdbcType=VARCHAR},#{age,jdbcType=INTEGER})
    </insert>

严格的写法要在获取数据时指定数据类型,jdbcType即是指定数据类型。

二,为什么要使用jdbcType

相信很多人在使用Mybatis时遇到过下面问题:

org.springframework.jdbc.UncategorizedSQLException: Error setting null parameter.  
        Most JDBC drivers require that the JdbcType must be specified for all nullable parameters.
    Caused by: java.sql.SQLException: 无效的列类型: 1111
        at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
        ......

产生这个异常的原因是:当某个参数为null时,系统不知道该参数是什么数据类型,此时就会报错。

但是,我有一个大大的❓,为什么大部分时候都不报错,只有个别情况下报错。希望看到此处的大神给予留言帮助,感激不尽!

解决上面问题的方式就是使用jdbcType指定数据类型。

三,常用的jdbcType与java数据类型的对应关系

常用的对应关系如下:

VARCHAR             String 
NUMERIC             java.math.BigDecimal   
INTEGER             int  
BIGINT              long   
DOUBLE              double  
DATE                java.sql.Date  
TIME                java.sql.Time  
TIMESTAMP           java.sql.Timestamp  

##resultMap的使用

一,定义resultMap

在mapper.xml文件中定义resultMap的方式如下:

    <resultMap id="BaseResultMap" type="studentModel">
        <result column="id" jdbcType="INTEGER" property="id"/>
        <result column="name" jdbcType="VARCHAR" property="name"/>
        <result column="age" jdbcType="VARCHAR" property="age"/>
        <result column="created_time" jdbcType="TIMESTAMP" property="createdTime"/>
    </resultMap>

说明:

  1. resultMap标签有两个属性,id是该resultMap的标识,type指定数据类型。
  2. 一个result标签对应数据库表中的字段,且对应Model类中的字段。column为数据库表中的字段,property为model类的字段。jdbcType为数据类型。

注:此时jdbyType的数据类型与上面讲的jdbcType的类型一致,但此时使用双引号,上面不需要双引号。

二,resultMap的使用

使用示例如下:

    <select id="queryOne" parameterType="int" resultMap="BaseResultMap">
        select name ,age 
        from student WHERE id=#{id}
    </select>

说明:

  1. 这是一个查询语句,此时查询的结果封装到resultMap中,此时resultMap属性的值即为定义resultMap时的id。
  2. 此时select name时不需要写as name,会根据resultMap中定义的对应关系对应Model类中的字段。
  3. 在java代码中直接使用resultMap中定义的Model类数据接收即可。

三,resultMap的作用

resultMap有两大作用:

  1. 指定数据库表中的字段与Model类中的字段的对应关系。
  2. 可以复用。

##sql片段的使用

在mapper.xml文件中可以定义sql片段,然后被其他地方使用。具体如下:

一,sql片段的定义

    <sql id="Base_Column_List">
        id, name, age
    </sql>

说明:

  1. 定义sql片段使用sql标签,id属性为该sql片段的标识。
  2. 在sql片段中可以是任意sql中的一段。

二,sql片段的使用

    <select id="queryOne" parameterType="int" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from student WHERE id=#{id}
    </select>

说明:

  1. 使用include引用sql片段,refid对应sql片段的ID。
  2. 引用sql片段等效于把该段sql写到引用处。

三,sql片段的作用

sql片段的最大作用就是复用,类似于java代码中的字符串常量,也便于修改维护。

##mapper.xml文件中特殊字符的处理

mapper.xml文件是一个xml文件,一些字符被作为xml的定义符号,当sql语句中使用这些特殊符号时需要做特殊处理。处理方式有两种,一种是使用转译字符,另外一种使用<![CDATA[   ]]>。

一,使用转译字符

常见的需要转译的字符如下:

原符号        <        <=        >        >=         &           '                "

替换符号    &lt;    &lt;=     &gt;    &gt;=    &amp;    &apos;      &quot;

例如:sql如下:

create_date_time &gt;= #{startTime} and  create_date_time &lt;= #{endTime}

二,使用<![CDATA[   ]]>

写在“<![CDATA[   ]]>”里面的字符不会被mybatis解析,直接拼接到sql语句中。如下:

大于等于

<![CDATA[ >= ]]>

小于等于

<![CDATA[ <= ]]>

例如:sql如下:

create_date_time <![CDATA[ >= ]]> #{startTime} and  create_date_time <![CDATA[ <= ]]> #{endTime}

##总结

MyBatis是一个非常优秀的框架,不仅将sql与代码分离,而且提供了很好的数据交互方式。

猜你喜欢

转载自blog.csdn.net/fightingXia/article/details/82317206