设为首页 收藏本站
查看: 861|回复: 0

[经验分享] SQL映射

[复制链接]

尚未签到

发表于 2018-10-20 09:21:12 | 显示全部楼层 |阅读模式
  前面学习了config.xml,下面就要进入MyBatis的核心SQL映射了,第一篇文章的时候,student.xml里面是这么写的:


  
   
  
        
  
   

  基于这个xml,进行扩展和学习。
  为什么要使用?
  上面的配置文件中,大家一定注意到了一个细节,就是SQL语句用这对标签包含起来了,那么为什么要这么做呢?不妨把上面内容稍微修改一下:


  
   
  
        select * from student where studentId = #{id} or studentAge < 10 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文件的语法。因此,"< 10 or studentAge >"这段,会先被解析为xml的标签,xml哪有这种形式的标签的?所以当然报错了。
  所以,使用,它可以保证如论如何里面的内容都会被解析成SQL语句。因此,建议每一条SQL语句都使用包含起来,这也是一种规避错误的做法。
  select
  SQL映射中有几个顶级元素,其中最常见的四个就是insert、delete、update、select,分别对应于增、删、改、查,下面先对于select元素进行学习。
  1、多条件查询查一个结果
  前面的select语句只有一个条件,下面看一下多条件查询如何做,首先是student.xml:
  
   
  注意这里的parameter只能是一个实体类,然后参数要和实体类里面定义的一样,比如studentId、studentName,MyBatis将会自动查找这些属性,然后将它们的值传递到预处理语句的参数中去。
  还有一个很重要的地方是,使用参数的时候使用了"#",另外还有一个符号"$"也可以引用参数,使用"#"最重要的作用就是防止SQL注入
  接着看一下Java代码的写法:

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来说,重要的当然是查询多个结果,查询多个结果有相应的写法,看一下:

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

   #{id};    ]]>

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

  
   
  
   
  
   
  
   
  
     #{id};    ]]>

  这样就可以了,注意两点:
  1、resultMap定义中主键要使用id
  2、resultMap和resultType不可以同时使用
  对resultMap有很好的理解的话,许多复杂的映射问题就很好解决了。
  insert
  select看完了,接着看一下插入的方法。首先是student.xml的配置方法,由于插入数据涉及一个主键问题,我用的是MySQL,我试了一下使用以下两种方式都可以:
  
        
  
        
  前一种是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的时候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的写法有一定限制,使用前要注意一下避免出错。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-623902-1-1.html 上篇帖子: 自学sql之路,SQL 是用于访问和处理数据库的标准的计算机语言! 下篇帖子: Hive SQL 监控系统 - Hive Falcon
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表