mybatis03——输入参数类型、多参数输入、输出类型、resultmap的使用

输入类型

parameterType支持的数据类型有

  • java简单类型 :int、String
  • pojo自定义对象
  • hashmap

前两种我们都使用过,现在演示map的用法

/** 
	 * 方法描述:pamarmType 为hashmap的用例
	 */
	@Test
	public void testMap() {
		Map<String, Object> map = new HashMap<>();//定义一个hashmap
		//往里面传值
		map.put("address", "山东");
		map.put("sex", "男");
		
		//根据map进行查询功能
		List<User> list = userMapper.selectByMap(map);//根据map里面的名字、性别查询用户列表
		System.err.println(list);
		sqlSession.close();
	}

上面这个方法是放在UserTest.java类中的。然后需要写接口,写映射文件(这三者的顺序随便。)
接口方法:

/** 
	 * 方法描述: 根据hashmap参数的用例
	 * @param map
	 * @return
	 */
	public List<User> selectByMap(Map<String, Object> map);

mapper.xml文件添加方法

<!-- hashmap的用例  #{}里面的值是所对应的key-->
	<!-- 注意:当使用map中不存在的key取值时,取值为空null,代码此处不报错 -->
	<select id="selectByMap" parameterType="map" resultType="User">
		select * from user where sex = #{sex} and address like concat("%",#{address},"%")	
	</select>

注意:当使用map中不存在的key取值时,取值为空null,代码此处不报错,也就是说如果把上面的#{address}改成#{addr},他就不会获取到值,但不会报错。

当你需要传进去多参数,却不是User当中的类的时候,可以使用map,如希望查找年龄在2001年到2020年的人,需要将2001和2020作为参数传进去,就可以放到map里面。

那么,接下来我们讲讲

多参数问题

上面是一种解决方法,这里我们再介绍两种
第一种
这就是一个多参接口方法

	/** 
	 * 方法描述: 多参数的查询
	 * @param map
	 * @return
	 */
	public List<User> selectByParams(String sex, String address);

然后我们写mapper.xml里的<select>
我们可以不写parameterType。
并且使用下标来进行标记,从零开始。表示第几个参数(必须从零开始)

	<!-- 多参数的用例 -->
	<!-- 多参数的时候parameterType可以直接省略掉 -->
	<select id="selectByParams" resultType="User">
 		select * from user where sex = #{0} and address like concat ("%",#{1},"%")
 	</select>

写测试方法,在UserTest.java里面

	@Test
	public void testParams() {
		List<User> list = userMapper.selectByParams("男", "山东");
		System.err.println(list);
		sqlSession.close();
	}

另一种方法,接口方法如下

	/** 
	 * 方法描述: 多参数的查询
	 * @param map
	 * @return
	 */
	public List<User> selectByParams(@Param("sex")String sex,@Param("address")String address);

这种方法是对接口里的参数进行注解。这种用注解的方式,相当于把参数放到了map中,使用map进行传递。
所以mapper.xml中的参数名还是要一致,如下:(还是把paramentType省略掉)

	<!-- 多参数的用例 -->
	<!-- 多参数的时候parameterType可以省略掉 -->
	<!-- @Params的作用:把注解对象set 放到map中 -->
	<select id="selectByParams" resultType="User">
		select * from user where sex = #{sex} and address like concat ("%",#{address},"%")
 	</select>

测试类没有变化。

总结:常用的是第一种方法。

resultType(输出类型)

resultType支持的类型有

  • java简单类型
  • pojo类型
  • hashmap

…没啥好讲的,前两种常使用,hashmap基本用不到,因为返回值都可以用我们自己定义的pojo类型进行接收
我们可以讲不用resultType,而是用resultmap

resultmap

问题

我们经常会遇到一种情况,就是如果数据库中表的字段名修改了。我们的mybatis可以正常运行,但该字段查不到,返回来为null。(此时跟传入参数没啥关系,传入参数只是在映射文件和方法使用中进行传值,不论你怎么改名字,只要映射成功,值都会传入我们所写的sql语句中,从而查出正确的信息,此时所讲的是输出类型)
所以我们总结出:
resultType在指定pojo对象接收映射的结果集时,需要将pojo对象的属性名和数据库中表的字段名要一致。
如果有不一致的,则查询的该字段为null。

(这跟map里的不一致不一样,map如果查不到,就是没条件,查不出来,而这个只是返回的数据中某个数据项没有值)

我们演示一下这个错误
在原有的项目中新建一个Car类

package com.cbb.pojo;

public class Car {
	private int carId;
	private String carName;//汽车名字,与表字段不一致
	private int userId;
	public int getCarId() {
		return carId;
	}
	public void setCarId(int carId) {
		this.carId = carId;
	}
	public String getCarName() {
		return carName;
	}
	public void setCarName(String carName) {
		this.carName = carName;
	}
	public int getUserId() {
		return userId;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}
	public Car() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Car(int carId, String carName, int userId) {
		super();
		this.carId = carId;
		this.carName = carName;
		this.userId = userId;
	}
	@Override
	public String toString() {
		return "Car [carId=" + carId + ", carName=" + carName + ", userId=" + userId + "]";
	}
	
}

汽车名字,与表字段不一致,表字段名为name

我们还需要创建一个Car的接口类、Car的mapper.xml映射类(这两个类名字要相同)
同样还需要在mybatis中配置这个类
CarMapper.java

