Mybatis中ResultMap解決屬性名和數(shù)據(jù)庫(kù)字段名不一致問(wèn)題
前言
我們Pojo類(lèi)的屬性名和數(shù)據(jù)庫(kù)中的字段名不一致的現(xiàn)象時(shí)有發(fā)生,簡(jiǎn)單的情況我們可以開(kāi)啟駝峰命名法解決大小寫(xiě)問(wèn)題,但是遇到其它非大小寫(xiě)問(wèn)題,我們就不得不使用Mybatis中的結(jié)果集映射resultMap。
1. 字段名不一致
數(shù)據(jù)庫(kù)中的字段

我們項(xiàng)目中實(shí)體類(lèi)的字段
public class User {
private int id;
private String name;
private String password;
解決方法:
第一種方式: 起別名
pwd as password
<select id="getUserById" parameterType="int" resultType="com.gs.pojo.User">
select id,name,pwd as password from user1 where id = #{id};
</select>
第二種方式: 結(jié)果集映射 resultMap
使用resultMap匹配pojo類(lèi)中屬性名與數(shù)據(jù)庫(kù)中字段的值。
其中column為數(shù)據(jù)庫(kù)中的字段,property為實(shí)體類(lèi)中的屬性
<!--結(jié)果集映射-->
<resultMap id="UserMap" type="user">
<!--column數(shù)據(jù)庫(kù)中的字段,property實(shí)體類(lèi)中的屬性-->
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" parameterType="int" resultMap="UserMap">
select * from user1 where id = #{id};
</select>
官方文檔有這么一段話:
- resultMap元素是MyBatis中最重要強(qiáng)大的元素
- ResultMap的設(shè)計(jì)思想是,對(duì)簡(jiǎn)單的語(yǔ)句做到零配置,對(duì)于復(fù)雜一點(diǎn)的語(yǔ)句,只需要描述語(yǔ)句之間的關(guān)系就行了。
- ResultMap的優(yōu)秀之處在于你完全可以不用顯示的配置字段名已經(jīng)相同的屬性
根據(jù)官方文檔,上面的結(jié)果集映射可以簡(jiǎn)化為:
<!--結(jié)果集映射-->
<resultMap id="UserMap" type="user">
<!--column數(shù)據(jù)庫(kù)中的字段,property實(shí)體類(lèi)中的屬性-->
<result column="pwd" property="password"/>
</resultMap>
<select id="getUserById" parameterType="int" resultMap="UserMap">
select * from user1 where id = #{id};
</select>
2. 多對(duì)一處理
上面講述的只是普通字段名不一致的問(wèn)題,使用結(jié)果集映射解決相對(duì)簡(jiǎn)單。而在Mybatis中關(guān)于使用結(jié)果集映射解決的問(wèn)題比較出名的有多對(duì)一的處理和一對(duì)多的處理(這兩種問(wèn)題是相對(duì)而言的)
我們生活中有很多相關(guān)的例子,這里以老師和學(xué)生為例,對(duì)于學(xué)生而言,多個(gè)學(xué)生擁有一個(gè)共同的老師,這屬于多對(duì)一問(wèn)題;對(duì)于老師而言,一個(gè)老師擁有多個(gè)學(xué)生,這又是一個(gè)一對(duì)多的問(wèn)題。

相關(guān)解析:
對(duì)于學(xué)生而言,屬于關(guān)聯(lián)現(xiàn)象,多個(gè)老師關(guān)聯(lián)一個(gè)老師 (多對(duì)一)
對(duì)于老師而言,屬于集合現(xiàn)象, 一個(gè)老師擁有很多學(xué)生(一對(duì)多)
測(cè)試環(huán)境搭建;
[1] 建立一個(gè)老師表和學(xué)生表
CREATE TABLE `teacher`(
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(`id`,`name`) VALUES(1,'zs');
CREATE TABLE `student`(
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY(`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher`(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('1','小明','1');
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('2','小紅','1');
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('3','小張','1');
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('4','小李','1');
INSERT INTO `student`(`id`,`name`,`tid`) VALUES('5','小工','1');
[2] 新建一個(gè)Maven項(xiàng)目,導(dǎo)入相關(guān)依賴,并編寫(xiě)實(shí)體類(lèi)及其映射
搭建后項(xiàng)目目錄為:

<1> 導(dǎo)入依賴,并解決打包問(wèn)題
<!--導(dǎo)入依賴-->
<dependencies>
<!--mysql驅(qū)動(dòng)-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
</dependencies>
<!--解決導(dǎo)出項(xiàng)目時(shí)resources的xml未打包問(wèn)題-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
<2> 編寫(xiě)數(shù)據(jù)庫(kù)配置文件 db.properties
driver = com.mysql.jdbc.Driver url = jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8 username = root
<3> 編寫(xiě)Mybatis核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--導(dǎo)入外部配置文件-->
<properties resource="db.properties"/>
<!-- <settings>
<!–標(biāo)準(zhǔn)的日志工廠實(shí)現(xiàn)–>
<!–<setting name="logImpl" value="STDOUT_LOGGING"/>–>
<setting name="logImpl" value="LOG4J"/>
</settings>-->
<!--可以給實(shí)體類(lèi)起別名-->
<typeAliases>
<package name="com.gs.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/gs/dao/TeacherMapper.xml"/>
<mapper resource="com/gs/dao/StudentMapper.xml"/>
<!--<mapper class="com.com.com.gs.dao.TeacherMapper"/>
<mapper class="com.com.com.gs.dao.StudentMapper"/>-->
</mappers>
</configuration>
<4> 編寫(xiě)實(shí)體類(lèi)
這里的Student類(lèi)中有一個(gè)老師的字段,這正是與我們數(shù)據(jù)庫(kù)中不一致的地方,也是這次問(wèn)題解決的重點(diǎn)
Student.class
package com.gs.pojo;
import lombok.Data;
/**
* @Auther: Gs
* @Date: 2020/6/9
* @Description: com.com.com.gs.pojo
* @version: 1.0
*/
@Data
public class Student {
private int id;
private String name;
//組合進(jìn)來(lái)一個(gè)老師
private Teacher teacher;
}
Teacher.class
package com.gs.pojo;
import lombok.Data;
/**
* @Auther: Gs
* @Date: 2020/6/9
* @Description: com.com.com.gs.pojo
* @version: 1.0
*/
@Data
public class Teacher {
private int id;
private String name;
}
<5> 編寫(xiě)接口 StudentMapper
public interface StudentMapper {
//查詢所有的學(xué)生信息,以及對(duì)應(yīng)的的老師的信息
public List<Student> getStudent();
}
<6> 使用resultMap解決問(wèn)題
[1] 按結(jié)果嵌套查詢 使用association字段來(lái)匹配結(jié)果集中Teacher中的字段屬性
<!--按照結(jié)果嵌套處理-->
<select id="getStudent" resultMap="studentMapper2">
select s.id sid, s.name sname, t.name tname
from student s, teacher t
where s.tid = t.id
</select>
<resultMap id="studentMapper2" type="student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
解析:一開(kāi)始看這sql語(yǔ)句肯定很繞,我們先從原生的sql語(yǔ)句出發(fā),編寫(xiě)出能聯(lián)表查詢的語(yǔ)句(因?yàn)閷W(xué)生類(lèi)里有老師這個(gè)實(shí)體屬性)
這里我們使用別名以及聯(lián)表查詢得到學(xué)號(hào),學(xué)生姓名,老師姓名,不難發(fā)現(xiàn)我們使用簡(jiǎn)單的reultType已經(jīng)不能解決這個(gè)多屬性問(wèn)題(resultType適合解決單一實(shí)體類(lèi),字段名和數(shù)據(jù)庫(kù)屬性一一對(duì)應(yīng)的情況),所以我們想到使用結(jié)果集映射 resultMap.
select s.id sid, s.name sname, t.name tname from student s, teacher t where s.tid = t.id
resultMap中前兩項(xiàng)的字段名和屬性名比較好映射,直接是學(xué)生的id,學(xué)生的姓名,可是最后一項(xiàng)的屬性時(shí)一個(gè)Teacher對(duì)象,所以我們必須使用關(guān)聯(lián)association 來(lái)嵌套老師這個(gè)實(shí)體類(lèi)的屬性。相關(guān)語(yǔ)句為:
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
那么完整的隱射語(yǔ)句為:
<resultMap id="studentMapper2" type="student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
最后我們?cè)侔堰@兩個(gè)語(yǔ)句拼接就能得到我們最終的語(yǔ)句了。
[2] 按照查詢嵌套處理 (理解起來(lái)相對(duì)復(fù)雜)
<!--思路: 1.查詢所有的學(xué)生信息
2.根據(jù)查詢出來(lái)的學(xué)生的tid,尋找對(duì)應(yīng)的老師 子查詢
-->
<select id="getStudent" resultMap="studentMapper">
select * from student;
</select>
<resultMap id="studentMapper" type="student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--復(fù)雜的屬性,我們需要單獨(dú)處理 對(duì)象: association 集合: collection -->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id};
</select>
解析:看著語(yǔ)句更加暈了,這其實(shí)相當(dāng)于我們?cè)鶶ql的子查詢,這里分三步走,把原本的結(jié)果集在通過(guò)查詢進(jìn)行封裝。
<1> 編寫(xiě)簡(jiǎn)單的學(xué)生查詢
<select id="getStudent" resultMap="studentMapper">
select * from student;
</select>
<2> 完成相關(guān)實(shí)體類(lèi)屬性和數(shù)據(jù)庫(kù)字段的映射,前兩個(gè)依舊簡(jiǎn)單,關(guān)鍵還是Teacher這個(gè)實(shí)體類(lèi),這次我們不嵌套屬性,而是通過(guò)一次子查詢解決問(wèn)題 (property對(duì)應(yīng)實(shí)體類(lèi)屬性,column對(duì)應(yīng)數(shù)據(jù)庫(kù)名稱,javaType標(biāo)明類(lèi)型,select表示使用查詢的方法)
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
這里使用 getTeacher的方法獲取新的屬性值
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id};
</select>
完整的映射
<resultMap id="studentMapper" type="student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--復(fù)雜的屬性,我們需要單獨(dú)處理 對(duì)象: association 集合: collection -->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
最后,我們把這三句sql進(jìn)行拼裝,就能得到我們上面最終的結(jié)果了。
3. 一對(duì)多處理
同樣是上面的例子,對(duì)老師而言,就是一對(duì)多的關(guān)系
[1] 環(huán)境搭建和上面的一樣
[2] 測(cè)試的實(shí)體類(lèi)的變化
Student
@Data
public class Student {
//學(xué)生id
private int id;
//學(xué)生姓名
private String name;
//教師id
private int tid;
}
Teacher
@Data
public class Teacher {
private int id;
private String name;
//一個(gè)老師有多個(gè)學(xué)生
private List<Student> students;
}
[3] 業(yè)務(wù)需求:獲取指定老師下所有學(xué)生及老師自身的信息
<1> 編寫(xiě)接口
//獲取指定老師下所有學(xué)生及老師的信息
Teacher getTeacher(@Param("tid") int id);
<2> 解決方式依舊是兩種,一種是按結(jié)果嵌套查詢(即所謂的連接查詢),另外一種是按照查詢嵌套處理(即所謂的子查詢)
第一種方式:按結(jié)果嵌套查詢
編寫(xiě)連接查詢的sql語(yǔ)句
<!--按結(jié)果嵌套查詢-->
<select id="getTeacher" resultMap="teacherMap">
select s.id sid, s.name sname, t.id tid, t.name tname from student s, teacher t
where s.tid = t.id and t.id = #{tid}
</select>
通過(guò)結(jié)果集映射找到相應(yīng)的屬性(由于是一對(duì)多關(guān)系,所以使用集合類(lèi)型 collection)
<resultMap id="teacherMap" type="teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--復(fù)雜的屬性:我們需要單獨(dú)處理對(duì)象, 對(duì)象:association 集合:collection
javaType="" 指定屬性類(lèi)型
ofType 指定屬性中的泛型類(lèi)型
-->
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
相關(guān)解析:
復(fù)雜的屬性:我們需要單獨(dú)處理對(duì)象, 多對(duì)一時(shí)使用 association,一對(duì)多是使用collection;
若是普通的pojo類(lèi)使用 javaType="" 指定屬性類(lèi)型,若是泛型類(lèi)型則要使用ofType 指定屬性中的泛型類(lèi)型
3) 我們拼接一下上面兩段代碼即得到我們的結(jié)果
<!--按結(jié)果嵌套查詢-->
<select id="getTeacher" resultMap="teacherMap">
select s.id sid, s.name sname, t.id tid, t.name tname from student s, teacher t
where s.tid = t.id and t.id = #{tid}
</select>
<resultMap id="teacherMap" type="teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--復(fù)雜的屬性:我們需要單獨(dú)處理對(duì)象, 對(duì)象:association 集合:collection
javaType="" 指定屬性類(lèi)型
ofType 指定屬性中的泛型類(lèi)型
-->
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
第二種方式:按照查詢嵌套處理
使用子查詢進(jìn)行拼接
<1> 先查出指定老師的信息
<!--子查詢-->
<select id="getTeacher" resultMap="teacherMap2">
select * from teacher where id = #{tid}
</select>
<2> 由于查詢的信息里有學(xué)生對(duì)象信息,所以得進(jìn)行結(jié)果集映射
<resultMap id="teacherMap2" type="Teacher">
<result property="id" column="id"/>
<collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudent"/>
</resultMap>
解析:
<collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudent"/>
property表明要查詢的實(shí)體類(lèi)屬性名,javaType表明查詢的類(lèi)型,ofType表明泛型的類(lèi)型,select表明使用查詢的方式,這里比較疑惑的應(yīng)該是column的值,它對(duì)應(yīng)的是數(shù)據(jù)庫(kù)中的列,那它應(yīng)該使用什么呢,我們不難發(fā)現(xiàn),我們要查詢的是老師下的所有學(xué)生,而學(xué)生表示通過(guò)老師id進(jìn)行關(guān)聯(lián)的,那么它對(duì)應(yīng)的值應(yīng)該是數(shù)據(jù)庫(kù)的教師id的列名
<3> 最后編寫(xiě)通過(guò)老師id查詢學(xué)生的方法.getStudent
<select id="getStudent" resultType="Student">
select * from student where tid=#{id}
</select>
<4> 最后我們把上面的代碼塊進(jìn)行拼接就能滿足我們的業(yè)務(wù)需求了。
<!-- =============================== -->
<!--子查詢-->
<select id="getTeacher" resultMap="teacherMap2">
select * from teacher where id = #{tid}
</select>
<resultMap id="teacherMap2" type="Teacher">
<result property="id" column="id"/>
<collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudent"/>
</resultMap>
<select id="getStudent" resultType="Student">
select * from student where tid=#{id}
</select>
小結(jié)
解決屬性名不一致的問(wèn)題大體上分為三種情況。簡(jiǎn)單的名字不同,類(lèi)型相同我們可以起別名解決。對(duì)于名字不同,類(lèi)型也不同,我們只能使用結(jié)果集映射解決,這種方式又分為兩種情況,一種是多對(duì)一,一種是一對(duì)多,我們?cè)诮鉀Q多對(duì)一時(shí),可以聯(lián)想學(xué)生和老師的關(guān)系,多個(gè)學(xué)生關(guān)聯(lián)一個(gè)老師,那么我們使用association(關(guān)聯(lián))這個(gè)關(guān)鍵詞,而反過(guò)來(lái),一個(gè)老師下有多個(gè)學(xué)生,屬于集合關(guān)系,那么我們可以使用collection(集合)。
到此這篇關(guān)于Mybatis中ResultMap解決屬性名和數(shù)據(jù)庫(kù)字段名不一致問(wèn)題的文章就介紹到這了,更多相關(guān)Mybatis 屬性名和數(shù)據(jù)庫(kù)字段名不一致內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis一對(duì)多和多對(duì)一處理的深入講解
Mybatis可以通過(guò)關(guān)聯(lián)查詢實(shí)現(xiàn),關(guān)聯(lián)查詢是幾個(gè)表聯(lián)合查詢,只查詢一次,通過(guò)在resultMap里面的association,collection節(jié)點(diǎn)配置一對(duì)一,一對(duì)多的類(lèi)就可以完成,這篇文章主要給大家介紹了關(guān)于Mybatis一對(duì)多和多對(duì)一處理的相關(guān)資料,需要的朋友可以參考下2021-09-09
@Transactional跟@DS動(dòng)態(tài)數(shù)據(jù)源注解沖突的解決
這篇文章主要介紹了@Transactional跟@DS動(dòng)態(tài)數(shù)據(jù)源注解沖突的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
Java如何基于IO流實(shí)現(xiàn)同一文件讀寫(xiě)操作
這篇文章主要介紹了Java如何基于IO流實(shí)現(xiàn)文件讀寫(xiě)操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
Spring實(shí)戰(zhàn)之方法級(jí)別緩存用法示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之方法級(jí)別緩存用法,結(jié)合實(shí)例形式分析了spring方法級(jí)別緩存配置、屬性文件、領(lǐng)域模型及相關(guān)使用技巧,需要的朋友可以參考下2020-01-01
java監(jiān)聽(tīng)器的實(shí)現(xiàn)和原理詳解
這篇文章主要給大家介紹了關(guān)于java監(jiān)聽(tīng)器實(shí)現(xiàn)和原理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
SpringBoot解決Required?String?parameter?xxx?is?not?prese
這篇文章主要介紹了SpringBoot解決Required?String?parameter?xxx?is?not?present問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01

