内容简介:MyBatis学习笔记(2)—映射关系篇MyBatis学习笔记(1)—使用篇
...敬请期待
通过上一篇的入门 MyBatis学习笔记(1)—使用篇 ,可以发现除了一些基本配置外,Mybatis的精华就在于Mapper(映射)部分。Mybatis是针对映射器构造的 SQL 构建的轻量级框架,并且可以通过配置生成对应的JavaBean给调用者。在Mybatis中可以灵活使用SQL来满足各种不同场景的需求,所以在互联网企业内更偏爱于使用Mybatis来应对高速变化的需求,而传统企业更偏向于使用Hibernate。
映射器的主要元素
上一节我们仅仅定义了一个select语句:
<mapper namespace="com.shuqing28.dao.CommodityDao"> <select id="getAllCommodity" resultType="com.shuqing28.pojo.Commodity"> SELECT * FROM commodity </select> </mapper>
实际上增删改查在Mybatis映射器里面都有对应的元素
元素名称 | 描述 | 备注 |
---|---|---|
select | 查询语句,最常用的 | 可以自定义参数,返回结果集 |
insert | 插入语句 | 执行后返回一个整数,代表插入的条数 |
update | 更新语句 | 执行后返回一个整数,代表更新的条数 |
delete | 删除语句 | 执行后返回一个整数,代表删除的条数 |
parameterMap | 定义参数映射关系 | 即将被删除的元素,不建议使用 |
sql | 允许定义一部分的SQL,然后在各个地方引用 | 例如,定义一个表名,在其它地方的SQL语句中使用 |
resultMap | 用来描述从数据库结果集中加载对象 | 它将提供映射规则 |
cache | 给定命名空间的缓存配置 | ———— |
cache-ref | 其他命名空间缓存配置的引用 | ———— |
下面我们探究主要使用的几个元素
select
select元素是我们最常用的元素,正如在SQL里是查询功能也是最主要的功能之一。在我们常识里,查询语句通常都是根据 一个或者多个 条件,查询数据库 返回一个,多个或者所有字段 。之前我们举得 getAllCommodity
没有查询条件,返回所有字段。
在Mybatis里,我们可以传入简单的参数类型,像int,float,String这些,也可以传入一些复杂的类型,比如JavaBean、Map之流的,Mybatis把这些参数转换成SQL语句需要的类型后,返回结果,并且通过映射,将结果集自动绑定到JavaBean中,所以JDBC里面那一套一个一个从ResultSet获取值的操作都被省略了。
下面我们看一个有参数的select语句:
<select id="getCommodityById" parameterType="int" resultType="com.shuqing28.pojo.Commodity"> SELECT * FROM commodity where id=#{id} </select>
同时我们定义了接口方法:
Commodity getCommodityById(Integer id);
不同于 getAllCommodity
没有传入参数, getCommodityById
有一个int类型的传入参数,返回的还是Commodity。 上面的select语句包含以下属性:
- id 标识了这条sql,id与接口名保持一致
- parameterType 定义参数类型,这里就是int
- resultType 定义了返回值类型,这里是我们定义的POJO类
这里看resultType,我们查询的是commodity的所有字段,再次回顾字段定义:
字段名 | 类型 |
---|---|
id | int |
name | varchar(255) |
price | decimal(8,2) |
description | varchar(255) |
而我们的POJO类包含:
private Integer id; private String name; private Double price; private String description;
这里Mybatis帮我们完成了 自动映射 ,只要返回的SQL列名和JavaBean的属性一致,Mybatis就可以帮助我们自动回填这些字段而无需任何配置。我们可以再Mybatis的配置文件里,通过autoMappingBehavior来设置自动映射,它包含3个值:
- NONE :取消自动映射
- PARTIAL :这也是默认值,只会自动映射,没有定义嵌套结果集映射的结果集
- FULL :会自动映射任意复杂的结果集(无论是否嵌套)
刚才我们举例的是只传递了一个参数,如果传递多个参数呢?这时候就要说说输入映射了。
输入映射
传递多个参数通常来说有3种方式,通过Map,通过注解,以及通过POJO对象
通过Map传递参数
假设我们想查询带有 饼 的食物,并且价格低于80的。那么我们可以这么写SQL语句
<select id="getCommodityByMap" parameterType="map" resultType="com.shuqing28.pojo.Commodity"> SELECT * FROM commodity WHERE name like '%${name}%' AND price<#{price} </select>
因为mybatis使用xml定义Mapper,所以这里'<'用了转义符 <
表示,其实还是一样的。 parameterType定义为map,我们定义的接口也是接受Map作为参数
List<Commodity> getCommodityByMap(Map<String, Object> params);
使用:
CommodityDao commodityDao = sqlSession.getMapper(CommodityDao.class); Map<String, Object> paramsMap = new HashMap<String , Object>(); paramsMap.put("name", "饼"); paramsMap.put("price", 80.0); List<Commodity> commodities = commodityDao.getCommodityByMap(paramsMap);
最后打印commodities:
[Commodity{id=1001, name='野葡萄烤饼', price=10.0, description='吃完还有点饿'}, Commodity{id=1003, name='南瓜百吉饼', price=50.0, description='份大量足,可以去很远的地方'}]
虽然Map很简单,但是光是看传入参数Map,你不知道包含了怎样的内容,若是深入还得看如何设置Map的,而且使用时还要一项项指定Map的Key的名字,所以不怎么提倡使用了。
使用注解方式传递参数
注解方式使用了**@Param**注解,我们这样定义接口:
List<Commodity> getCommodityByAnnation(@Param("name") String name, @Param("price") Double price);
Mybatis根据@Param提供的名称,把变量值传到SQL语句中对应的参数中,参数的可读性大大提高,但是不足之处在于,若是参数很多,一个一个写很麻烦,降低了可读性。
所以最经常使用的还是利用POJO传递参数。
使用POJO传递参数
通常我们只需要传递简单的POJO对象就可以了,比如我们这样定义select元素:
<select id="getCommodityByPOJO" parameterType="com.shuqing28.pojo.Commodity" resultType="com.shuqing28.pojo.Commodity"> SELECT * FROM commodity WHERE name like '%${name}%' AND price<#{price} </select>
测试:
@Test public void getLowPriceCommodityByPOJO(){ SqlSession sqlSession = sqlSessionFactory.openSession(); try { CommodityDao commodityDao = sqlSession.getMapper(CommodityDao.class); Commodity commodity = new Commodity(); commodity.setName("饼"); commodity.setPrice(80.0); List<Commodity> commodities = commodityDao.getCommodityByPOJO(commodity); System.out.println(commodities); } finally { sqlSession.close(); } }
也会返回和上面一样的结果,这里Mybatis会把POJO里对应的属性值传到SQL里,然后返回结果,注意看传入参数就是POJO的完全限定名,和ResultType是一样的,其实可以通过别名减少名称的长度,我们只需要在 mybatis-config.xml
中的configuration中定义:
<typeAliases> <typeAlias alias="commodity" type="com.shuqing28.pojo.Commodity" /> </typeAliases>
就可以用commodity替换所有的全称了,但是不能有重名的,否则会出错。
有些负责的情况,我们需要定义POJO作为查询参数,比如上面的例子,你只需要两个输入参数,你也可以定制一个只包含这两个参数的POJO。
public class CommodityCustom { private String name; private Double price;
当然使用过程还是一样的,定义自己包装过的POJO通常用来解决传入查询条件很复杂的情况,比如设计到几张表联查的,这时候原先定义的POJO解决不了问题,就需要定义一些复合的POJO。
在输入参数中还有个经常被提到的问题,即#和$的区别
#和$的区别
Mybatis本身是基于JDBC封装的。所以 #{para}
是预编译处理 (PreparedStatement
),相当于原来的 ?
,而 ${para}
是字符串替换。Mybatis在处理#时,会调用 PreparedStatement
的 set
系列方法来赋值;处理 $
时,就是把 ${para}
替换成变量的值。 #
方式能够很大程度防止 sql
注入, $
方式一般用于传入数据库对象,例如传入表名,一般能用 #
的就别用 $
.
说完输入我们说输出映射。
输出映射
MyBatis的输出映射分为两种方式,resultType和resultMap
resultType
我们上面所有的例子里都是定义的resultType,resultType可以是简单类型,比如我们想获取商品数量啊之类的,还有就是输出POJO对象或者POJO列表。
不管是POJO对象还是POJO列表,我们在resultType中的定义都是一样的,只不过接口定义不一样:
单个对象
Commodity getCommodityById(Integer id);
Mybatis根据接口返回值判断返回一条对象,如果用过ibatis的可以知道内部调用了session.selectOne。
返回列表
List<Commodity> getCommodityByPOJO(Commodity commodity);
内部使用session.selectList,Mapper接口使用 List<XXX>
作为返回值。
查询出来的列名和POJO属性只要有一个一致就会创建POJO对象,顶多别的字段为默认值,但是如果全部不一致,就不会创建该POJO对象了。
resultMap
上面的resultType在查询的列名和POJO属性值一致的时候才可以映射成功,如果不一致的话,就需要resultMap登场表演了。
如果查询出来的列名和POJO的属性名不一致,通过定义一个resultMap对列名和POJO属性名之间作一个映射关系。
在使用resultMap前我们需要定义resultMap 假设我们查询商品类的两个字段id和name,但是查询的时候定义为 id_
和 name_
。列名和属性名不一致了,先定义resultMap
<resultMap id="commodityResultMap" type="commodity"> <id column="id_" property="id"/> <result column="name_" property="name"/> </resultMap>
其中
- id 标识这个resultMap
- type 标识映射哪个POJO里面的属性,这里因为上面说过别名了,所以就是映射的Commodity这个POJO
- id 元素标识这个对象的主键,result就是普通字段
- property 代表POJO的属性名称
- column 表示数据库SQL的列名
再看我们的select元素:
<select id="getCommodityByPrice" parameterType="double" resultMap="commodityResultMap"> SELECT id id_, name name_ FROM USER WHERE price=#{price} </select>
使用resultType进行输出映射时,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。 此外,resultMap还可以做一对多、多对多等高级映射,这些内容将在后续文章中介绍。
insert
insert相对于select简单很多,下面是往商品表插入一个商品的实例:
<insert id="insertCommodity" useGeneratedKeys="true" keyProperty="id"> insert into commodity (name,price,description) values (#{name},#{price},#{description}) </insert>
接口为:
void insertCommodity(Commodity commodity);
这里我们注意到了insert语句里多了两个属性 useGeneratedKeys
和 keyProperty
,这里涉及到的是主键回填的概念。
- useGeneratedKeys :告诉Mybatis是否使用数据库内置策略生成主键
- keyProperty :告诉Mybatis哪一列是主键 这样我们无须传入id值,Mybatis就可以帮我们设置主键,同时还会回填POJO内的id值,当我们像下面这样调用时:
@Test public void insertCommodity(){ SqlSession sqlSession = sqlSessionFactory.openSession(); try { CommodityDao commodityDao = sqlSession.getMapper(CommodityDao.class); Commodity commodity = new Commodity(); //commodity.setId(1005); commodity.setName("艾蒿小麦饼"); commodity.setPrice(100.0); commodity.setDescription("像在艳阳下恋爱"); commodityDao.insertCommodity(commodity); System.out.println(commodity.getId()); } finally { sqlSession.close(); } }
通过打印我们能得到 1005
,说明commodity已经具备了id,这就是回填的效果。 在这里,系统默认的方式是给主键值加1,如果我们想要定义自己的主键生成方式,可以使用selectKey进行自定义:
<insert id="insertCommodity" useGeneratedKeys="true" keyProperty="id"> <selectKey keyProperty="id" resultType="int" order="BEFORE"> select if (max(id) is null, 1, max(id) + 2) as newId from commodity </selectKey> insert into commodity (name,price,description) values (#{name},#{price},#{description}) </insert>
这里我们定义主键值是最大id加2,如果还没有记录,则初始化为1。
update和delete
update和的delete都会返回影响的条目数 下面仅仅列出配置的实例:
<update id="updateCommodity" parameterType="commodity"> update commodity set name=#{name}, price=#{price}, description=#{description} where id=#{id} </update> <delete id="deleteCommodity" parameterType="int"> delete from commodity where id=#{id} </delete>
这一节主要介绍了主要的几个语句的使用,着重介绍了select语句,同时结合select语句说明了Mybatis中输入映射和输出映射的内容,其它一些高级的映射内容,留到后面的文章介绍。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【mybatis xml】数据层框架应用--Mybatis(三)关系映射之一对一关系映射
- Hibernate 关系映射整理
- Hibernate 关系映射整理
- hibernate教程--关联关系的映射详解
- hibernate教程--关联关系的映射详解
- Entity Framework 一对多关系映射
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Objective-C编程
[美] Aaron Hillegass / 夏伟频、李骏 / 华中科技大学出版社 / 2012-9-25 / 58.00元
《Objective-C编程》讲述Objective-C编程语言和基本的iOS/Mac开发知识。作者首先从基本的编程概念讲起(变量、条件语句、循环结构等),接着用浅显易懂的语言讲解Objective-C和Foundation的知识,包括Objective-C的基本语法、 Foundation常用类 、内存管理、常用设计模式等,最后手把手教读者编写完整的、基于事件驱动的iOS/Mac应用。作者还穿插......一起来看看 《Objective-C编程》 这本书的介绍吧!