package com.cbb.mapper;

import java.util.List;
import com.cbb.pojo.Car;
import com.cbb.pojo.UserVo;

public interface CarMapper {
	
	/** 
	 * 方法描述: 查询所有小汽车
	 * @return
	 */
	public List<Car> selectAll();
}

Carmapper.xml

<select id="selectAll" resultType="Car">
		select * from car
		方案一:给sql查询字段as别名,别名和pojo对象的属性名一致 
		 select carId,name carName,userId from car 
	</select>

再写一个测试类测试(我这里只写方法,类就是一个平常的类)

@Test
	public void test() {
		SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession();//获取会话
		CarMapper carMapper = sqlSession.getMapper(CarMapper.class);//获取代理对象
		List<Car> list = carMapper.selectAll();
		System.err.println(list);
		sqlSession.close();
	}

运行我们就会发现,carName会没有值,这就是我们上面所说的错误。

那么,该如何解决这个问题呢?我们有两种解决办法
第一种,给查询的字段重命名:

	<select id="selectAll" resultType="Car">
		方案一:给sql查询字段as别名,别名和pojo对象的属性名一致 
		 select carId,name carName,userId from car 
	</select>

第二种,我们可以使用resultmap进行解决。
解决办法就是先做一个<resultmap>,这个标签和<select>标签是同一级的。如下

<!--type:把结果集映射到那个对象上去  -->
<resultMap type="Car" id="CarMap"></resultMap>
<!--我们再对select进行修改-->
<!-- resultMap:对应自定义的哪个resultMap 的id -->
	<select id="selectAll" resultMap="CarMap">
		select * from car
	</select>

从上面可以看出,我们可以做好几个resultmap,然后根据id想用哪个用哪个。

我们还需要对resultmap进行编写,因为上面只是定义了一个而已,编辑如下

<!-- 
		type:把结果集映射到那个对象上去
		<id/>:结果集的主键 唯一标识
		<result/>: 结果集的 普通字段
			column:表的字段名
			property:pojo对象的属性名
			column和property 在一起表示之间的映射关系
	 -->	 
	<resultMap type="Car" id="CarMap">
		<!-- 可以只在resultMap里配置这个名字不一致的字段 ,名字一致的可以省略掉-->
		<id column="carId" property="carId"/>
		<result column="name" property="carName"/>
		<result column="userId" property="userId"/>
	</resultMap>

在resultmap中,column和property相同,可以省略,只写不一样的(name和carName)就可以,名字一致的可以省略掉。

resultMap:除了能够解决上述的名字不一致的问题外,还可以解决映射复杂的pojo问题。就如一对多关系

一对多关系

比如一个人,可以有多辆车子。我们在数据库中根据连接查询查出来结果(人和车进行表连接),然后要获取展示出来。
我们就需要将获取的信息封装,也就是创建一个pojo对象来接收数据。
我们创建一个UserVo对象
直接继承User类,就不需要再写user的属性了。
然后车子要用一个List接收

package com.cbb.pojo;

import java.util.List;
public class UserVo extends User{
	
	private List<Car> cars;//一对多 一个人可能会有多个汽车

	public List<Car> getCars() {
		return cars;
	}

	public void setCars(List<Car> cars) {
		this.cars = cars;
	}

	@Override
	public String toString() {
		return "UserVo [cars=" + cars + ", getId()=" + getId() + ", getUserName()=" + getUserName() + ", getBirthday()="
				+ getBirthday() + ", getSex()=" + getSex() + ", getAddress()=" + getAddress()  + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + "]";
	}	
}

我们再添加一个功能,在CarMapping.java里面

	/** 
	 * 方法描述:查询所有用户,以及用户下的汽车信息
	 * @return
	 */
	public List<UserVo> selectUserCar();

然后先使用

	@Test
	public void OneToManey() {
		SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession();//获取会话
		CarMapper carMapper = sqlSession.getMapper(CarMapper.class);//获取代理对象
		List<UserVo> list = carMapper.selectUserCar();
		System.err.println(list);
		sqlSession.close();
	}

我们将全部注意力放在映射文件上。

<!-- 一对多用例 -->
 	<select id="selectUserCar" resultType="UserVo">
		SELECT * from `user` u LEFT JOIN car c on u.id = c.userId 
	</select>

但我们会发现,他并没有我们设想的那样封装进去,小汽车根本显示不出来。
所以用resultType根本不管用,我们要用resultMap才行
写我们的reaultMap

<resultMap type="UserVo" id="UserVoMap">
		<id column="id" property="id"/>
		<result column="userName" property="userName"/>
		<result column="sex" property="sex"/>
		<result column="birthday" property="birthday"/>
		<result column="address" property="address"/>
		<result column="" property=""/>
		<result column="" property=""/>
		<!-- 一对多集合  ofType: 集合的类型-->
		<collection property="cars" ofType="Car">
			<id column="carId" property="carId"/>
			<result column="name" property="carName"/>
			<result column="userId" property="userId"/>
		</collection>

此时我们不能进行省略名字相同的字段,(我们现在处理的是一对多关系,而不是名字不相同的问题)。
在一对多的时候,我们就使用<collection>,当我们确定是一对一关系的时候,我们就是用<association>
使用方法如下图
使用方法
以上就是本次的内容

END

猜你喜欢

转载自blog.csdn.net/qq_37989076/article/details/88584892
今日推荐