mybatis-映射器-select
来源:互联网 发布:打印机没有usb端口选择 编辑:程序博客网 时间:2024/06/14 21:08
select元素是我们最常用也是功能最强大的sql语言。select元素帮助我们从数据库中读取出数据,组装数据给业务人员。执行select语句之前,我们需要定义参数,它可以是一个简单的参数类型,例如int,float,String,也可以是一个复杂的参数类型,例如JavaBean,Map等,这些都是mybatis接受的参数类型。执行sql后,mybatis也提供了强大的映射规则,甚至自动映射来帮助我们把返回的结果集绑定到javabean中。
一:select元素的主要配置
id:它和Mapper的命名空间组合起来是唯一的,提供给mybatis调用,如果命名空间和id组合起来不唯一,mybatis将抛出异常。
parameterType:可以给出类的全命名也可以给出类的别名,但使用别名必须是mybatis内部定义或者自定义的,我们可以选择javabean,map等复杂的参数类型传递给sql。
parameterMap: 即将被废弃的元素,不考虑。
resultType:定义类的全路径,在运行自动匹配的情况下,结果集将通过javabean的规范映射;或定义为int,double,float等参数,也可以使用别名,但需符合别名规范,不能和resultMap同时使用。
resultMap:它是映射集的引用,将执行强大的映射功能,我们可以使用resultType或者resultMap其中的一个,resultMap给予了我们自定义映射规则的机会,可以配置映射规则,级联,typeHandler等。
flushCache:它的作用是在调用sql后,是否要求mybatis情况之前查询的本地缓存和二级缓存,取值为布尔值,默认为false。
useCache:启动二级缓存的开关,是否要求mybatis将结果缓存,取值为布尔值,默认为true。
timeout:设置超时参数,等超时的时候将抛出一次,单位为秒,默认值是数据库厂商提供的jdbc驱动所设置的秒数。
fetchSize:获取记录的总条数设定,默认值是数据库厂商提供的jdbc驱动所设置的条数。
statementType:告诉mybatis使用哪个jdbc的Statement工作,取值为STATEMENT(Statement),PREPARED(PreparedStatement),CallableStatement,默认值为PREPARED。
resultSetType:这是对jdbc的resultSet接口而言,它的值包括FORWARD_ONLY(游标运行向前访问),SCROLL_SENSITIVE(双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在resultSet中反应出来),SCROLL_INSENSITIVE(双向滚动,并及时跟踪数据库的更新,以便更改resultSet中的数据),默认值是数据库厂商提供的jdbc驱动所设置的
databaseId:它的使用可以参考前面databaseIdProvider数据库厂商标识的内容,提供多种数据库的支持。
resultOrdered:这个设置仅使用于嵌套结果集的select语句,如果为true,就是假设包含了嵌套结果集或者是分组了,当返回一个结果行的时候,就不能对前面结果集的引用。这就确保了在获取嵌套的结果集的时候不至于导致内存不够用。取值为布尔值,默认false。
resultSets:适合多个结果集的情况,它将列出执行sql后每个结果集的名称,每个名称之间的用逗号分隔,很少使用。
二:简易数据类型的例子
例如,统计一个姓氏的用户数量,我们应该把姓氏作为参数传递,而将结果设置为整型返回给调用者,代码如下:
<!-- 根据姓氏查询该姓氏的用户数量 --> <select id="countFirstName" parameterType="string" resultType="int" > select count(*) as total from t_user where name like contat(#{firstName},'%') </select>
在UserDao中定义如下方法:
package org.mybatis.mapper;import org.mybatis.pojo.User;/** * 用户接口 * * @author wj * */public interface UserMapper {/** * 获取用户 * * @param id * @return */public User getUser(Long id);/** * 插入用户 * * @param user * @return */public int insertUser(User user);/** * * 查询指定姓氏的人数 * * @param firstName * @return */public int countFirstName(String firstName);}
这样就可以使用mybatis调用sql了,操作步骤可以概括如下:
1)用id标记出这条sql
2)parameterType定义参数类型
3)resultType定义了返回值类型
这是一个简单的例子,mybatis的映射往往比这复杂。
三:自动映射
有这样一个参数autoMappingBehavior,当它不设置为NONE的时候,mybatis会提供自动映射的功能,只要返回的sql列名和javabean的属性一致,mybatis就会帮助我们回填这些字段而无需任何配置,它可以很大程度上简化我们的配置工作。在实际情况中,大部分的数据库规范都是要求每个单词用下划线分割,而java则是用驼峰命名法来命名,于是使用列的别名就可以使得mybatis自动映射,或者直接在配置文件中开启驼峰命名。
下面再来看一个例子,体验下自动映射。我们需要通过角色编号查询一个角色,并将结果集映射到角色的javabean上。下面先给出javabean,代码如下所示:
package org.mybatis.pojo;public class Role {private Long id;private String roleName;private String note;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getRoleName() {return roleName;}public void setRoleName(String roleName) {this.roleName = roleName;}public String getNote() {return note;}public void setNote(String note) {this.note = note;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn "Role [id=" + id + ",roleName=" + roleName + ",note=" + note + "]";}}
而数据库的结构如下:
下面编写Mapper的映射语句,代码如下:
<!-- 根据角色id查找角色 --><select id="getRole" parameterType="long" resultType="org.mybatis.pojo.Role">select id,role_name as roleName,note from role where id = #{id}</select>
对于RoleDao接口,提供getRole方法,代码如下:
package org.mybatis.mapper;import java.util.List;import org.mybatis.pojo.Role;//接口public interface RoleMapper {// 通过id获取角色public Role getRole(Long id);// 插入角色public int insertRole(Role role);// 通过id删除角色public int deleteRole(Long id);// 通过角色名字,模糊查找public List<Role> findRole(String roleName);}
这样mybatis就可以通过mapper进行接口的调用。角色名称(role_name)使用sql提供的别名功能使得查询结果和javabean的属性一一对象起来,然后mybatis提供的自动映射的功能使得我们无需通过过多的提供配置信息,大大减少了我们的工作量。
自动映射可以在settings元素中配置autoMappingBehavior属性值来设置其测量。它含三个值:
NONE:取消自动映射。
PARTIAL: 只会自动映射,没有定义嵌套结果集映射的结果集。
FULL:会自动映射任意复杂的结果集(无论是否嵌套)
默认值为PARTIAL,所以在默认的情况下,它可以做到当前对象的映射,使用FULL是嵌套映射,在性能上会下降。
如果你的数据库是规范命名的,即每一个单词都用下划线分割,pojo采用驼峰式命名方法,那么可以设置mapUnderscoreToCamelCase为true,这样就可以实现从数据库到pojo的自动映射了。
四:传递多个参数
上面的例子是传递一个参数给映射器,更多的时候需要传递多个参数给映射器,比如需要根据角色名称和备注来模糊查询角色,这里就涉及到两个参数了。
1,使用map传递参数
可以使用mybatis提供的map接口作为参数来实现,代码如下:
<!-- 通过角色名称和备注字段两个参数模糊查询角色 --> <select id="findRoleByMap" parameterType="map" resultMap="roleMap"> select id,role_name as roleName,note from role where role_name like concat('%',#{roleName},'%') and note like concat('%',#{note},'%') </select>
对于Role的接口,我们需要在提供一个findRoleByMap的方法
// 通过角色名称和备注两个参数模糊查询角色信息,返回角色数组public List<Role> findRoleByMap(Map<String, String> params);
有了上面的接口,我们就可以使用这个方法了,代码如下:
Map<String,String> paramsMap = new HashMap<String,String>();paramsMap.put("roleName", "jack");paramsMap.put("note", "test");roleMapper.findRoleByMap(paramsMap);
上面的使用方法比较简单,但是有一个弊端,这样设置的参数使用了Map,而Map需要键值对应,由于业务关联性不强,需要深入看代码,造成可读性下降。mybatis提供了更好的实现方法,它就是注解参数的形式,下面看看使用注解,怎么实现参数的传递。
2,使用注解的方式传递参数
我们需要使用mybatis的参数注解@Param(org.apache.ibatis.annotations.Param)来实现传递参数的功能。操作方法是把RoleDao接口修改为下面的形式:
// 通过mybatis的注解实现传递参数public List<Role> findRoleByAnnotation(@Param("roleName") String rolename, @Param("note") String note);
把映射器的xml修改为无需定义参数类型,代码如下:
<!-- 通过角色名称和备注字段两个参数模糊查询角色,通过mybatis的注解传递参数 --> <select id="findRoleByAnnotation" resultMap="roleMap"> select id,role_name as roleName,note from role where role_name like concat('%',#{roleName},'%') and note like concat('%',#{note},'%') </select>
当我们把参数传递给后台的时候,通过@Param提供的名称Mybatis就会知道#{roleName}代表rolename,参数的可读性大大提高了。但这会引起另外一个麻烦,一条sql拥有10个参数的查询,如果我们都使用@Param方式,那么参数将十分复杂,可读性依旧不高,不够mybatis为我们提供了javabean定义参数的方式来解决这个问题。
3:使用JavaBean传递参数
在参数过多的情况下,Mybatis允许组织一个JavaBean,通过简单的setter和getter方法设置参数,这样就可以提供我们的可读性。首先定义一个RoleParams的JavaBean,代码如下所示:
package org.mybatis.params;public class RoleParam {private String roleName;private String note;public String getRoleName() {return roleName;}public void setRoleName(String roleName) {this.roleName = roleName;}public String getNote() {return note;}public void setNote(String note) {this.note = note;}}
下面用javabean改写一下传递参数的例子,代码如下:
<!-- 通过角色名称和备注字段两个参数模糊查询角色,通过javabean传递参数 --> <select id="findRoleByParms" parameterType="org.mybatis.params.RoleParam" resultMap="roleMap"> select id,role_name as roleName,note from role where role_name like concat('%',#{roleName},'%') and note like concat('%',#{note},'%') </select>
同样在Role的接口中提供一个方法
// 通过javabean的方法传递参数public List<Role> findRoleByParms(RoleParam params);
然后在使用这个接口的时候直接传入javabean对象即可,这就是通过javabena传递多个参数的方式。
小结:
上面讲解了三种方式进行多个参数的传递,一是通过map的方式,二是通过mybatis注解的方式,三是通过javabean的方式。下面分析下利弊:
1,使用map传递参数,因为map导致业务可读性的丧失,从而导致后续扩展和维护的困难,在实际的应用中,不建议使用。
2,使用@Param注解传递多个参数,这种方式的使用受到参数个数(n)的影响。当n《=5时,它是最佳的传参方式,它比javabean更好,因为更加直观;当n大于5时,多个参数将给调用带来困难。
3,当参数个数多于5个时,建议使用javabean方式
五:使用resultMap映射结果集
前面介绍了自动映射,返回的也只是简单的javabean对象,但是在某些时候,我们需要处理更为复杂的映射,resultMap为我们提供了这样的模式。我们需要在映射器中定义resultMap,这也是我们常见的场景,代码如下:
<resultMap type="role" id="roleMap"> <!--定义结果类型转换标识,才能使用类型转换器 --> <id column = "id" property = "id" javaType ="long" jdbcType = "BIGINT"/> <result column ="role_name" property = "roleName" javaType = "string" jdbcType = "VARCHAR"/> <result column = "note" property = "note"/> </resultMap>
<!-- 根据角色id查找角色 --><select id="getRole" parameterType="long" resultMap="roleMap">select id,role_name as roleName,note from role where id = #{id}</select>
下面解释下resultMap的配置:
1,定义了唯一的标识(id)为roleMap的resultMap,用type属性去定义它对应的是哪个JavaBean(也可以使用别名),上面我用的就是别名。
2,通过id元素定义resultResultMap,这个对象代表着使用哪个属性作为其主键。result元素定义了普通列的映射关系,例如,把sql结果返回的列role_no和type属性定义的javabean的属性id等做一 一对应。
3,这样select语句就不在需要使用自动映射的规则,直接用resultMap属性指定resultMap定义的id(roleMap)即可,这样mybatis就会使用我们的自定义映射规则。
resultMap是映射器里面最为复杂的元素,它一般用于复杂,级联的配置,我们可以使用resultMap通过自动映射来完成,这样配置的工作量就会大大减少。·
- mybatis-映射器-select
- mybatis引入映射器与select元素
- MyBatis —— 映射配置之select
- 【Mybatis学习】Mybatis映射器
- Mybatis--映射器注解
- MyBatis-映射器
- Mybatis映射器
- MyBatis四映射器
- mybatis--映射器
- Mybatis映射器
- Mybatis 映射器
- MyBatis映射器
- MyBatis 映射器
- mybatis映射器注解
- mybatis--mapper映射文件配置之select,resultMap
- MyBatis的映射文件mapper的select标签
- MyBatis的XML映射文件、映射器
- 深入MyBatis开发之mybatis映射器
- 河南省第十届ACM程序设计竞赛排行榜
- 第28章 离散信号(非周期)频域分析--DTFT
- 小白项目初尝试——全民飞机大战初期
- 生产者消费者模型(使用lock.condition进行分组唤醒)
- 内部类
- mybatis-映射器-select
- 2017年5月份源码发布详情_源码盒子(www.srcbin.net)
- 【PKMS】- Settings中应用详情页卸载还原系统应用但数据未清除
- 基于Android中实现定时器的3种解决方法
- MAC环境安装imagemagick
- 我们来聊聊缓存
- 一箭双雕,安装sqoop1和sqoop2
- C++11之future,promise,packaged_task,async详解
- ESP8266 SDK 编程和下载入门