MyBatis学习笔记(2)—映射关系篇

MyBatis学习笔记(1)—使用篇

MyBatis学习笔记(2)—映射关系篇sql

MyBatis学习笔记(3)—高级映射之一对一映射数据库

Mybatis学习笔记(4)-高级映射之一对多映射缓存

Mybatis学习笔记(5)-高级映射之多对多映射bash

...敬请期待session

经过上一篇的入门MyBatis学习笔记(1)—使用篇,能够发现除了一些基本配置外,Mybatis的精华就在于Mapper(映射)部分。Mybatis是针对映射器构造的SQL构建的轻量级框架,而且能够经过配置生成对应的JavaBean给调用者。在Mybatis中能够灵活使用SQL来知足各类不一样场景的需求,因此在互联网企业内更偏心于使用Mybatis来应对高速变化的需求,而传统企业更偏向于使用Hibernate。mybatis

映射器的主要元素

上一节咱们仅仅定义了一个select语句:app

<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 其余命名空间缓存配置的引用 ————

下面咱们探究主要使用的几个元素post

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&lt;#{price}
        </select>
复制代码

由于mybatis使用xml定义Mapper,因此这里'<'用了转义符&lt;表示,其实仍是同样的。 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&lt;#{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在处理#时,会调用PreparedStatementset系列方法来赋值;处理$时,就是把${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语句里多了两个属性useGeneratedKeyskeyProperty,这里涉及到的是主键回填的概念。

  • 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中输入映射和输出映射的内容,其它一些高级的映射内容,留到后面的文章介绍。

相关文章
相关标签/搜索