前面学习了config.xml,下面就要进入MyBatis的核心SQL映射了,第一篇文章的时候,student.xml里面是这么写的:

1
2
3
4
5
6
7
8
9
10
11
<?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.xrq.StudentMapper">
    <select id="selectStudentById" parameterType="int" resultType="Student">
        <![CDATA[
            select * from student where studentId = #{id}
        ]]>
    </select>
</mapper>

基于这个xml,进行扩展和学习。

为什么要使用<![CDATA[ ... ]]>?

上面的配置文件中,大家一定注意到了一个细节,就是SQL语句用<![CDATA[ ... ]]>这对标签包含起来了,那么为什么要这么做呢?不妨把上面内容稍微修改一下:

1
2
3
4
5
6
7
8
9
<?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.xrq.StudentMapper">
    <select id="selectStudentById" parameterType="int" resultType="Student">
        select * from student where studentId = #{id} or studentAge < 10 or studentAge > 20;
    </select>
</mapper>

当然这句SQL语句没有任何含义,只是瞎写的演示用而已,运行一下看一下结果:

1
2
3
4
5
6
Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.xrq.test.MyBatisTest.main(MyBatisTest.java:9)
Caused by: org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in student.xml
...

后面的异常信息就不列了。按理说很正常的一句SQL语句,怎么会报错呢?仔细想来,错误的根本原因就是student.xml本身是一个xml文件,它并不是专门为MyBatis服务的,它首先具有xml文件的语法。因此,”< 10 or studentAge >”这段,会先被解析为xml的标签,xml哪有这种形式的标签的?所以当然报错了。

所以,使用<![CDATA[ ... ]]>,它可以保证如论如何<![CDATA[ ... ]]>里面的内容都会被解析成SQL语句。因此,建议每一条SQL语句都使用<![CDATA[ ... ]]>包含起来,这也是一种规避错误的做法。

select

SQL映射中有几个顶级元素,其中最常见的四个就是insert、delete、update、select,分别对应于增、删、改、查,下面先对于select元素进行学习。

1、多条件查询查一个结果

前面的select语句只有一个条件,下面看一下多条件查询如何做,首先是student.xml:

1
2
3
4
5
<select id="selectStudentByIdAndName" parameterType="Student" resultType="Student">
    <![CDATA[
        select * from student where studentId = #{studentId} and studentName = #{studentName};
    ]]>
</select>

注意这里的parameter只能是一个实体类,然后参数要和实体类里面定义的一样,比如studentId、studentName,MyBatis将会自动查找这些属性,然后将它们的值传递到预处理语句的参数中去。

还有一个很重要的地方是,使用参数的时候使用了”#”,另外还有一个符号”$”也可以引用参数,使用”#”最重要的作用就是防止SQL注入

接着看一下Java代码的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public Student selectStudentByIdAndName(int studentId, String studentName)
{
    SqlSession ss = ssf.openSession();
    Student student = null;
    try
    {
        student = ss.selectOne("com.xrq.StudentMapper.selectStudentByIdAndName",
                new Student(studentId, studentName, 0, null));
    }
    finally
    {
        ss.close();
    }
    return student;
}

这里selectOne方法的第二个参数传入一个具体的Student进去就可以了,运行就不演示了,结果没有问题。

2、查询多个结果

上面的演示查询的是一个结果,对于select来说,重要的当然是查询多个结果,查询多个结果有相应的写法,看一下:

1
2
3
4
5
6
<select id="selectAll" parameterType="int" resultType="Student" flushCache="false" useCache="true"
    timeout="10000" fetchSize="100" statementType="PREPARED" resultSetType="FORWARD_ONLY">
    <![CDATA[
        select * from student where studentId > #{id};
    ]]>
</select>

