java web(七): mybatis的动态sql和mybatis generator自动生成pojo类和映射文件
前言:
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类和映射文件的更多相关文章
- 使用eclipse插件mybatis generator来自动生成实体类及映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguratio ...
- Java的generator工具类,数据库生成实体类和映射文件
首先需要几个jar包: freemarker-2.3.23.jar log4j-1.2.16.jar mybatis-3.2.3.jar mybatis-generator-core-1.3.2.ja ...
- mybatis generator自动生成 实体类, sqlmap配置文件 详细介绍
我使用的是Eclipse Luna 装了自己常用的插件, generator也是其中一个推荐下载 MyBatis_Generator_1.3.1.zip离线安装包 <?xml version=& ...
- SpringBoot整合Mybatis 使用generator自动生成实体类代码、Mapper代码、dao层代码
1.新建一个SpringBoot项目,并引入Mybatis和mybatis-generator相关的依赖. <dependency> <groupId>org.springfr ...
- mybatis根据表逆向自动化生成代码(自动生成实体类、mapper文件、mapper.xml文件)
.personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...
- 一分钟带你了解下MyBatis的动态SQL!
MyBatis的强大特性之一便是它的动态SQL,以前拼接的时候需要注意的空格.列表最后的逗号等,现在都可以不用手动处理了,MyBatis采用功能强大的基于OGNL的表达式来实现,下面主要介绍下. 一. ...
- MyBatis的动态SQL详解
MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑,本文详解mybatis的动态sql,需要的朋友可以参考下 MyBatis 的一个强大的特性之一通常是它 ...
- mybatis 使用动态SQL
RoleMapper.java public interface RoleMapper { public void add(Role role); public void update(Role ro ...
- MyBatis框架——动态SQL、缓存机制、逆向工程
MyBatis框架--动态SQL.缓存机制.逆向工程 一.Dynamic SQL 为什么需要动态SQL?有时候需要根据实际传入的参数来动态的拼接SQL语句.最常用的就是:where和if标签 1.参考 ...
随机推荐
- Lintcode105 Copy List with Random Pointer solution 题解
[题目描述] A linked list is given such that each node contains an additional random pointer which could ...
- eclipse中svn上传及更新
- windows图形图像桌面消失(误删.net组件)
核心模式core 变回完整模式 Full,用dism命令,具体命令如下 dism /online /enable-feature /all /featurename:servercore-fullse ...
- hbase大规模数据写入的优化历程 ,ZZ
http://blog.csdn.net/zbc1090549839/article/details/51582817
- mean
import caffe import numpy as np MEAN_PROTO_PATH = 'mean.binaryproto' # 待转换的pb格式图像均值文件路径 MEAN_NPY_PAT ...
- 广工十四届校赛 count 矩阵快速幂
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6470 题意:求,直接矩阵快速幂得f(n)即可 构造矩阵如下: n^3是肯定得变换的,用二项式展开来一点 ...
- 『TensorFlow』网络操作API_中_损失函数及分类器
一.误差值 度量两个张量或者一个张量和零之间的损失误差,这个可用于在一个回归任务或者用于正则的目的(权重衰减). l2_loss tf.nn.l2_loss(t, name=None) 解释:这个函数 ...
- Matlab:Crank Nicolson方法求解线性抛物方程
tic; clear clc M=[,,,,,,];%x的步数 K=M; %时间t的步数 :length(M) hx=/M(p); ht=/K(p); r=ht/hx^; %网格比 x=:hx:; t ...
- HTTP 错误 500.19 - Internal Server Error v4.0.30319
1 打开运行,输入cmd进入到命令提示符窗口.2 进入到C:\Windows\Microsoft.NET\Framework\v4.0.30319 目录.3 输入aspnet_regiis.exe - ...
- 【sparkSQL】SparkSession的认识
https://www.cnblogs.com/zzhangyuhang/p/9039695.html https://www.jianshu.com/p/dea6a78b9dff 在Spark1.6 ...