mybatis基础系列(二)——基础语法、别名、输入映射、输出映射
增删改查
mapper根节点及其子节点
mybatis框架需要读取映射文件创建会话工厂,映射文件是以<mapper>作为根节点,在根节点中支持9个元素,分别为insert、update、delete、select(增删改查);cache、cache-ref、resultMap、parameterMap、sql。如下图:
命名空间
<mapper>根节点有个属性namespace,作用是对sql语句进行分类化管理。
select节点
占位符#{}
一个<select>代表一条查询语句,<select>常用属性有id,parameterType,resultType。<select>节点的内容为sql语句,其语法与平常写的sql语句相似,不同的地方是条件参数可以通过占位符#{}替换。例如:
sql语法:
SELECT * FROM t_emp WHERE empno=’7369’
mybitis中的语法:
SELECT * FROM t_emp WHERE empno=#{empno}
id:标志映射文件中的sql,通常id也称为statement的id。id的值就是xxxMapper.java中的方法名。
parameterType:执行sql语句中的输入参数的类型。
resultType:指定sql输出结果映射成java类型的对象。
#{}:表示一个占位符
#{id}:其中id表示接收输入的参数,参数名称就是id。#{}中的参数可以是任意对象。
示例与运行问题
EmpMapper.xml
<mapper namespace="com.itpsc.mapper.EmpMapper" > <select id="queryById" parameterType="int" resultType="com.itpsc.entity.Emp">
SELECT * FROM t_emp WHERE empno=#{empno}
</select> </mapper>
//EmpMapper.java
public interface EmpMapper extends BaseMapper<Emp> {
Emp queryById(Integer empno);
} //EmpService.java
public interface EmpService {
Emp queryById(Integer empno);
} //EmpServiceImpl.java
@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper,Emp> implements EmpService { public EmpServiceImpl() {
super();
};
public EmpServiceImpl(EmpMapper mapper) {
this.baseMapper = mapper;
};
@Override
public Emp queryById(Integer empno) {
return this.baseMapper.queryById(empno);
}
} //EmpTests.java
@RunWith(SpringRunner.class)
@SpringBootTest
public class EmpTests {
@Resource
private EmpService empService;
@Test
public void contextLoads() {
}
@Test
public void testQueryById() {
System.out.println(empService.queryById(7369));
}
}
运行报错:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.itpsc.mapper.EmpMapper.queryById
找不到xml,发现在idea编译后的classes路径下并没有相应的XML文件。
因为IDEA在编译的时候忽略掉了XML文件,一个解决方法是将所有的XML文件移动到Resource文件夹下,这样在编译的时候就会将XML文件一起。
另一个方法是配置Maven不过滤src/main/java目录下的.properties文件和.xml文件。
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
再次编译就看到了classes目录下有xml文件了。
运行test后输出:
Emp{empno=7369, ename='SMITH', job='CLERK', mgr=7902, hiredate=Wed Dec 17 00:00:00 CST 1980, sal=800.0, comm=null, deptno=20}
拼接${}
${}:用来拼接sql字符串,将接收到的参数内容不加任何修饰拼接在sql语句中。
sql语法:
SELECT * FROM t_emp WHERE ename LIKE 'SMITH';
mybitis中的语法:
<select id="queryLikeName" parameterType="String" resultType="com.itpsc.entity.Emp">
SELECT * FROM t_emp WHERE ename LIKE '${_parameter}'
</select>
注意
如果传入的参数类型为String类型,则参数名需统一修改为_parameter,不能将参数设为bean里的名称。
否则运行报错为:There is no getter for property named 'preCode' in 'class java.lang.String
insert节点
一个<insert>代表一条insert语句,和<select>节点一样,<insert>其语法与平常写的sql语句相似,不同的地方是条件参数可以通过占位符#{}替换。
sql语法:
insert into t_emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(7100,’itpsc’,’developer’,7902,’1980-12-10’,1000.00,200.00,20)
mybitis中的语法:
<insert id="add" parameterType="com.itpsc.entity.Emp">
insert into t_emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
values(#{empno},#{ename},#{job},#{mgr},#{hiredate,jdbcType=DATE},#{sal},#{comm},#{deptno})
</insert>
注意日期类型
mybatis日期类型的字段,要加jdbcType=DATE。否则会报错:There is no getter for property named 'hirdate' in 'class com.itpsc.entity.Emp'。
Mybatis中javaType和jdbcType对应关系
JDBC Type Java Type
CHAR String
VARCHAR String
LONGVARCHAR String
NUMERIC java.math.BigDecimal
DECIMAL java.math.BigDecimal
BIT boolean
BOOLEAN boolean
TINYINT byte
SMALLINT short
INTEGER int
BIGINT long
REAL float
FLOAT double
DOUBLE double
BINARY byte[]
VARBINARY byte[]
LONGVARBINARY byte[]
DATE java.sql.Date
TIME java.sql.Time
TIMESTAMP java.sql.Timestamp
CLOB Clob
BLOB Blob
ARRAY Array
DISTINCT mapping of underlying type
STRUCT Struct
REF Ref
DATALINK java.net.URL
insert与非自增主键返回
有时候新增记录之后,需要这条新增记录的主键,以便业务使用,但是新增之后再将其查询出来明显不合理,效率也变低了。mybatis可以将insert的记录的主键返回。使用mysql的uuid()函数生成主键,需要修改表中id字段类型为string,长度设置成35位。
mybatis的<selectKey>可以帮我们实现。Insert之前先通过uuid()查询到主键,将主键输入到sql语句中。
UserMapper.xml
<mapper namespace="com.itpsc.mapper.UserMapper" >
<insert id="adduser" parameterType="com.itpsc.entity.User">
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT uuid()
</selectKey>
insert into t_user(id,name,password,phone) values(#{id},#{name},#{password},#{phone})
</insert>
</mapper>
测试
@Test
public void testAddUser() {
User user = new User();
//user.setId(1L);
user.setName("uuid name1");
user.setPassword("98764");
user.setPhone("13877711111");
System.out.println(userService.adduser(user));
System.out.println(user.getId());
} 输出: 1
9a64919e-b02f-11e8-8b1f-f48e38ec6bad
insert与自增主键返回
再将user表中的id字段修改为Bigint类型,并设为自增。User.java中id修改为Long类型。通过mysql函数LAST_INSERT_ID()获取到刚插入记录的自增主键,是insert之后调用此函数。
<insert id="getIdAfterAdduser" parameterType="com.itpsc.entity.User">
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into t_user(name,password,phone) values(#{name},#{password},#{phone})
</insert>
@Test
public void getIdAfterAdduser() {
User user = new User();
user.setName("auto add id");
user.setPassword("98764");
user.setPhone("13877711111");
System.out.println(userService.getIdAfterAdduser(user));
System.out.println(user.getId());
} 运行输出:
1
3
delete节点
sql语法:
delete FROM t_user WHERE id=3
mybitis中的语法:
delete FROM t_user WHERE id=#{id}
<delete id="delete" parameterType="java.lang.Long">
DELETE from t_user WHERE id=#{id}
</delete>
update节点
<update id="updateById" parameterType="com.itpsc.entity.User">
UPDATE t_user set NAME=#{name},password=#{password},phone=#{phone} WHERE id=#{id}
</update>
把整个java对象传入,要更新哪些字段sql语句决定。
占位符与拼接符小结
#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型也可以是复杂的数据类型。#{}接收对象值,通过OGNL语法(user.username)读取对象中的属性值。
${}表示一个拼接符号,会引用sql注入,不建议使用${}。${}接收输入参数,类型可以是简单类型也可以是复杂数据类型。${}接收对象值,通过OGNL语法(user.username)读取对象中的属性值。
出入参定义别名
批量定义别名
在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。
如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。
在springboot 的yml配置文件中通过type-aliases-package定义别名,在对parameterType或resultType指定的类型中就可以省略包名。
mybatis-plus:
mapper-locations: "classpath:com/itpsc/mapper/**/*.xml"
type-aliases-package: "com.itpsc.entity"
global-config:
db-column-underline: true <insert id="adduser" parameterType="User">
insert into t_user(name,password,phone) values(#{name},#{password},#{phone})
</insert>
输入映射
parameterType
前面我们学习的输入都是简单对象,如果输入参数的类型是复杂对象(包装对象),该怎么写呢。
<select id="queryList" parameterType="com.itpsc.request.EmpRequest" resultType="com.itpsc.vo.EmpVo">
SELECT * FROM t_emp WHERE deptno=#{emp.deptno} and job=#{emp.job}
</select>
public interface EmpMapper extends BaseMapper<Emp> {
//...
EmpVo queryList(EmpRequest request);
} public class EmpRequest{
private Emp emp;
//其它条件
public Emp getEmp() {
return emp;
}
public void setEmp(Emp emp) {
this.emp = emp;
}
} public class EmpVo extends Emp{
//...
}
使用parameterType进行输入映射,类型是包装对象,但是占位符里用的是被包装对象的属性。通过#{emp.deptno}取出被包装对象的deptno属性。
输出映射
resultType
运行测试方法报错:
org.mybatis.spring.MyBatisSystemException:
nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4
返回数据类型由xxxMapper.java接口中声明的方法的返回类型和xxxMapper.xml文件共同决定。如果mapper方法返回单个对象(非集合对象),代理对象内部通过selectOne查询数据库。如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。不论是返回单一对象还是对象列表,xxxMapper.xml中的配置都是一样的,都是resultMap=”***Map”或resultType=“* .* .*”类型。
例如:
返回单个对象resultType的值为"com.itpsc.entity.Emp"
返回多个对象resultType的值也是"com.itpsc.entity.Emp"
所以将mapper方法的返回类型声明为List<Emp>即可。
使用resultType进行输出映射,只有查询出来的列名和对象中的属性名一致,该列才可以映射成功。如果查询出来的列名和对象中的属性名全部不一致,没有创建对象。只要查询出来的列名和对象中的属性有一个一致,就会创建对象。
如果我们把上面例子中的EmpVo 不继承Emp,查询出来就不创建对象。如下图
resultMap
如果查询出来的列名和对象的属性名不一致,通过定义一个resultMap对列名和对象属性名之间作一个映射关系。
1、定义resultMap
2、使用resultMap作为statement的输出映射类型
<resultMap id="userMap" type="com.itpsc.entity.Emp" >
<result column="_empno" property="empnum" jdbcType="INTEGER" />
<result column="_ename" property="ename" jdbcType="VARCHAR" />
<result column="_job" property="job" jdbcType="VARCHAR" />
<result column="_mgr" property="mgr" jdbcType="INTEGER" />
<result column="_hiredate" property="hiredate" jdbcType="DATE" />
<result column="_sal" property="sal" jdbcType="REAL" />
<result column="_comm" property="comm" jdbcType="REAL" />
<result column="_deptno" property="deptno" jdbcType="INTEGER" />
</resultMap> <select id="queryById" parameterType="int"resultMap ="userMap">
SELECT empno _empno,ename _ename,job _job,mgr _mgr,hiredate _hiredate,sal _sal,comm _comm,deptno _deptno FROM t_emp WHERE empno=#{empno}
</select>
本篇到此结束,下篇预告mybatis基础系列(三)——动态sql。
mybatis基础系列(二)——基础语法、别名、输入映射、输出映射的更多相关文章
- mybatis入门系列二之输入与输出参数
mybatis入门系列二之详解输入与输出参数 基础知识 mybatis规定mapp.xml中每一个SQL语句形式上只能有一个@parameterType和一个@resultType 1. 返回 ...
- 【C++自我精讲】基础系列二 const
[C++自我精讲]基础系列二 const 0 前言 分三部分:const用法.const和#define比较.const作用. 1 const用法 const常量:const可以用来定义常量,不可改变 ...
- MyBatis 框架系列之基础初识
MyBatis 框架系列之基础初识 1.什么是 MyBatis MyBatis 本是 apache 的一个开源项目 iBatis,后改名为 MyBatis,它 是一个优秀的持久层框架,对 jdbc 的 ...
- MyBatis学习系列二——增删改查
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring 数据库的经典操作:增删改查. 在这一章我们主要说明一下简单的查询和增删改, ...
- (转)MyBatis框架的学习(四)——Mapper.xml文件中的输入和输出映射以及动态sql
http://blog.csdn.net/yerenyuan_pku/article/details/71893689 前面对MyBatis框架的学习中,我们对Mapper.xml映射文件多少有些了解 ...
- Python3基础系列-基本入门语法
本文简单地介绍了python的一些基本入门知识,通过对这些知识的了解,大家可以写一些简单的代码,同时也为后面深入理解打下基础.本文的主要内容如下: 值和类型 值,即value,通常有:1,2,3.14 ...
- Python 基础【第三篇】输入和输出
这里我们创建一个python(pytest)脚本用于学习测试(以后都为这个文件,不多做解释喽),这个文件必须要有执行权限的哈 1.创建pytest并赋予执行权限 [root@fengyuba_serv ...
- 【Mybatis架构】输入、输出映射
前言综述: 其实在我们分析Mybatis的查询缓存或者是一些简介的时候,我们就不难看到有关于Mybatis输入输出映射的东西,比如说: 但是一直没有想起来系统的来总结一下这方面的相关知识,偶然看到 ...
- JAVAEE——Mybatis第二天:输入和输出映射、动态sql、关联查询、Mybatis整合spring、Mybatis逆向工程
1. 学习计划 1.输入映射和输出映射 a) 输入参数映射 b) 返回值映射 2.动态sql a) If标签 b) Where标签 c) Sql片段 d) Foreach标签 3.关联查询 a) 一对 ...
- mybatis 输入、输出映射
一.输入映射 mapper.xml的参数只有一个.可以传参数,基本简单类型,hashmap和javabean (一).Javabean的方法. 需求:通过小说名和作者模糊找书. 1.定义Javabea ...
随机推荐
- HighCharts使用更多图表HighChartsMore
添加highcharts-moreimport HighCharts from 'highcharts'import highchartsMore from 'highcharts/highchart ...
- Spring容器的创建刷新过程
Spring容器的创建刷新过程 以AnnotionConfigApplicationContext为例,在new一个AnnotionConfigApplicationContext的时候,其构造函数内 ...
- canvas-star1.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- js 绘制数学函数
<!-- <!doctype html> --> <html lang="en"> <head> <meta charset= ...
- jQuery中是事件绑定方式--on、bind、live、delegate
概述:jQuery是我们最常用的js库,对于事件的绑定也是有很多种,on.one.live.bind.delegate等等,接下来我们逐一来进行讲解. 本片文章中事件所带的为版本号,例:v1.7+为1 ...
- python2&python3
1.Python3 使用 print 必须要以小括号包裹打印内容,比如 print('hi') Python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容,比如 print 'hi ...
- sql server:Monty Hall problem (蒙提霍尔问题)
--------------------------------------------------------------------- -- Auxiliry Table of Numbers 数 ...
- 禁用 Gnome Shell 默认的 Ubuntu Dock 和 Ubuntu AppIndicators 扩展
以前折腾的时候禁用过,现在已经忘记目录了,结果今天手贱把系统从 18.04 升级到了 18.10 ,很多东西都要重新搞过,而且用惯了 mac 已经不熟悉 linux 上瞎折腾的那一套了,简直坑爹.. ...
- CSS格式化排版--排版
1.文字排版--字体:利用font-family设置字体,注意设置的字体必须是本地电脑中存在的字体. 例子:class="MicrosoftYahei"的h1标签的字体设置为 宋体 ...
- 探讨PHP页面跳转几种实现技巧 转自# 作者:佚名 来源:百度博客 #
Web系统中,从一个网页跳转到另一个网页,是LAMP项目中最常用的技术之一.页面跳转可能是由于用户单击链接.按钮等引发的,也可能是系统自动产生的. 此处介绍PHP中常用的实现页面自动跳转的方法. PH ...