前提
学生对象不会变如下:
package com.xzd.domain;
public class Student {
Integer sid;
String sname;
int sage;
String ssex;
public Student() {
}
public Student(Integer sid, String sname, int sage, String ssex) {
this.sid = sid;
this.sname = sname;
this.sage = sage;
this.ssex = ssex;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public int getSage() {
return sage;
}
public void setSage(int sage) {
this.sage = sage;
}
public String getSsex() {
return ssex;
}
public void setSsex(String ssex) {
this.ssex = ssex;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", sage=" + sage +
", ssex='" + ssex + '\'' +
'}';
}
}
数据库中的表和数据:
CREATE DATABASE /*!32312 IF NOT EXISTS*/`testmybatis` /*!40100 DEFAULT CHARACTER SET utf8mb3 */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `testmybatis`;
/*Table structure for table `student` */
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`s_id` int DEFAULT NULL,
`sname` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
`sage` int DEFAULT NULL,
`ssex` varchar(2) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*Data for the table `student` */
insert into `student`(`s_id`,`sname`,`sage`,`ssex`) values
(1,'张三',18,'男'),
(2,'赛貂蝉',14,'女'),
(3,'胡铁花',23,'男'),
(4,'白飞飞',16,'女'),
(5,'李寻欢',16,'男'),
(4,'宫崎',18,'男');
对于查询,有时候返回的不一定是一个以定义对象类,所以也会返回不同的数据,如果处理,本篇就是简单的聊一些这个问题。主要是关键属性resultType。
返回对象
这个在前面演示的大都是返回的的是对象,所以就简单的说一下配置文件
<select id="[包路径.]方法名" resultType="[包路径.]对象类">
</select>
可以写完整的路径,或者在核心配置文件mybatis-config.xml使用typeAliases+package两个标签,加入包路径,直接写类名:
<typeAliases>
<package name="对象类的包路径"/>
</typeAliases>
而方法的包路径可以如下写:
<mappers>
<package name="映射配置文件中id等于的方法包路径" ></package>
</mappers>
如果不懂可以看下,核心配置文件的常用标签:传送阵
返回值是集合
比如返回的是多个对象呢,如下操作:
<select id="getAllStudent" resultType="Student">
SELECT sid,sname,sage,ssex FROM`testmybatis`.`student`
</select>
在映射中如此:
public interface StudentMapper {
List<Student> getAllStudent();
}
但是看配置文件的话,感觉其返回都是resultType=“Student” ,但是为什么返回的一个是对象,一个确实对象的list,其本质还是底层会通过接口返回的值进行判断而返回不同的数据。
所以看一下结果:
返回值(比如一共多少行)
有时候会通过聚合函数得到一个值,而这个值又不是对象属性值,如下操作。
<select id="getStudentCount" resultType="java.lang.Integer">
SELECT count(ssex)
FROM `testmybatis`.`student`
</select>
在映射中如此:
public interface StudentMapper {
int getStudentCount();
}
然后运行程序:
可以看出因为反射回来的是一个数字所以类型用:java.lang.Integer
但是如果将resultType="java.lang.Integer"换成resultType="Integer"或resultType="int"运行结果一样,为什么会这样,其实看一下官网文档:
可以看出mybatis为了方便使用,其框架本身就些了一些别名,方便我们使用。可以通过别名来代替一些,可以如此从尝试:
补充
当然如果是对象也可以转换为map,比如这样
public interface StudentMapper {
Map<String, String> getStudent(@Param("sid") String sid);
}
<select id="getStudent" resultType ="hashmap">
SELECT sid,sname,sage,ssex FROM`testmybatis`.`student` where sid=#{sid}
</select>
这个可以看出一件事,那就是数据库返回的值,会自动将属性名作为map的key值。注意如果返回的某个值是null,那就不会放在map中。所以不是所有的属性值都会转换为map的key,也就是上面如果四个属性都有值,但是我只写三个,那就是map就含有三个key。
当然如果将映射文件写如下:
<select id="getStudentByMap" resultType="hashmap">
SELECT sid, sname, sage, ssex, COUNT(sid)
FROM `testmybatis`.`student`
WHERE sid = #{sid}
GROUP BY sid, sname, sage, ssex
</select>
如果是对象的话,可能无法得到了,这个时候需要resultType ="hashmap"来进行:
但是如果resultType ="Student"的话如下:
<select id="getStudentByMap" resultType="Student">
SELECT sid, sname, sage, ssex, COUNT(sid)
FROM `testmybatis`.`student`
WHERE sid = #{sid}
GROUP BY sid, sname, sage, ssex
</select>
那么就如上了:
因为Student中没有属性 COUNT(sid)这个值,所以无法得到这个值。
当然上面的例子返回的一条数据,如果是一个很多数据呢,其实很简单和返回,然后在映射类中如下下:
public interface StudentMapper {
List<Map<String, String>> getStudent(@Param("sid") String sid);
}
因为和返回对象集合类似,就不再演示了。
补充 注解@MapKey(“”)
这个时候如果返回的数据是一个集合的,如果非要用map进行保存,但是这个有一个问题,那就是如果单挑数据,可以同属性值作为key,但是一个大map保存所有数据得到的map,那么这个map的key值就需要用通过这个注解来实现,如下操作:
@MapKey("sid")
Map<String, Object> getStudent(@Param("sid") String sid);
也就是将属性sid作为key的值,演示如下:
处理数据库表列名与属性名无法匹配
一般的时候最理想的情况就是在创建表种的列名(字段)和java对象属性名。但是这个时候在开发过程种会有规范。
1:java开发中对象的属性名采用的是驼峰命名方式,比如:studentName
2:mysql中的列名(字段)名要求使用下划线(_),比如student_name
首先将表中的student中字段sid变为s_id,其它的不变。
然后映射接口:
public interface StudentMapper {
Student getStudent(@Param("sid") String sid);
}
映射文件如下:
<select id="getStudent" resultType="Student">
SELECT s_id, sname, sage, ssex
FROM `testmybatis`.`student`
WHERE s_id = #{sid}
</select>
可以看结果:
当然不会报错,只不过是返回一个空值而已。
但是如果返回的map呢?
public interface StudentMapper {
Map<String,String> getStudent(@Param("sid") String sid);
}
当然如果使用接受数据的是map:
<select id="getStudent" resultType="hashmap">
SELECT s_id, sname, sage, ssex
FROM `testmybatis`.`student`
WHERE s_id = #{sid}
</select>
如果返回的是map的话,就没有这个问题,因为从这个地方可以知道如果不是通过student接受数据而是map接受数据的话,其key值其实是字段名,而不一定是属性名。
通过sql中as 使用别名
当然还可以通过修改别名的方式也是可以的,也就是在sql语句中使用as修改别名
,如果将其变成如下:
<select id="getStudent" resultType="Student">
SELECT s_id as sid, sname, sage, ssex
FROM `testmybatis`.`student`
WHERE s_id = #{sid}
</select>
通过配置文件添加mapUnderscoreToCamelCase
但是如果字段很多的话,使用别名就有点麻烦了,所以可以通过配置文件来配置默认映射关系,将下划线和驼峰进行匹配:
在mybatis-config.xml添加如下配置信息:
<setting name="mapUnderscoreToCamelCase" value="true"/>
然后还是通过上面的配置返回的
public interface StudentMapper {
Student getStudent(@Param("sid") String sid);
}
<select id="getStudent" resultType="Student">
SELECT s_id, sname, sage, ssex
FROM `testmybatis`.`student`
WHERE s_id = #{sid}
</select>
然后看得到结果:
使用resultMap
其实如果简单的这样说的话,可能有些懵,这个在resultType =“hashmap”,不就是返回一个map吗,为什么还要有这个属性名?
其实在IDE种输入会有提示如下:
这个如何使用呢?还是老规矩进行实例演示:
<resultMap id="studentmap" type="Student">
<id column="s_id" property="sid"></id>
<result column="sname" property="sname"></result>
<result column="sage" property="sage"></result>
<result column="ssex" property="ssex"></result>
</resultMap>
<select id="getStudent" resultMap="studentmap">
SELECT s_id, sname, sage, ssex
FROM `testmybatis`.`student`
WHERE s_id = #{sid}
</select>
如果resultMap只是为了解决这个数据库列名(字段)那就是有的太简单了还有后面标签的意义,这个后面再聊。