前言:

  MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据

不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。

利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

  Mybatis Generator可以帮我们根据数据库表自动生成pojo类和SQL映射文件,SQL映射文件提供了增删改查功能。


        动态SQL

到网上找一个经典的mysql数据库表

CREATE TABLE `emp` (
  #编号
  `empno` int(11) NOT NULL,
  #姓名
  `ename` varchar(255) NOT NULL,
  #职位
  `job` varchar(255) DEFAULT NULL,
  `mgr` int(11) DEFAULT NULL,
  #入职时间
  `hiredate` date NOT NULL,
  #薪水
  `sal` decimal(7,2) DEFAULT NULL,
  #奖金级别
  `comm` decimal(7,2) DEFAULT NULL,
  #部门编号
  `deptno` int(11) DEFAULT NULL,
  PRIMARY KEY (`empno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

#部门表
CREATE TABLE `dept` (
  #部门编号
  `deptno` int(11) NOT NULL,
  #部门名称
  `dname` varchar(255) NOT NULL,
  #部门地址
  `loc` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`deptno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO emp VALUES(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp VALUES(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp VALUES(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp VALUES(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp VALUES(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp VALUES(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp VALUES(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp VALUES(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp VALUES(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp VALUES(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp VALUES(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);

INSERT INTO dept VALUES(10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept VALUES(20, 'RESEARCH', 'DALLAS');
INSERT INTO dept VALUES(30, 'SALES', 'CHICAGO');
INSERT INTO dept VALUES(40, 'OPERATIONS', 'BOSTON');


表准备完成之后,开始编写动态SQL语句

If

动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。

<select id="selectEmployeeByCondition1" parameterType="Employee"
resultMap="EmployeeBaseMap">
select * from emp
where 1 = 1
<if test="empno != null">
and empno = #{empno}
</if>
<if test="ename != null">
and ename like #{ename}
</if>
<if test="job != null">
and job = #{job}
</if>
</select>

这条语句会根据empno,ename,job是否为空插入条件, " where 1 =  1 "是为了避免3个条件都为空出现"select * from emp where "这种SQL语句。

每个if条件之间必须显式用and或or进行连接。

choose,when,otherwise

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素

choose类似if else if  else,只会选择中一个条件执行。

  <!-- choose -->
<select id="selectEmployeeByCondition2" parameterType="Employee"
resultMap="EmployeeBaseMap">
select * from emp
where
<choose>
<when test="empno != null">
empno = #{empno}
</when>
<when test="ename">
ename like #{ename}
</when>
<when test="job != null">
job = #{job}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</select>

如果三个when条件都不满足,则会选中<otherwise>拼接到where条件后面!

where   set   trim

上面的几条动态SQL语句都会加上where条件,有时候我们希望如果条件都不满足的情况下不加where字句。

  <select id="selectEmployeeByCondition3" parameterType="Employee"
resultMap="EmployeeBaseMap">
select * from emp
<where>
<if test="empno != null">
and empno = #{empno}
</if>
<if test="ename != null">
and ename like #{ename}
</if>
<if test="job != null">
and job = #{job}
</if>
</where>
 </select>

where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。

而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。

和where等价的trim

  <select id="selectEmployeeByCondition4" parameterType="Employee"
resultMap="EmployeeBaseMap">
select * from emp
<trim prefix="where" prefixOverrides="and | or">
<if test="empno != null">
and empno = #{empno}
</if>
<if test="ename != null">
and ename like #{ename}
</if>
<if test="job != null">
and job = #{job}
</if>
</trim>
</select>

<trim> 标签有两个属性,prefix是指定插入的内容,prefixOverrides属性会忽略通过管道分隔的文本序列。

它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。

假设一和三条件满足,SQL语句就会变成 " select * from emp where empno = #{empno} and job = #{job} ";

<set>标签是专门为更新语句而准备的。

  <update id="updateEmployee" parameterType="Employee">
update emp
<set>
<if test="ename != null">
ename = #{ename},
</if>
<if test="job != null">
job = #{job},
</if>
<if test="mgr != null">
mgr = #{mgr},
</if>
<if test="salary != null">
sal = #{salary},
</if>
<if test="comment != null">
comm = #{comment},
</if>
<if test="dept != null and dept.deptNo != null">
deptno = #{dept.deptNo}
</if>
</set>
where empno = #{empno}
</update>

set 元素可以用于动态包含需要更新的列,而舍去其它的

这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,

因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。

当然trim也可以完成set标签的功能

  <update id="updateEmployee2" parameterType="Employee">
update emp
<trim prefix="set" prefixOverrides=",">
<if test="ename != null">
ename = #{ename},
</if>
<if test="job != null">
job = #{job},
</if>
<if test="mgr != null">
mgr = #{mgr},
</if>
<if test="salary != null">
sal = #{salary},
</if>
<if test="comment != null">
comm = #{comment},
</if>
<if test="dept != null and dept.deptNo != null">
deptno = #{dept.deptNo}
</if>
</trim>
where empno = #{empno}
</update>

forEach

动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。

  <select id="selectEmployeeByEmpnos" parameterType="list" resultMap="EmployeeBaseMap">
select * from emp
where empno in
<foreach collection="list" open="(" close=")" item="item" index="index" separator=",">
#{item}
</foreach>
</select>

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和

索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。

这个元素是很智能的,因此它不会偶然地附加多余的分隔符。

注意: 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。

当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。

当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

动态SQL介绍完毕,这里提供一下完整的映射文件和映射接口。

映射文件:

<?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.briup.mapper.DynamicMapper">
<!-- 告诉数据库如何加载数据到类的那个属性上 -->
<resultMap type="Employee" id="EmployeeBaseMap">
<id column="empno" property="empno"/>
<result column="ename" property="ename"/>
<result column="job" property="job"/>
<result column="mgr" property="mgr"/>
<result column="hiredate" property="hiredate"/>
<result column="sal" property="salary"/>
<result column="comm" property="comment"/>
</resultMap> <resultMap type="Deptarment" id="DeptarmentBaseMap">
<id column="deptno" property="deptNo"/>
<result column="dname" property="dName"/>
<result column="loc" property="loc"/>
</resultMap> <!-- if -->
<select id="selectEmployeeByCondition1" parameterType="Employee"
resultMap="EmployeeBaseMap">
select * from emp
where 1 = 1
<if test="empno != null">
and empno = #{empno}
</if>
<if test="ename != null">
and ename like #{ename}
</if>
<if test="job != null">
and job = #{job}
</if>
</select> <!-- choose -->
<select id="selectEmployeeByCondition2" parameterType="Employee"
resultMap="EmployeeBaseMap">
select * from emp
where
<choose>
<when test="empno != null">
empno = #{empno}
</when>
<when test="ename">
ename like #{ename}
</when>
<when test="job != null">
job = #{job}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</select> <!-- where trim set -->
<select id="selectEmployeeByCondition3" parameterType="Employee"
resultMap="EmployeeBaseMap">
select * from emp
<where>
<if test="empno != null">
and empno = #{empno}
</if>
<if test="ename != null">
and ename like #{ename}
</if>
<if test="job != null">
and job = #{job}
</if>
</where>
</select> <select id="selectEmployeeByCondition4" parameterType="Employee"
resultMap="EmployeeBaseMap">
select * from emp
<trim prefix="where" prefixOverrides="and | or">
<if test="empno != null">
and empno = #{empno}
</if>
<if test="ename != null">
and ename like #{ename}
</if>
<if test="job != null">
and job = #{job}
</if>
</trim>
</select> <update id="updateEmployee" parameterType="Employee">
update emp
<set>
<if test="ename != null">
ename = #{ename},
</if>
<if test="job != null">
job = #{job},
</if>
<if test="mgr != null">
mgr = #{mgr},
</if>
<if test="salary != null">
sal = #{salary},
</if>
<if test="comment != null">
comm = #{comment},
</if>
<if test="dept != null and dept.deptNo != null">
deptno = #{dept.deptNo}
</if>
</set>
where empno = #{empno}
</update> <update id="updateEmployee2" parameterType="Employee">
update emp
<trim prefix="set" prefixOverrides=",">
<if test="ename != null">
ename = #{ename},
</if>
<if test="job != null">
job = #{job},
</if>
<if test="mgr != null">
mgr = #{mgr},
</if>
<if test="salary != null">
sal = #{salary},
</if>
<if test="comment != null">
comm = #{comment},
</if>
<if test="dept != null and dept.deptNo != null">
deptno = #{dept.deptNo}
</if>
</trim>
where empno = #{empno}
</update> <select id="selectEmployeeByEmpnos" parameterType="list" resultMap="EmployeeBaseMap">
select * from emp
where empno in
<foreach collection="list" open="(" close=")" item="item" index="index" separator=",">
#{item}
</foreach>
</select>
</mapper>

映射接口:

package com.briup.mapper;

import java.util.List;

import com.briup.bean.Employee;

public interface DynamicMapper {

    public abstract List<Employee> selectEmployeeByCondition1(Employee emp);

    public abstract List<Employee> selectEmployeeByCondition2(Employee emp);

    public abstract List<Employee> selectEmployeeByCondition3(Employee emp);

    public abstract List<Employee> selectEmployeeByCondition4(Employee emp);

    public abstract void updateEmployee(Employee emp);

    public abstract List<Employee> selectEmployeeByEmpnos(List<Integer> empnos);
}

mybatis Generator在ecplise中的使用

mybatis生成器(mbg)是mybatis mybatis和ibatis的代码生成器。它将为mybatis的所有版本生成代码,

并在版本2.2.0之后生成ibatis的版本。它将内省一个数据库表(或多个表),并生成可用于访问表的工件。

这减少了设置对象和配置文件以与数据库表交互的初始麻烦。MBG试图对大部分简单的CRUD(创建、检索、更新、删除)

数据库操作产生重大影响。您仍然需要为连接查询或存储过程手工编写SQL和对象代码。

MyBatis Generator will generate:

         *Java POJOs that match the table structure.

         *MyBatis/iBATIS Compatible SQL Map XML Files. MBG generates SQL for simple CRUD    functions on each table in a configuration.

         *Java client classes that make appropriate use of the above objects.

1.安装Mybatis Generator插件

  help --> Ecplise Marketplace...

然后搜索mybats,点击安装Mybatis Generator 1.3.7

2.创建配置文件

  右键点击java项目,选择 " New -- > Other... " 然后搜索mybatis,选中Mybatis Generator configuration File。

3.准备一些包和目录

在项目下创建一个目录lib,把连接mysql数据库的jar包放进去,我这里是msql-connector-java-5.1.47.jar

创建包com.briup.bean 和 com.briup.mapper,等下自动生成的pojo类和映射文件会放到这下面。

4.修改配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- mybatis-generator的核心配置文件 -->
<generatorConfiguration>
<!-- 连接数据库用到的jar包 -->
<classPathEntry
location="G:\java-code-2\mybatis-generator\lib\mysql-connector-java-5.1.47.jar" /> <context id="DB2Tables" targetRuntime="MyBatis3">
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://188.131.246.182:3306/cnblogs" userId="study"
password="123456">
<!-- 生成primary key方法 -->
<property name="userInformationSchema" value="true" />
</jdbcConnection> <!--指定生成的类型为java类型,避免数据库中number等类型字段 -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver> <!--自动生成的实体的存放包路径 -->
<javaModelGenerator targetPackage="com.briup.bean"
targetProject="mybatis-generator/src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator> <!--自动生成的*Mapper.xml文件存放路径 -->
<sqlMapGenerator targetPackage="com.briup.mapper"
targetProject="mybatis-generator/src">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator> <!--自动生成的*Mapper.java存放路径 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.briup.mapper" targetProject="mybatis-generator/src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator> <!-- 映射配置 -->
<table tableName="emp" domainObjectName="Employee"></table>
<table tableName="dept" domainObjectName="Deptarment"></table>
</context>
</generatorConfiguration>

5.运行配置文件

右键点击generatorConfig.xml文件,选择 'Run As' , 'Run Mybatis Generator'。

6.简单的介绍如何使用Mybatis Generator生成的映射文件进行增删改查。

如果你去看xml文件,会发现里面使用了动态的SQL语句,不过又额外的增加了一些东西。有兴趣的可以研究一下。

使用之前还需要把环境搭建好,什么mybatis-config.xml全局配置文件以及其他的都要准备好,上一篇随笔有如何在ecplise搭建一个mybatis项目。

由于自动生成的pojo类中toString都没有重写,不好看结果,我利用ecplise自动生成toString方法。

0)使用案例0

@SuppressWarnings("unused")
@Test
public void test0() {
SqlSession session = null;
try {
session = MySqlSessionFactory.opensession();
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); // 查询所有员工信息
EmployeeExample example = new EmployeeExample();
List<Employee> list = mapper.selectByExample(example);
System.out.println("list.size(): " + list.size());
for(Employee e: list)
System.out.println("name: " + e.getEname());
} catch (IOException e) {
if(session != null)
session.close();
e.printStackTrace();
}
}

1)使用案列1

查询工资大于1200的员工姓名和工资

@SuppressWarnings("unused")
@Test
public void test1() {
SqlSession session = null;
try {
session = MySqlSessionFactory.opensession();
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); // 查询工资大于1200的员工姓名和工资
EmployeeExample example = new EmployeeExample();
Criteria criteria = example.createCriteria();
// 添加查询条件
criteria.andSalGreaterThan(new BigDecimal(1200));
List<Employee> list = mapper.selectByExample(example);
System.out.println("list.size(): " + list.size() + " and list: " + list );
} catch (IOException e) {
if(session != null)
session.close();
e.printStackTrace();
}
}

  2)使用案列2

选择工资不在500到1200的员工的姓名和工资

@SuppressWarnings("unused")
@Test
public void test2() {
SqlSession session = null;
try {
session = MySqlSessionFactory.opensession();
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); // 选择工资不在500到1200的员工的姓名和工资
EmployeeExample example = new EmployeeExample();
Criteria criteria = example.createCriteria();
// 添加查询条件
criteria.andSalNotBetween(new BigDecimal(500), new BigDecimal(1200));
List<Employee> list = mapper.selectByExample(example);
System.out.println("list.size(): " + list.size());
for(Employee e: list)
System.out.println("salary: " + e.getSal());
} catch (IOException e) {
if(session != null)
session.close();
e.printStackTrace();
}
}

3)使用案例3

选择姓名中有字母a和e的员工

@SuppressWarnings({ "unused" })
@Test
public void test3() {
SqlSession session = null;
try {
session = MySqlSessionFactory.opensession();
EmployeeMapper mapper = session.getMapper(EmployeeMapper.class); // 选择姓名中有字母a和e的员工
EmployeeExample example = new EmployeeExample();
Criteria criteria = example.createCriteria();
// 添加查询条件
criteria.andEnameLike("%a%");
criteria.andEnameLike("%e%");
List<Employee> list = mapper.selectByExample(example);
System.out.println("list.size(): " + list.size());
for(Employee e: list)
System.out.println("name: " + e.getEname());
} catch (IOException e) {
if(session != null)
session.close();
e.printStackTrace();
}
}

  注:如何需要联合查询还需要自己写sql语句,mybatsi Generator生成的SQL映射文件只提供增删改查功能。

备注:mybais generator项目已经在百度网盘分享。

地址:https://pan.baidu.com/s/1ZrFsu1CcMtrBCmvk9y5IDQ

提取码:2tk9

java web(七): mybatis的动态sql和mybatis generator自动生成pojo类和映射文件的更多相关文章

  1. 使用eclipse插件mybatis generator来自动生成实体类及映射文件

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguratio ...

  2. mybatis generator自动生成 实体类, sqlmap配置文件 详细介绍

    我使用的是Eclipse Luna 装了自己常用的插件, generator也是其中一个推荐下载 MyBatis_Generator_1.3.1.zip离线安装包 <?xml version=& ...

  3. SpringBoot整合Mybatis 使用generator自动生成实体类代码、Mapper代码、dao层代码

    1.新建一个SpringBoot项目,并引入Mybatis和mybatis-generator相关的依赖. <dependency> <groupId>org.springfr ...

  4. mybatis根据表逆向自动化生成代码(自动生成实体类、mapper文件、mapper.xml文件)

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

  5. 一分钟带你了解下MyBatis的动态SQL!

    MyBatis的强大特性之一便是它的动态SQL,以前拼接的时候需要注意的空格.列表最后的逗号等,现在都可以不用手动处理了,MyBatis采用功能强大的基于OGNL的表达式来实现,下面主要介绍下. 一. ...

  6. MyBatis的动态SQL详解

    MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑,本文详解mybatis的动态sql,需要的朋友可以参考下 MyBatis 的一个强大的特性之一通常是它 ...

  7. mybatis 使用动态SQL

    RoleMapper.java public interface RoleMapper { public void add(Role role); public void update(Role ro ...

  8. MyBatis框架——动态SQL、缓存机制、逆向工程

    MyBatis框架--动态SQL.缓存机制.逆向工程 一.Dynamic SQL 为什么需要动态SQL?有时候需要根据实际传入的参数来动态的拼接SQL语句.最常用的就是:where和if标签 1.参考 ...

  9. MyBatis探究-----动态SQL详解

    1.if标签 接口中方法:public List<Employee> getEmpsByEmpProperties(Employee employee); XML中:where 1=1必不 ...

随机推荐

  1. Linux的原子操作与同步机制

    Linux的原子操作与同步机制   .进程1执行完“mov eax, [count]”后,寄存器eax内保存了count的值0.此时,进程2被调度执行,抢占了进程1的CPU的控制权.进程2执行“cou ...

  2. php实现设计模式之 观察者模式

    代码片段一: <?php /** * 观察者模式:定于对象间的一种一对多的依赖关系,当一个对象发生改变时,所有依赖它的对象都收到通知并自动更新. */ //例子:少林方丈的通讯录,当扫地僧的号码 ...

  3. rails再体验(第一个程序)

    掌握redmine plugin开发的目标在2016年未实现,2017年继续. 选择<Ruby on Rails Tutorial>教程,windows安装railsinstaller,该 ...

  4. 局部变量&amp;&amp;malloc函数&amp;&amp;生命周期的一些见解

    最近在温习指针的部分时发现了一个有趣的问题,先看以下程序: //1.c #include<stdio.h> int* fun() { int t = 567; return &t; ...

  5. android之apk反编译

    今天就来详细的讲一讲apk的反编译过程,之前自己一直没彻底搞清楚. 一.准备工作 反编译首先要准备三个工具.这三个工具都是可以百度下载的.就是下图所示的三个工具. 这三个工具是有各自作用的: (1)a ...

  6. jquery的$.ajax async使用详解

      async在jquery ajax中是一个同步参数了,我们下面来给大家介绍在jquery ajax中使用async时碰到的一些问题与方法介绍,希望例子能给各位同学带来一些帮助哦.   async默 ...

  7. PDO(PHP Data Object),Mysqli,以及对sql注入等问题的解决

    这篇是上一篇 http://www.cnblogs.com/charlesblc/p/5987951.html 的续集. 看有的文章提到mysqli和PDO都支持多重查询,所以下面的url会造成表数据 ...

  8. mysql left( right ) join使用on 与where 筛选的差异

    有这样的一个问题mysql查询使用mysql中left(right)join筛选条件在on与where查询出的数据是否有差异. 可能只看着两个关键字看不出任何的问题.那我们使用实际的例子来说到底有没有 ...

  9. PHP中的一个很好用的文件上传类

    <?php    class FileUpload{      private $filepath; //设置上传文件的路径   private $allowtype=array('jpg',' ...

  10. Android复制iPhone日期和时间选择器

    看效果图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGluZ2xvbmd4aW4yNA==/font/5a6L5L2T/fontsize/400/fi ...