最近工作比较闲,维护一个政府机关的短信发送平台,大部分业务逻辑都在Oracle数据库上,但自己明明应聘的是Java开发啊!!!整天写存储过程的我还是有一颗写高级语言的心啊!!!好吧!!!先找个数据库方面的框架学起来吧!

  手头项目比较老,还在用ibatis,就找了它的后继者Mybatis3来学习(3.3.0 released,24 May 2015)。

  学习的期望是:

  1. 理解Mybatis相比JDBC最大的优点。
  2. 自己动手搭建Mybatis框架。

  从这几个部分理解:

  1. Mybatis与ibatis的不同
  2. XML配置
  3. XML映射文件
  4. 动态SQL

  没耐心的可以直接跳到最后看总结。

  找来官方文档(还好有中文的)就读起来。

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的。我们可以从 SqlSessionFactory 中获取 SqlSession ,SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。

  我认为 SqlSessionFactory 相当于 ibatis中的SqlMapClient ,因为后者的方法中也有一个openSession()。SqlSession 相当于ibatis中的 SqlMapSession。

  相比之下,Mybatis采用更清晰并且类型安全的方式来执行SQL映射。

 SqlSession session = sqlSessionFactory.openSession();
try {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
} finally {
session.close();
}

更清晰安全的方式

  对于简单的增删改查,这只需要在Java中添加注解(复杂的映射文档中说了最好还是在XML中定义)

 package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}

通过@Java注解实现

  当然,在ibatis中通过XML定义SQL语句映射的方式也是支持的。

  XML映射文件是mybatis的重点。

 <select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>

SQL映射文件

  跟ibatis很像有木有~不同的是这里用#{parameter}来表示映射字段 而ibatis中是#patameter#。而在JDBC中,你需要像这样来映射字段,并且在得到结果集后一一手动映射到对象。这就是Mybatis框架可以节省代码的地方。

  在JDBC中是这样子的:

 String selectPerson = "SELECT * FROM PERSON WHERE ID=? and name = ? and age = ?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
ps.setString(2,name);
ps.setInt(3,age);
ResultSet res = ps.executeQuery();
while(res.next()){
  Student stu = new Student();
  stu.setId(res.getInt(1));
  stu.setName(res.getString(2));
  stu.setAge(res.getInt(3));
}

JDBC代码示例

  而Mybatis中是这样子的:

 <typeAliases>
<typeAlias alias="stu" type="domain.Student"/>
</typeAliases>
<select id="selectStudent" resultType="stu">
select id, username, password
from users
where id = #{id}
</select>

Mybatis代码示例

  除去标签占去的代码行数,当映射对象的属性更多时,代码量差距会更加明显。

  select中可以设置属性,常用的就是id(命名空间中的唯一标识符,用来被引用)、parameterType(传入参数的完整包名或别名)、resultType(返回结果的完整报名或别名,不和resultMap同时使用)、resultMap(外部resultMap的命名引用,稍后会详细讲)、flushCache(清空缓存)、useCache(使用缓存)、timeout(等待数据库返回结果的最大时间)

  对于Oracle,一般在插入中都需要获得主键,可以使用<selectKey>标签来获得主键ID。

 <!--Mybatis中Oracle的主键使用方法 -->
<insert id="insertSMSInpojo" parameterType="SMSINPojo">
<selectKey keyProperty="id" resultType="int">
select s_sms_in.nextval from dual
</selectKey>
insert into sms_in(
msgContent,
mobile,
destNO,
linkId,
curTime
) values(
#msgContent#,
#mobile#,
#destNO#,
#linkId#,
#curTime#
)
</insert>

Oracle主键使用

  对于参数映射,Mybatis中提供了强大的resultMap来支持。对于简单的查询(列名与属性名一一对应),你可以使用hashmap或pojo类来实现

 <!-- In mybatis-config.xml file -->
<typeAlias type="com.someapp.model.User" alias="User"/> <!-- In SQL Mapping XML file -->
<select id="selectUsers" resultType="User">
select id, username, hashedPassword
from some_table
where id = #{id}
</select> or use this <select id="selectUsers" resultType="map">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>

