专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
黑马程序员  ·  2025年,Java开发要起飞了吗? ·  2 天前  
黑马程序员  ·  2025年,Java开发要起飞了吗? ·  2 天前  
芋道源码  ·  如何优雅的将设计模式运用到实际项目中去? ·  3 天前  
Java编程精选  ·  只会 RedisTemplate 访问 ... ·  4 天前  
51好读  ›  专栏  ›  ImportNew

MyBatis(3):SQL映射

ImportNew  · 公众号  · Java  · 2016-12-21 20:02

正文

(点击上方公众号,可快速关注)


来源:五月的仓颉

链接:www.cnblogs.com/xrq730/p/5276988.html


前言


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


/span>

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 

   

        select * from student where studentId = #{id} or studentAge 20;

   


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


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文件的语法。因此,””这段,会先被解析为xml的标签,xml哪有这种形式的标签的?所以当然报错了。


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


select


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


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


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


    timeout="10000" fetchSize="100" statementType="PREPARED" resultSetType="FORWARD_ONLY">

   

        select * from student where studentId > #{id};

    ]]>


这里稍微玩了一些花样,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方法即可:


public List selectStudentsById(int studentId)

{

    SqlSession ss = ssf.openSession();

    List 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中的属性名存在对应关系,如果名称不对应,也没关系,可以采用类似下面的方式:


        timeout="10000" fetchSize="100" statementType="PREPARED" resultSetType="FORWARD_ONLY">

   

        select * from student where studentId > #{id};

    ]]>


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


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


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


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


insert


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


   

        insert into student    values(null, #{studentName}, #{studentAge}, #{studentPhone});

    ]]>   


   

        insert into student(studentName, studentAge, studentPhone) 

            values(#{studentName}, #{studentAge}, #{studentPhone});

    ]]>   


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


Java代码比较容易:


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代码就不列了,首先是修改元素:


   

        update student set studentAge = #{studentAge} where 

            studentId = #{studentId};

    ]]>   


接着是删除元素:


   

        delete from student where studentId = #{studentId};

    ]]>   


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


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:


    studentName, studentAge, studentPhone


然后在修改一下insert:


    insert into student(

        values(#{studentName}, #{studentAge}, #{studentPhone});


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


本系列:



觉得本文对你有帮助?请分享给更多人

关注「ImportNew」,看技术干货