mybatis学习——各种查询操作示例

Posted sadoshi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis学习——各种查询操作示例相关的知识,希望对你有一定的参考价值。

前言

查询是数据库操作中最频繁,花样最多的操作,没有之一。上一篇文章看来只要在xml里写好sql即可。主要的问题在于各种类型参数如何传参到sql语句里,可能还需要一些动态语句。另外当数据库字段和接收查询结果的实体类属性没对上的话,如何进行映射。

事前准备

上篇文章我们直接在主程序里面进行。这篇文章开始我们使用junit测试。

我是使用Eclipse Oxygen(挺老的版本),Eclipse都是自带junit的,在build path中添加即可,如下图所示:

然后我们在src/test/java目录下添加测试用的类simpleTest.java

package com.sadoshi.test.mybatisTest.test;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.BeforeClass;

import com.sadoshi.test.mybatisTest.mapper.StudentMapper;

public class simpleTest {
	
	private static StudentMapper studentMapper;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		String resource = "mybatis-config.xml";
		InputStream inputStream;
		try {
			inputStream = Resources.getResourceAsStream(resource);
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession session = sqlSessionFactory.openSession();
			studentMapper = (StudentMapper) session.getMapper(StudentMapper.class);
		}finally {
		}
	}
}

其中17-28行内容是用于初始化StudentMapper,这样我们后面写测试方法的时候,直接拿已初始化的StudentMapper即可。

各种查询操作

假设当前我们student数据库的数据如下:

每个测试,我们需要添加的代码都是三个步骤:

1、mapper文件编写接口方法;

2、xml文件里编写查询具体的sql;

3、测试类里调用mapper编写的方法;

单个传入参数的查询

StudentMapper.java中添加selectById方法,指定id为查询条件:

public interface StudentMapper {
//......

	public Student selectById(Integer id);

//......
}

 StudentMapper.xml中添加以下,其中#{}的内容不一定要和参数的名字一样,可以随意

<mapper namespace="com.sadoshi.test.mybatisTest.mapper.StudentMapper">
<!-- 省略 -->

	<select id="selectById" resultType="com.sadoshi.test.mybatisTest.entity.Student">
		select * from student where
		id = #{idabcdefg}
	</select>

<!-- 省略 -->
</mapper>

测试类simpleTest.java里添加测试方法,这里指定查询id为1的数据:

public class simpleTest {
//......

	@Test
	public void testSelectById() {
		Student res = studentMapper.selectById(1);
		System.out.println(res);
	}

//......
}

执行后控制台输出结果:

多个传入参数的查询

StudentMapper.java中添加selectByMultiParam方法,指定根据name和age两个参数查询结果。当要传多个参数时,需要通过@Param指定其传参的名字

public interface StudentMapper {
//......

	public List<Student> selectByMultiParam(@Param("name")String name, @Param("age")Integer age);

//......
}

StudentMapper.xml中添加对应的查询条件,其中#{}内的名称要和StudentMapper.java中指定的参数名一致:

