输入类型
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