Hashmap pojo类实现

  如果列明没有精确匹配,可以通过 as 来设置别名

 <select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "hashedPassword"
from some_table
where id = #{id}
</select>

  或是通过更强大的resultMap来解决,因为实现了列名和属性名分离,更易于在不同语句中重用

 <resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap> <select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>

ResultMap用法

  

  而且不仅是代码量的差距,我也相信你一定维护过像这样 逗号,拼接 的代码:

 public void insertIntoHddx(TbSmsSync tbsyncpojo, SmsTaskPojo smstask, int num, String optionList) {
String hddxSql = "insert into sms_hddx values(";
hddxSql += tbsyncpojo.getTaskId() + ",";
hddxSql += "'" + smstask.getTaskName() + "',";
hddxSql += "'" + tbsyncpojo.getMsgContent() + "',";
hddxSql += "0 ,";
hddxSql += "to_date('" + smstask.getSendTime() + "','yyyy-mm-dd hh24:mi:ss') ,";
hddxSql += num + ")";
String[] items = optionList.split(";");
for (String item : items) {
String[] itemIdAndName = item.split(",");
String itemId = itemIdAndName[0];
String itemName = itemIdAndName[1];
String searchItemSql = "insert into sms_hddx_option values(";
searchItemSql += "'" + itemId + "',";
searchItemSql += "'" + itemName + "',";
searchItemSql += "0,";
searchItemSql += tbsyncpojo.getTaskId() + ")";
JdbcTemplate template = dbTemplate.getJdbcTemplate();
template.execute(searchItemSql);
}
JdbcTemplate template = dbTemplate.getJdbcTemplate();
template.execute(hddxSql);
}

逗号,拼接

  或是这样 #动态字段映射# 的代码

 public PageInfo showTasks(SearchSMS searchSMS, int page) {
String sql = "select id from SMS_TASK sms_task where id = ? "
}
if (StringUtils.isNotBlank(searchSMS.getEndtime())) {
sql += "and createtime < to_date('" + searchSMS.getEndtime() + "','yyyy-mm-dd') + 1 ";
}
if (StringUtils.isNotBlank(searchSMS.getSendContent())) {
sql += "and id in (select TASKID from SMS_SYNC where TASKID=sms_task.id and msgcontent like '%" + searchSMS.getSendContent() + "%')";
}
if (StringUtils.isNotBlank(searchSMS.getSendPhone())) {
sql += "and id in (select TASKID from SMS_SYNC where TASKID=sms_task.id and mobile like '%" + searchSMS.getSendPhone() + "%')";
}

#动态字段映射#

  你一定感受过为了一个逗号而抓狂的经历,拼接的时候提醒自己一定不能忘了添加前后的空格和删除句末的逗号。

  幸运的是,通过动态SQL这样的问题在Mybatis中不复存在。通过<where>来智能识别语句前后的and/or,<set>来识别语句前后的逗号,或使用<trim>来自定义实现。

  通过<if test>来判断字段是否为空,<choose><when><otherwise>来实现类似switch……case的效果,<foreach>来实现集合的遍历,这里介绍了动态SQL。

   总结:Mybatis框架优越之处在于使用XML映射文件替代了JDBC中手工设置属性,降低SQL代码耦合性,将动态SQL与其他Java代码分离,使得代码看起来更加整洁并有利于重用;提供缓存、自动映射功能,并通过一系列设置合理的默认值来简化开发者的工作。

  