<mapper namespace="com.sadoshi.test.mybatisTest.mapper.StudentMapper">
<!-- 省略 -->

	<select id="selectByMultiParam" resultType="com.sadoshi.test.mybatisTest.entity.Student">
		select * from student
		where name like CONCAT('%', #{name}, '%') and age = #{age}
	</select>

<!-- 省略 -->
</mapper>

测试类simpleTest.java里添加测试方法,这里指定查询name为李四,age是9的记录:

public class simpleTest {
//......

	@Test
	public void testSelectByMultiParam() {
		List<Student> res =studentMapper.selectByMultiParam("李四", 9);
		System.out.println(res);
	}

//......
}

执行后控制台输出结果:

传入参数为Map类型的查询

有时候参数可能是通过一个map对象传入,mybatis也是可以接受的。StudentMapper.java添加方法selectByMap,并且给其指定参数名为myMap。其实单传一个map参数的话,不指定也可以,读者可以试试不传的话怎么实现:

public interface StudentMapper {
//......

	public List<Student> selectByMap(@Param("myMap")Map<String, Object> map);

//......
}

 StudentMapper.xml添加对应的sql:

<mapper namespace="com.sadoshi.test.mybatisTest.mapper.StudentMapper">
<!-- 省略 -->

	<select id="selectByMap" resultType="com.sadoshi.test.mybatisTest.entity.Student">
		select * from student where
		name like CONCAT('%', #{myMap.name}, '%') and age = #{myMap.age}
	</select>

<!-- 省略 -->
</mapper>

测试类simpleTest.java里添加测试方法,这里传入name为王五,age为10,查询记录:

public class simpleTest {
//......

	@Test
	public void testSelectByMap() {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("name", "王五");
		map.put("age", 10);
		List<Student> res =studentMapper.selectByMap(map);
		System.out.println(res);
	}

//......
}

执行后控制台输出结果:

传入参数为List类型的查询

有时候传参也会是List类型,例如想查询包含了id为1、3的记录,会用到“select ... from .. where ... in (...)” 这样的语法。在in里面通常就是填充我们传进去的List。StudentMapper.java添加selectByList方法,其中参数指定为myList,也可以不指定,只影响在xml里面的引用:

public interface StudentMapper {
//......

	public List<Student> selectByList(@Param("myList")List<Integer> list);

//......
}

StudentMapper.xml添加对应的sql。这里要用到动态sql,通过foreach迭代list中的元素,并且以逗号分隔:

<mapper namespace="com.sadoshi.test.mybatisTest.mapper.StudentMapper">
<!-- 省略 -->

	<select id="selectByList" resultType="com.sadoshi.test.mybatisTest.entity.Student">
		select * from student where id in
		<foreach item="item" index="index" collection="myList" open="("
			separator="," close=")">
			#{item}
		</foreach>
	</select>

<!-- 省略 -->
</mapper>

测试类simpleTest.java里添加测试方法,这里为list添加1、3两个元素,查询id为1或3的记录:

public class simpleTest {
//......

	@Test
	public void testSelectByList() {
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(3);
		List<Student> res =studentMapper.selectByList(list);
		System.out.println(res);
	}

//......
}

执行后控制台输出结果:

传入参数为对象类型的查询

 一般项目中常见的查询,更多是通过传递对象类型作为参数的。StudentMapper.java中添加selectByObj方法:

public interface StudentMapper {
//......

	public List<Student> selectByObj(@Param("obj")Student student);

//......
}

 StudentMapper.xml添加对应的sql,看起来和传递map类型有些相似: 

<mapper namespace="com.sadoshi.test.mybatisTest.mapper.StudentMapper">
<!-- 省略 -->

	<select id="selectByObj" resultType="com.sadoshi.test.mybatisTest.entity.Student">
		select * from student where
		name like CONCAT('%', #{obj.name}, '%') and age = #{obj.age}
	</select>

<!-- 省略 -->
</mapper>

 测试类simpleTest.java里添加测试方法:

public class simpleTest {
//......

	@Test
	public void testSelectByObj() {
		Student obj = new Student();
		obj.setName("李四");
		obj.setAge(9);
		List<Student> res =studentMapper.selectByObj(obj);
		System.out.println(res);
	}

//......
}

执行后控制台输出结果:

动态sql过滤查询项

上面传入参数为对象类型的查询中,我们必须对name和age都赋值,否则对应值为null,查询数据库时就匹配不上了。但实际应用当众,程序员更希望如果不设置对象的某个属性,则查询条件就不包含这个字段,这也是项目中最常见的使用方式。StudentMapper.java中添加selectByCond方法:

public interface StudentMapper {
//......

	public List<Student> selectByCond(@Param("obj")Student student);

//......
}

 在StudentMapper.xml添加对应的sql,这里通过if进行过滤。注意通过where标签里面,会自动把多余的and去掉,例如当name属性没设置时,where语句只包含"and age = #{obj.age}",这时mybatis会把前面多余的and去掉:

<mapper namespace="com.sadoshi.test.mybatisTest.mapper.StudentMapper">
<!-- 省略 -->

	<select id="selectByCond" resultType="com.sadoshi.test.mybatisTest.entity.Student">
		select * from student
		<where>
			<if test="obj.name != '' and obj.name != null">
				name like CONCAT('%', #{obj.name}, '%')
			</if>
			<if test="obj.age != null">
				and age = #{obj.age}
			</if>
		</where>
	</select>

<!-- 省略 -->
</mapper>

 测试类simpleTest.java里添加测试方法,这里把设置name的代码注释,看看是否会过滤where后面name字段的匹配:

public class simpleTest {
//......

	@Test
	public void testSelectByCondition() {
		Student obj = new Student();
		//obj.setName("王五");
		obj.setAge(10);
		List<Student> res =studentMapper.selectByCond(obj);
		System.out.println(res);
	}

//......
}

执行后控制台输出结果,果然过滤了name字段的匹配:

关于resultMap的查询

resultMap也是项目中使用比较多的mybatis功能。例如数据表的字段和查询返回结果的对象属性名没有对应,那查询的结果就没法赋予对象了。为了解决这个问题,需要一种映射方式,把数据表的字段和对象的属性对应起来。这就要通过resultMap。StudentMapper.java中添加testResultMap方法:

public interface StudentMapper {
//......

	public List<Student2> selectResultMap();

//......
}

 在StudentMapper.xml添加对应resultMap,并且需要用到resultMap的sql要把其resultType改为resultMap并指定其id:

<mapper namespace="com.sadoshi.test.mybatisTest.mapper.StudentMapper">
<!-- 省略 -->

	<select id="selectResultMap" resultMap="myResultMap">
		select * from student
	</select>

	<resultMap id="myResultMap" type="com.sadoshi.test.mybatisTest.entity.Student2">
		<id property="id2" column="id" />
		<result property="name2" column="name" />
		<result property="age2" column="age" />
	</resultMap>

<!-- 省略 -->
</mapper>

上面我们让myResultMap返回类型为Student2,创建Student2类型,所有属性后面都加2,只为了测试resultMap能否把数据表字段映射到Student2的属性上:

package com.sadoshi.test.mybatisTest.entity;

public class Student2 {

	private Integer id2;
	private String name2;
	private Integer age2;
	
	public Integer getId2() {
		return id2;
	}
	public void setId2(Integer id2) {
		this.id2 = id2;
	}
	public String getName2() {
		return name2;
	}
	public void setName2(String name2) {
		this.name2 = name2;
	}
	public Integer getAge2() {
		return age2;
	}
	public void setAge2(Integer age2) {
		this.age2 = age2;
	}
	@Override
	public String toString() {
		return "Student2 [id2=" + id2 + ", name2=" + name2 + ", age2=" + age2 + "]";
	}
}

测试类simpleTest.java里添加测试方法:

public class simpleTest {
//......

	@Test
	public void testResultMap() {
		List<Student2> res = studentMapper.selectResultMap();
		System.out.println(res);
	}

//......
}

执行后控制台输出结果,成功映射字段:

小结:

本文针对mybatis查询中常见的情况做了一些示例,仅供参考。

 

以上是关于mybatis学习——各种查询操作示例的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis学习笔记 —— MyBatis的各种查询功能

(Myatis 学习) MyBatis的各种查询功能

mybatis递归,一对多代码示例

MyBatis从入门到精通

mybatis学习笔记(11)-一对多查询

mybatis学习笔记(11)-多对多查询