概述
MyBatis的查询
- MyBatis的查询
- 1、mybatis的查询属性说明
- 2、最简单的mybatis的查询
- 3、关于parameterType=”map” 的使用
- 4、关于ResultType=”map”的使用
- 4.1、在使用mybatis的esultType=”map”之前
- 4.2、使用resultType=”map”最简单的情形
- 4.3、返回Map >这种类型
- 5、动态sql进行查询
- 5.1、foreach查询
- 5.1.1、传入的是单参数且参数类型是一个List的时候
- 5.1.2、传入的是单参数且参数类型是一个array数组的时候
- 5.1.3、传入的参数是多个的时候
- 5.1.4、对应的mapper接口
- 5.1.5、测试方法
- 5.2 if标签的一些问题
- 5.1、foreach查询
1、mybatis的查询属性说明
<select
id="selectUser"
parameterType="int"
resultType="hashmap"
resultMap="userResultMap"
flushCache="true" //如果为true,则任何的本地缓存和二级缓存都是会被清空的
timeout="10000" //驱动程序等待数据库返回请求结果的的秒数
statementType:"PREPARED" //选择使用JDBC的Satement,PreparedStatement或CallableStatement></select>
2、最简单的mybatis的查询
使用的是resultType作为返回类型,parameterType是接收参数的类型
<!-- 根据用户ID,查询用户信息 -->
<!--
select:表示的是MappedStatement对象
[id]:statement的id,要求在命名空间内唯一
[parameterType]:入参的java类型
[resultType]:查询出的单条结果集对应的java类型
[#{}]: 表示一个占位符?
[#{id}]:表示该占位符待接收参数的名称为id。注意:如果参数为简单类型时,#{}里面的参数名称可以是任意定义
-->
<select id="findUserById" parameterType="int" resultType="com.itheima.mybatis.po.User">
SELECT * FROM USER WHERE id = #{id}
</select>
第二种使用的是模糊查询:
<!--根据用户名称模糊的查询用户列表-->
<!--使用${}可以吧需要的调进来,其余的补上
${}:表示的是一个sql的连接符
${value}:里面的value表示输入参数的参数名称,如果该参数是简单类型,那么${}里面的参数名称必须是value
${}:这种写法存在sql注入的风险,所以要慎用!!但是在一些场景下,必须使用${},比如排序时,动态传入排序的列名,${}会原样输出,不加解释,如果是用#{}里面放的是String类型的话,会自动的加上‘’,sql会出错-->
<select id="findUsersByName" parameterType="java.lang.String" resultType="com.itheima.mybatis.po.User">
SELECT * from user where username like '%${value}%'
</select>
3、关于parameterType=”map” 的使用
请求参数就是你serviceImpl参数里传入的map
先看看select的sql语句:
<select id="findUserByHashmap" parameterType="hashmap" resultType="user">
select * from user where username LIKE "%${user.username}%" AND sex=#{user.sex}
</select>
这里我们可以看到的是parameterType=”hashmap”,所以下面传进来的也是map;
下面的是测试代码:
@Test
public void testFindUserByHashmap()throws Exception{
//获取session
SqlSession session = sqlSessionFactory.openSession();
//获限mapper接口实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//构造查询条件Hashmap对象
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id", 1);
map.put("username", "管理员");
//传递Hashmap对象查询用户列表
List<User>list = userMapper.findUserByHashmap(map);
//关闭session
session.close();
}
4、关于ResultType=”map”的使用
4.1、在使用mybatis的esultType=”map”之前
我们先看看map类型在pringMVC中的作用:
springmvc形参(@RequestBody HashMap hashMap)
,即请求过来的json就封装到了hashMap里,这样可以省去QueryVo,直接调用service接口传入hashMap.get("id"),hashMap.get("name"))
但通常还是将请求过来的json通过@RequestBody注解转为实体类(或者用hashmap<String,String> hashmap
来接收),然后调用service层(此时传入对象或hashmap)
4.2、使用resultType=”map”最简单的情形
返回值map的键就是表中字段的别名,值就是是你查到的值,如果是多个,mapper接口就是list包map,即 List<Map<String, Object>>
,如此可省去new返回值对象,很简单
先看看返回多条数据的情形:
- xml文件如下:
<select id="selectUser" resultType="map">
SELECT * FRMO TB_USER
</select>
这里返回的是多个user对象,resultType=”map”表示返回的是一个Map集合(使用的是列名作为key,列值作为value),这种情况下在写mapper接口的时候可以使用
- dao层的mapper接口
List<Map<String,Object>> selectUser(); //mapper接口
其中String表示的是key的类型,而用Object可以接受任意的返回的类型,
- service层进行封装
然后在service层中使用UserMsg,这样做的目的主要是:如果需要返回的结果中包含着User类中没有的属性就可以使用自定义的类型进行封装。
List<Map<String,Object>> userList = userMapper.selectUser();
for (Map<String,Object> map:courseChoiceList){
UserMsg userMsg=new
UserMsg();
userMsg.setId((Long)map.get("id"));
userMsg.setName(map.get("course_id").toString());
userMsg.setBirthday(new Date());
courseChoiceMsgList.add(courseChoiceMsg);
}
4.3、返回Map<String, Map<String, Object>>
这种类型
需求场景:
批量从数据库查出若干条数据,包括id和name两个字段。希望可以把结果直接用Map接收,然后通过map.get(id)方便地获取name的值。
{1={id=1,name="zhangsan"},2={id=2,name="lisi"},3={id=3,name="wangwu"}}
解决的方法是在外面再用一个Map:
Map<Integer, Map<String, Object>> m = abcDao.getNamesByIds(idList);
然后,在这个dao的方法上面加一个注解:
@MapKey("id")
public Map<Integer, Map<String, Object>> getNamesByIds(List<Map<String, Objec>)
Mapper.xml中的配置如下:
<select id="getNamesByIds" resultType="java.util.Map">
SELECT id, name FROM tb_abc WHERE id IN
<foreach item="item" collection="list" open="(" separator="," close=")">
#{item.id}
</foreach>
</select>
5、动态sql进行查询
5.1、foreach查询
需求场景:
需要通过传过来的一个id数组,查询出对应的用户
- foreach元素的属性主要有 item,index,collection,open,separator,close。
- item表示集合中每一个元素进行迭代时的别名,
- index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,
- open表示该语句以什么开始,
- separator表示在每次进行迭代之间以什么符号作为分隔符,
- close表示以什么结束。
- 在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:
- 1**.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list**
- 2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- 3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map(Object),当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key.
public class Employees {
private Integer employeeId;
private String firstName;
private String lastName;
private String email;
private String phoneNumber;
private Date hireDate;
private String jobId;
private BigDecimal salary;
private BigDecimal commissionPct;
private Integer managerId;
private Short departmentId;
}
5.1.1、传入的是单参数且参数类型是一个List的时候
<!--List:forech中的collection属性类型是List,collection的值必须是:list,item的值可以随意,Dao接口中参数名字随意 -->
<select id="getEmployeesListParams" resultType="Employees">
select *
from EMPLOYEES e
where e.EMPLOYEE_ID in
<foreach collection="list" item="employeeId" index="index"
open="(" close=")" separator=",">
#{employeeId}
</foreach>
</select>
5.1.2、传入的是单参数且参数类型是一个array数组的时候
<!--Array:forech中的collection属性类型是array,collection的值必须是:list,item的值可以随意,Dao接口中参数名字随意 -->
<select id="getEmployeesArrayParams" resultType="Employees">
select *
from EMPLOYEES e
where e.EMPLOYEE_ID in
<foreach collection="array" item="employeeId" index="index"
open="(" close=")" separator=",">
#{employeeId}
</foreach>
</select>
5.1.3、传入的参数是多个的时候
注意:这里传入的是Object类型的也是可以的
第一种:map
<!--Map:不单单forech中的collection属性是map.key,其它所有属性都是map.key,比如下面的departmentId -->
<select id="getEmployeesMapParams" resultType="Employees">
select *
from EMPLOYEES e
<where>
<if test="departmentId!=null and departmentId!=''">
e.DEPARTMENT_ID=#{departmentId}
</if>
<if test="employeeIdsArray!=null and employeeIdsArray.length!=0">
AND e.EMPLOYEE_ID in
<foreach collection="employeeIdsArray" item="employeeId"
index="index" open="(" close=")" separator=",">
#{employeeId}
</foreach>
</if>
</where>
</select>
第二种:pojo
传入的是pojo的类型parameterType="com.itheima.mybatis.po.UserQueryVO"
<!--定义sql片段-->
<!--sql片段内最好不要将where和select声明在内-->
<sql id="whereClause">
<!-- if标签可以对输入的参数进行判断-->
<!-- test:判断表达式-->
<!-- if:防止出现空指针异常的出现-->
<if test="user!=null">
<if test="user.username!=null and user.username!=''">
AND username LIKE "%${user.username}%"
</if>
<if test="user.sex!=null and user.sex!=''">
AND sex=#{user.sex}
</if>
</if>
<if test="idList!=null">
AND id IN
<foreach collection="idList" item="id" open="(" close=")" separator=",">#{id}</foreach>
</if>
</sql>
<!--综合查询,查询用户列表(根据用户名,性别,用户id;SELECT * FROM USER WHERE id IN (1,2,10))-->
<select id="findUserList" parameterType="com.itheima.mybatis.po.UserQueryVO" resultType="user">
SELECT * FROM user
<!--where标签:默认的去掉后面的第一个AND符号,如果是没有参数,则把自己干掉-->
<where>
<include refid="whereClause"/>
</where>
5.1.4、对应的mapper接口
Mapper类:
public interface EmployeesMapper {
List<Employees> getEmployeesListParams(List<String> employeeIds);
List<Employees> getEmployeesArrayParams(String[] employeeIds);
List<Employees> getEmployeesMapParams(Map<String,Object> params);
}
5.1.5、测试方法
@Test
public void testGetEmployeesListParams() {
List<String> employeeIds = Arrays.asList("100", "101", "200");
List<Employees> result = employeesMapper
.getEmployeesListParams(employeeIds);
assertEquals(3, result.size());
}
@Test
public void testGetEmployeesArrayParams() {
String[] employeeIds = new String[] { "100", "200" };
List<Employees> result = employeesMapper
.getEmployeesArrayParams(employeeIds);
assertEquals(2, result.size());
}
@Test
public void testGetEmployeesMapParams() {
String departmentId = "60";
List<String> employeeIdsList = Arrays.asList("103", "104", "105");
String[] employeeIdsArray = new String[] { "103", "104" };
// 传入多个参数
Map<String, Object> params = new HashMap<String, Object>();
params.put("departmentId", departmentId);
params.put("employeeIdsList", employeeIdsList);
params.put("employeeIdsArray", employeeIdsArray);
List<Employees> result = employeesMapper.getEmployeesMapParams(params);
assertEquals(3, result.size());
}
5.2 if标签的一些问题
1、常见错误:
There is no getter for property named ‘parentId’ in ‘class java.lang.Long’(或者String)
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘parentId’ in ‘class java.lang.Long’
sql是这样写的:
<select id="queryByParentId" parameterType="long" resultMap="beanMap">
SELECT * FROM <include refid="t_pt_category"/>
<where>
isdel = 0
<if test="parentId != null">
AND parent_id = #{parentId}
</if>
</where>
ORDER BY parent_id
</select>
解决1:
把<if>
标签去掉传参还是直接传递传递long,如下:sql2
<select id="queryByParentId" parameterType="long" resultMap="beanMap">
SELECT * FROM <include refid="t_pt_category"/>
<where>
isdel = 0
AND parent_id = #{parentId}
<!--<if test="parentId != null">
AND parent_id = #{parentId}
</if> -->
</where>
ORDER BY parent_id
</select>
解决2:保持sql1不变,在dao层把参数换成map类型,
Map<String, Object> params = new HashMap<>(1);
params.put("parentId", parentId);
解决3:改写sql1,如下,全部的参数都换成”_parameter”,如下sql3:
select id="queryByParentId" parameterType="long" resultMap="beanMap">
SELECT * FROM <include refid="t_pt_category"/>
<where>
isdel = 0
<if test="_parameter != null">
AND parent_id = #{_parameter}
</if>
</where>
ORDER BY parent_id
</select>
最后
以上就是妩媚鞋垫为你收集整理的MyBatis的查询MyBatis的查询的全部内容,希望文章能够帮你解决MyBatis的查询MyBatis的查询所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复