一、准备订单order表和Order实体类
public class Order {
// 订单id
private int id;
// 用户id
private Integer userId;
// 订单号
private String number;
// 订单创建时间
private Date createtime;
// 备注
private String note;
//省略get set方法和toString方法
}
注:可以发现order表中的字段user_id和Order类中的成员变量userId不相同。
二、查询所有订单信息
1、持久层接口
src\main\java\cn\cyl\dao\OrderDao.java
public interface OrderDao {
public List<Order> findAll();
}
2、持久层接口的映射配置:记得在核心配置文件SqlMapConfg.xml文件配置该映射
src\main\java\cn\cyl\dao\OrderDao.java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.cyl.dao.OrderDao">
<select id="findAll" resultType="cn.cyl.bean.Order">
<!--order是数据库关键字,需要打``符号-->
select * from `order`;
</select>
</mapper>
3、加入查询的测试方法
@Test
public void test01(){
SqlSession sqlSession = MySessionUtils.getSession();
//获取Order接口的实现类对象
OrderDao dao = sqlSession.getMapper(OrderDao.class);
//使用集合接收
List<Order> list = dao.findAll();
System.out.println(list);
for (Order order:list){
System.out.println(order);
}
sqlSession.close();
}
4、控制台输出
5、总结
- 为什么id属性能被Mybatis赋值?
底层使用从sql语句查询的字段名id生成setId方法名,
使用反射生成实体类对象调用setId方法来赋值。 - 为什么userId不能被赋值?
底层使用sql语句查询的字段名是user_id,生成setUser_id方法名,
使用反射生成实体类对象调用setUser_id方法,而类中只有setUserId方法。
如果对上述话不了解,我们可以看看查询字段与成员变量的映射原理。
三、下面我们编写一个测试类来模拟底层原理
@Test
public void test01() throws Exception {
//获取数据库中传来的字段名
String name = "id";
//然后将首字母大写
name = "Id";
//方法名字:采用拼接的方式 set+变量名(首字母大写)
String methodName = "setId";
//通过反射实例化对象
Class clz = Class.forName("cn.cyl.bean.Order");
Object orderObj = clz.newInstance();
//获取实例化对象中的方法:参1:方法名 参2:参数类型
//也就是去寻找有无setId方法
Method method = clz.getMethod(methodName,int.class);
//执行该方法,相当于order对象调用setId(int i)方法
method.invoke(orderObj,10);
}
看完这段代码,就知道id属性是能成功被赋值的,从而知道userId属性是不能被赋值的。
总之就是
接收到从数据库传来的字段名,要和类成员变量名对应才能赋值;
如果不对应,就找不到该方法进行赋值
解决办法
1.修改类成员变量名字
2.修改字段名字
3.在sql语句中,将字段名取别名,该别名和类成员变量名字一样
<select id="findAll" resultType="order">
<!--order是数据库关键字,需要打``符号-->
select o.id,
o.user_id as userId,
o.number,
o.createtime,
o.note
from `order` o;
</select>
如果我们的查询很多,都使用别名的话写起来岂不是很麻烦,有没有别的解决办法呢?
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类 型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。
四、resultMap 结果类型
1、ResultMap有什么用?
- 建立查询字段与实体类成员变量的映射关系
即查询字段是user_id但是Mybatis去赋值userId
- 字段名与变量名不一致,可以赋值
- 实现一对多,多对多的查询
- ResultMap标签映射关系,resultMap使用
在不改表,也不改类的基础上,完成查询数据对变量的赋值。
2、定义ResultMap
<!--id:映射的唯一标识,给查询select标签引用用的。
type:指定实体类的全限定类名-->
<resultMap id="OrderMap" type="cn.cyl.bean.Order">
<!--id:指定主键字段
column:数据库表的字段名;
property:实体类的成员变量名-->
<id column="id" property="id"></id>
<!--result:指定非主键字段-->
<result column="user_id" property="userId"/>
<!--查询字段名和类的变量名相同的可以不写-->
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
</resultMap>
<!--resultMap:指向一个id为OrderMap的映射关系-->
<select id="findAll" resultMap="OrderMap">
<!--order是数据库关键字,需要打``符号-->
select * from `order`;
</select>
三、返回值为Map类型 处理
3.1 知道返回值的数据类型
<select id="countByCourse" resultType="map">
select
c.name,
sum(case when score>=#{score} then 1 else 0 end)good,
sum(case when score<#{score} then 1 else 0 end)notgood
from course c left join sc on c.id = sc.cid group by cid
</select>
3.1.1 返回的数据有一条 Map<String,String>
//统计
Map<String,String> countByCourse(@Param("score")int score);
3.1.2 多条数据 List<Map<String,String>>
//统计
List<Map<String,String>> countByCourse(@Param("score")int score);
3.2 不知道返回值的类型,
比如说查询的值有时间之类的,我们可以用Map<String,Object>来接收
3.3 想设置自己想要的 键 名字可以通过resultMap
type=“hashMap” 或者 type=“map” 都可以
<resultMap id="sheet_Map" type="hashMap">
<result property="columnName" column="COLUMN_NAME"/>
<result property="data_type" column="DATA_TYPE"/>
</resultMap>
<select id="querySheet" resultMap="sheet_Map">
select DISTINCT COLUMN_NAME,DATA_TYPE from information_schema.COLUMNS where table_name = 'student2'
</select>