Mybatis3 框架理解的更多相关文章

  1. ssm框架理解

    SSM框架理解 最近两星期一直在学JavaEE的MVC框架,因为之前学校开的JavaEE课程就一直学的吊儿郎当的,所以现在真正需要掌握就非常手忙脚乱,在此记录下这段时间学习的感悟,如有错误,希望大牛毫 ...

  2. SSM框架理解(转)

    SSM框架理解 最近两星期一直在学JavaEE的MVC框架,因为之前学校开的JavaEE课程就一直学的吊儿郎当的,所以现在真正需要掌握就非常手忙脚乱,在此记录下这段时间学习的感悟,如有错误,希望大牛毫 ...

  3. mybatis中两种取值方式?谈谈Spring框架理解?

    1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...

  4. Flask 框架理解(一)

    Flask 框架理解(一) web 服务器 , web 框架 以及 WSGI 这里说的 web 服务器特指纯粹的 python HTTP 服务器(比如 Gunicorn,而不是 Apache,Ngin ...

  5. 遵循统一的机器学习框架理解高斯混合模型(GMM)

    遵循统一的机器学习框架理解高斯混合模型(GMM) 一.前言 我的博客仅记录我的观点和思考过程.欢迎大家指出我思考的盲点,更希望大家能有自己的理解. 本文参考了网络上诸多资料,特别是B站UPshuhua ...

  6. 遵循统一的机器学习框架理解SVM

    遵循统一的机器学习框架理解SVM 一.前言 我的博客仅记录我的观点和思考过程.欢迎大家指出我思考的盲点,更希望大家能有自己的理解. 本文参考了李宏毅教授讲解SVM的课程和李航大大的统计学习方法. 二. ...

  7. Web框架理解

    目录 1.web框架理解     2.http工作原理     3.通过函数实现浏览器和服务端通信案例     4.服务器程序和引用程序理解     5.jinja2渲染模板案例     6.Djan ...

  8. MVVM框架理解

    MVC框架 将整个前端页面分成View,Controller,Modal,视图上发生变化,通过Controller(控件)将响应传入到Model(数据源),由数据源改变View上面的数据. 整个过程看 ...

  9. Linux图像系统框架-理解X11与Qt的层次结构

    转:http://blog.csdn.net/kjfureone/article/details/52848550 1. 前言 图形子系统是linux系统中比较复杂的子系统之一:对下,它要管理形态各异 ...

随机推荐

  1. 射频识别技术漫谈(16)——Mifare UltraLight

    Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本.小容量的卡片.低成本,是指它是目前市场中价格最低的遵守ISO14443A协议的芯片 ...

  2. Apache RewriteCond RewriteRule 入门和Laravel去掉index.php

        Ci删除index.php办法: 创建.htaccess 文件放到网站的根目录下,文件中的内容如下: RewriteEngine onRewriteCond %{REQUEST_FILENAM ...

  3. C++模板:文件操作

    freopen("demo.in","r",stdin); freopen("demo.out","w",stdout) ...

  4. 【LeetCode】Path Sum 2 --java 二叉数 深度遍历,保存路径

    在Path SUm 1中(http://www.cnblogs.com/hitkb/p/4242822.html) 我们采用栈的形式保存路径,每当找到符合的叶子节点,就将栈内元素输出.注意存在多条路径 ...

  5. Intersecting Lines(数学)

    Intersecting Lines Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12844   Accepted: 57 ...

  6. CALayer3-层的属性

    一.隐式动画属性 * 在前面几讲中已经提到.每个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层). 全部的非Root Layer.也就是手动创建的 ...

  7. leetcode208 happynumber

    19 is a happy number 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1 class Solution {public ...

  8. CentOS环境下R语言的安装和配置

    最近在看数据统计和分析,想到了R语言,于是就着手在自己的CentOS环境下进行安装和配置.步骤如下: 1.前往R官网下载安装包. 2.解压压缩包:tar xvzf R-3.2.2.tar.gz 3.进 ...

  9. poj 2515 Birthday Cake

    /** 大意 : 求1^m + 2^m + 3^m + 4^m +....+ n^m 解题步骤: 先构造从0到m的第1阶差分序列,然后以下所有2---->p阶的差分表. 令C[n+1][1]=n ...

  10. SQL分页存储过程(不支持多表联合查询,不支持多字段排序)

    CREATE PROCEDURE [dbo].[Pro_GetPageOfRecords] @PageSize INT=20, --分页大小 @CurrentPage INT, --第几页 @Clum ...