这里稍微玩了一些花样,select里面多放了一些属性,设置了每条语句的作用细节,分别解释下这些属性的作用:

  • id—-不说了,用来和namespace唯一确定一条引用的SQL语句
  • parameterType—-参数类型,如果SQL语句中的动态参数只有一个,这个属性可有可无
  • resultType—-结果类型,注意如果返回结果是集合,应该是集合所包含的类型,而不是集合本身
  • flushCache—-将其设置为true,无论语句什么时候被调用,都会导致缓存被清空,默认值为false
  • useCache—-将其设置为true,将会导致本条语句的结果被缓存,默认值为true
  • timeout—-这个设置驱动程序等待数据库返回请求结果,并抛出异常事件的最大等待值,默认这个参数是不设置的(即由驱动自行处理)
  • fetchSize—-这是设置驱动程序每次批量返回结果的行数,默认不设置(即由驱动自行处理)
  • statementType—-STATEMENT、PREPARED或CALLABLE的一种,这会让MyBatis选择使用Statement、PreparedStatement或CallableStatement,默认值为PREPARED。这个相信大多数朋友自己写JDBC的时候也只用过PreparedStatement
  • resultSetType—-FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE中的一种,默认不设置(即由驱动自行处理)

xml写完了,看一下如何写Java程序,比较简单,使用selectList方法即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public List<Student> selectStudentsById(int studentId)
{
    SqlSession ss = ssf.openSession();
    List<Student> list = null;
    try
    {
        list = ss.selectList("com.xrq.StudentMapper.selectAll", studentId);
    }
    finally
    {
        ss.close();
    }
    return list;
}

同样,结果也就不演示了,查出来和数据库内的数据相符。

3、使用resultMap来接收查询结果

上面使用的是resultType来接收查询结果,下面来看另外一种方式—-使用resultMap,被MyBatis称为MyBatis中最重要最强大的元素。

上面使用resultType的方式是有前提的,那就是假定列名和Java Bean中的属性名存在对应关系,如果名称不对应,也没关系,可以采用类似下面的方式:

1
2
3
4
5
6
7
<select id="selectAll" parameterType="int" resultType="Student" flushCache="false" useCache="true"
    timeout="10000" fetchSize="100" statementType="PREPARED" resultSetType="FORWARD_ONLY">
    <![CDATA[
        select student_id as "studentId",student_name as "studentName",student_age as "studentAge",
      student_phone as "studentPhone" from student whehre restudentId > #{id};
    ]]>
</select>

毫无疑问,这样很繁琐,我们可以采用resultMap来解决列名不匹配的问题,把2由resultType的形式改成resultMap的形式,Java代码不需要动:

1
2
3
4
5
6
7
8
9
10
11
12
13
<resultMap type="Student" id="studentResultMap">
    <id property="studentId" column="studentId" />
    <result property="studentName" column="studentName" />
    <result property="studentAge" column="studentAge" />
    <result property="studentPhone" column="studentPhone" />
</resultMap>
<select id="selectAll" parameterType="int" resultMap="studentResultMap" flushCache="false" useCache="true"
        timeout="10000" fetchSize="100" statementType="PREPARED" resultSetType="FORWARD_ONLY">
    <![CDATA[
        select * from student where studentId > #{id};
    ]]>
</select>

这样就可以了,注意两点:

1、resultMap定义中主键要使用id

2、resultMap和resultType不可以同时使用

对resultMap有很好的理解的话,许多复杂的映射问题就很好解决了。

insert

select看完了,接着看一下插入的方法。首先是student.xml的配置方法,由于插入数据涉及一个主键问题,我用的是MySQL,我试了一下使用以下两种方式都可以:

1
2
3
4
5
<insert id="insertOneStudent" parameterType="Student">
    <![CDATA[
        insert into student    values(null, #{studentName}, #{studentAge}, #{studentPhone});
    ]]>   
</insert>

1
2
3
4
5
6
<insert id="insertOneStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="studentId">
    <![CDATA[
        insert into student(studentName, studentAge, studentPhone)
            values(#{studentName}, #{studentAge}, #{studentPhone});
    ]]>   
</insert>

前一种是MySQL本身的语法,主键字段在insert的时候传入null,后者是MyBatis支持的生成主键方式,useGeneratedKeys表示让数据库自动生成主键,keyProperty表示生成主键的列。

Java代码比较容易:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void insertOneStudent(String studentName, int studentAge, String studentPhone)
{
    SqlSession ss = ssf.openSession();
    try
    {
        ss.insert("com.xrq.StudentMapper.insertOneStudent",
            new Student(0, studentName, studentAge, studentPhone));
        ss.commit();
    }
    catch (Exception e)
    {
        ss.rollback();
    }
    finally
    {
        ss.close();
    }
}

还是一样,insert方法比如传入Student的实体类,如果insertOneStudent方法要传入的参数比较多的话,建议不要把每个属性单独作为形参,而是直接传入一个Student对象,这样也比较符合面向对象的编程思想。

然后还有一个问题,这个我回头还得再看一下。照理说设置了transactionManager的type为JDBC,对事物的处理应该和底层JDBC是一致的,JDBC默认事物是自动提交的,这里事物却得手动提交,抛异常了得手动回滚才行。

修改、删除元素

修改和删除元素比较类似,就看一下student.xml文件怎么写,Java代码就不列了,首先是修改元素:

1
2
3
4
5
6
<update id="updateStudentAgeById" parameterType="Student">
    <![CDATA[
        update student set studentAge = #{studentAge} where
            studentId = #{studentId};
    ]]>   
</update>

接着是删除元素:

1
2
3
4
5
<delete id="deleteStudentById" parameterType="int">
    <![CDATA[
        delete from student where studentId = #{studentId};
    ]]>   
</delete>

这里我又发现一个问题,记录一下,update的时候Java代码是这么写的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void updateStudentAgeById(int studentId, int studentAge)
{
    SqlSession ss = ssf.openSession();
    try
    {
        ss.update("com.xrq.StudentMapper.updateStudentAgeById",
                new Student(studentId, null, studentAge, null));
        ss.commit();
    }
    catch (Exception e)
    {
        ss.rollback();
    }
    finally
    {
        ss.close();
    }
}

studentId和studentAge必须是这个顺序,互换位置就更新不了学生的年龄了,这个是为什么我还要后面去研究一下,也可能是写代码的问题。

SQL

SQL可以用来定义可重用的SQL代码段,可以包含在其他语句中,比如我把上面的插入换一下,先定义一个SQL:

1
2
3
<sql id="insertColumns">
    studentName, studentAge, studentPhone
</sql>

然后在修改一下insert:

1
2
3
4
<insert id="insertOneStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="studentId">
    insert into student(<include refid="insertColumns" />)
        values(#{studentName}, #{studentAge}, #{studentPhone});
</insert>

注意这里要把”<![CDATA[ ... ]]>”给去掉,否则”<”和”>”就被当成SQL里面的小于和大于了,因此使用SQL的写法有一定限制,使用前要注意一下避免出错。

转载于:https://www.cnblogs.com/tuojunjie/p/6210282.html

MyBatis(3):SQL映射相关推荐

  1. 关于Mybatis的SQL映射文件中in关键字的用法

    有一个需求是可以选择多个设备进行删除,于是想到将多个设备id拼成字符串作为参数,以逗号隔开,如:"123,234,456". SQL如下: <delete id=" ...

  2. MyBatis简介——半自动的持久化层框架(SQL映射框架)|| 支持定制化sql

    MyBatis简介 1.MyBatis:和数据库进行交互:持久化层框架(SQL映射框架): 1).从原始的JDBC-----dbutils(QueryRunner)-------JdbcTemplat ...

  3. MyBatis是持久化层框架(SQL映射框架)-操作数据库

    MyBatis是持久化层框架(SQL映射框架)-操作数据库 1.环境搭建 1).创建一个java工程: 2).创建测试库,测试表,以及封装数据的javaBean,和操作数据库的dao接口 创建表:自己 ...

  4. 8、mybatis中的sql映射文件详解(3)

    对于初学者,如何进行mybatis的学习呢?我总结了几点,会慢慢的更新出来.首先大家需要了解mybatis是什么.用mybatis来做什么.为什么要用mybatis.有什么优缺点:当知道了为什么的时候 ...

  5. 7、mybatis中的sql映射文件详解(2)

    对于初学者,如何进行mybatis的学习呢?我总结了几点,会慢慢的更新出来.首先大家需要了解mybatis是什么.用mybatis来做什么.为什么要用mybatis.有什么优缺点:当知道了为什么的时候 ...

  6. 6、mybatis中的sql映射文件详解(1)

    对于初学者,如果进行mybatis的学习呢?我总结了几点,会慢慢的更新出来.首先大家需要了解mybatis是什么.用mybatis来做什么.为什么要用mybatis.有什么优缺点:当知道了为什么的时候 ...

  7. SpringBoot项目集成Mybatis Plus(四)SQL映射文件

    实际使用中,都会用到自定义SQL查询语句,并且需要支持分页,因为之前在项目中配置了分页插件,所以用起来很简单. 例如,定义接口getList,接口参数为分页参数和查询条件, @RequestMappi ...

  8. 【java学习之路】(java框架)004.Mybatis SQL映射文件详解

    02Mybatis SQL映射文件详解 ​ 在之前我们学习了mybatis的全局配置文件,下面我们开始学习mybatis的映射文件,在映射文件中,可以编写以下的顶级元素标签: cache – 该命名空 ...

  9. 2 MyBatis Sql映射文件

    MyBatis SQL映射文件 文章目录 MyBatis SQL映射文件 1.SQL映射的XML文件 2.select条件查询 3.多条件查询 1.将条件封装成Java对象作为入参 2.将查询条件封装 ...

最新文章

  1. 摄影测量(计算机视觉)中的三角化方法
  2. 李开复对话李飞飞:AI要理解人类的情感,还早着呢
  3. Android 热修复总结
  4. python中对切片的理解
  5. NYOJ 257 中缀表达式表示成后缀表达式
  6. poj 1011 Sticks 搜索
  7. xavier初始化_深入解读xavier初始化(附源码)
  8. python 随机排序_Python 如何随机打乱列表(List)排序
  9. matlab如何画函数的外包络曲线,怎样在MATLAB中划出一个函数的包络线?
  10. 高能同步辐射光源科学数据管理策略研究与应用
  11. [zz]linux修改密码出现Authentication token manipulation error的解决办法
  12. VSCode 1.35 发布,新的图标,支持远程开发
  13. python人工智能学习笔记_[Python] 人工智能与自然语言处理学习笔记(1)
  14. MFC UpdateData
  15. [大牛翻译系列]Hadoop(7)MapReduce:抽样(Sampling)
  16. 连续十日票房日冠,《人生大事》带热了电影大盘!它凭何突出重围?
  17. oracle 行转列后列名,Oracle 多行转多列,列值转为列名
  18. js和jQury实现Aajx
  19. Redis集群之多主多从
  20. 男人撒娇的十个关键词

热门文章

  1. MySQL CONCAT函数:字符串拼接
  2. linux文件夹不能修改权限
  3. 解决批处理命令执行完毕后自动关闭cmd窗口
  4. Material Design组件之NavigationView
  5. 第10讲 | 深入区块链技术(二):P2P网络
  6. 电脑出现 flash update failed 解决方法
  7. Linux基础之bash脚本编程初级-变量与算术运算
  8. Linux内核——定时器和时间管理
  9. 删除IE 下输入后的清除小叉叉
  10. 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02) A Amusing Numbers (数学)