mybatis的mybatis resultmapp能映射多个类吗

本帖子已过去太久远了,不再提供回复功能。2890人阅读
mybatis(2)
问题描述:在使用mybatis进行多表联合查询时,如果两张表中的字段名称形同,会出现无法正常映射的问题。
问题解决办法:在查询时,给重复的字段 起别名,然后在resultMap中使用别名进行映射。
给出一个小demo:如下是一个**mapper.xml映射文件的一个查询片段,用到了四表联合查询,其中订单id,项目id,回报id,是需要查询的数据,并且字段名都是id,显然是重复字段,此时就需要为这些重复的id起别名了,请看下面的红色部分代码:
&resultMap type=&com.lz.pojo.MyOrder& id=&myOrder&&
&result column=&name& property=&name& /&
&result column=&type& property=&type& /&
&result column=&money& property=&money& /&
&result column=&content& property=&content& /&
&result column=&state& property=&state& /&
&result column=&pic& property=&pic& /&
&result column=&pid& property=&pid& /&
&result column=&hid& property=&hid& /&
&result column=&oid& property=&oid& /&
&/resultMap&
&!-- findMyOrderByUserId:根据用户id,查询我的订单 --&
&select id=&findMyOrderByUserId& parameterType=&int& resultMap=&myOrder&&
SELECT p.name,p.type,o.money,h.content,o.state,h.pic,p.id pid,h.id hid,o.id oid
FROM project p,huibao h,`order` o,`user` u
WHERE o.projectId=p.id AND o.userId=u.id and o.hbId=h.id AND u.id=#{userId}
这样处理后,查询时就可以成功的完成,实体类与查询字段的映射了。
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:13317次
排名:千里之外
原创:10篇
(1)(7)(1)(1)MyBatis用嵌套ResultMap实现一对多映射
MyBatis用嵌套ResultMap实现一对多映射
发布时间: 20:50:23
编辑:www.fx114.net
本篇文章主要介绍了"MyBatis用嵌套ResultMap实现一对多映射 ",主要涉及到MyBatis用嵌套ResultMap实现一对多映射 方面的内容,对于MyBatis用嵌套ResultMap实现一对多映射 感兴趣的同学可以参考一下。
我的技术博客经常被流氓网站恶意爬取转载。请移步原文:/hamhog/p/3959451.html,享受整齐的排版、有效的链接、正确的代码缩进、更好的阅读体验。
我们知道,MyBatis可以很方便地把SQL select出来的数据直接映射为对象的属性,把对象取出来。
但是,有些对象的属性是集合类型,集合里保存的是数个其他类型的对象。如何用MyBatis把它取出来呢?
以以下这个应用场景为例:一个教师对应多个课程。
数据结构如下:
public class Course{
public class Tutor{
List&Course&
}
这时,就需要分别写出两者的ResultMap:
&resultMap type="Course" id="courseResult"&
&result column="course_id" property="id" /&
&result column="course_name" property="name" /&
&/resultMap&
&resultMap type="Tutor" id="tutorResult"&
&id column="tutor_id" property="id" /&
&result column="tutor_name" property="name" /&
&collection property="courses" resultMap="Course" /&
&/resultMap&
然后把select语句的resultMap设为tutorResult:
&select id="findTutorById" parameterType="int" resultMap="TutorResult"&
SELECT TUTOR_ID, TUTOR_NAME, COURSE_ID, COURSE_NAME FROM TUTOR
&/select&
这样就能把Tutor类的数据正确地读进来了。
以上这个例子来自《Java Persistence with MyBatis3》。让我好奇的是,myBatis是如何判断,哪些course应该对应同一个tutor的呢?对于每个course,它是怎么寻找应该把它放进哪个tutor的List里呢?
用以上的例子,数据为:
tutor_name
course_name
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:Mybatis字段映射Map - 有个博客 - ITeye技术网站
博客分类:
Mybatis3的资源优先,官方除了用户指南之外,没有别的资料。源码中的单元测试也没有完整的覆盖业务。
遇到这样的问题,在一个JavaBean中,有一个Map属性,希望这个属性可以映射到Table中的一列。
public class TaskEntity implements Task, Serializable, PersistentObject {
protected Map&String, String& properties = new HashMap&String, String&();
public String getProperty(String key) {
return properties.get(key);
public void setProperty(String key, String value) {
properties.put(key, value);
希望properties可以映射 column="EXECUTION_ID_"。
很明显,需要实现一个TypeHandler,将这个实现命名为 MapTypeHandler
public class MapTypeHandler implements TypeHandler&Map&String, String&& {
private static JsonBinder binder = JsonBinder.buildNonDefaultBinder();
public Map&String, String& getResult(ResultSet rs, String columnName) throws SQLException {
String value = rs.getString(columnName);
return binder.fromJson(value, Map.class);
public Map&String, String& getResult(CallableStatement cs, int columnIndex) throws SQLException {
String value = cs.getString(columnIndex);
return binder.fromJson(value, Map.class);
public void setParameter(PreparedStatement ps, int i, Map&String, String& parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
ps.setNull(i, Types.VARCHAR);
ps.setString(i, binder.toJson(parameter));
setParameter是在Jdbc insert,update会调用到的方法。getResult是在Jdbc select会调用到的方法。
MapTypeHandler中的逻辑很简单,就是用json将Map进行序列化和反序列化,将json格式的内容存储在 column="EXECUTION_ID_"中。
我们有了MapTypeHandler之后,怎么让他在转换类型时生效呢?
答案就是配置类型映射。配置javaType="java.util.Map"与jdbcType="VARCHAR"之间的转换,使用MapTypeHandler。这个配置要写入mappings.xml中。
&configuration&
&settings&
&setting name="lazyLoadingEnabled" value="false" /&
&/settings&
&typeHandlers&
&typeHandler handler="com.apusic.bpm.engine.persistence.MapTypeHandler" javaType="java.util.Map" jdbcType="VARCHAR" /&
&/typeHandlers&
&mapper resource="com/apusic/bpm/db/mapping/entity/Task.xml" /&
&/mappers&
&/configuration&
最后一步就是配置Entity具体的信息,Task.xml中Insert,Update,resultMap中,只要指定property="properties" column="EXECUTION_ID_" javaType="java.util.Map" jdbcType="VARCHAR",系统就会调用MapTypeHandler进行类型映射。
&mapper namespace="com.apusic.bpm.engine.task.impl.TaskEntity"&
&!-- TASK INSERT --&
&insert id="insertTask" parameterType="com.apusic.bpm.engine.task.impl.TaskEntity"&
insert into ACT_RU_TASK (EXECUTION_ID_)
#{properties, jdbcType=VARCHAR, javaType=java.util.Map}
&update id="updateTask" parameterType="com.apusic.bpm.engine.task.impl.TaskEntity"&
update ACT_RU_TASK
EXECUTION_ID_ = #{properties, jdbcType=VARCHAR, javaType=java.util.Map}
&resultMap id="taskResultMap" type="com.apusic.bpm.engine.task.impl.TaskEntity"&
&result property="properties" column="EXECUTION_ID_" javaType="java.util.Map" jdbcType="VARCHAR"/&
&/resultMap&&/mapper&
tigerlchen
浏览: 112806 次
来自: 深圳
WatchKey都没有reset,第二次loop妥妥的捕获不到 ...
复杂对象就需要使用framedecorator了深入浅出Mybatis系列(八)---mapper映射文件配置之select、resultMap
1740次浏览
深入浅出Mybatis系列
本篇将介绍select、resultMap的用法。select无疑是我们最常用,也是最复杂的,mybatis通过resultMap能帮助我们很好地进行高级映射。下面就开始看看select 以及 resultMap的用法:
先看select的配置吧:
1. id (必须配置)
id是命名空间中的唯一标识符,可被用来代表这条语句。
一个命名空间(namespace) 对应一个dao接口,
这个id也应该对应dao里面的某个方法(相当于方法的实现),因此id 应该与方法名一致
id=&selectPerson&
&!-- 2. parameterType (可选配置, 默认为mybatis自动选择处理)
将要传入语句的参数的完全限定类名或别名, 如果不配置,mybatis会通过ParameterHandler 根据参数类型默认选择合适的typeHandler进行处理
parameterType 主要指定参数类型,可以是int, short, long, string等类型,也可以是复杂类型(如对象) --&
parameterType=&int&
&!-- 3. resultType (resultType 与 resultMap 二选一配置)
resultType用以指定返回类型,指定的类型可以是基本类型,可以是java容器,也可以是javabean --&
resultType=&hashmap&
&!-- 4. resultMap (resultType 与 resultMap 二选一配置)
resultMap用于引用我们通过 resultMap标签定义的映射类型,这也是mybatis组件高级复杂映射的关键 --&
resultMap=&personResultMap&
&!-- 5. flushCache (可选配置)
将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false --&
flushCache=&false&
&!-- 6. useCache (可选配置)
将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true --&
useCache=&true&
&!-- 7. timeout (可选配置)
这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)--&
timeout=&10000&
&!-- 8. fetchSize (可选配置)
这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)--&
fetchSize=&256&
&!-- 9. statementType (可选配置)
STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED--&
statementType=&PREPARED&
&!-- 10. resultSetType (可选配置)
FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)--&
resultSetType=&FORWARD_ONLY&&
配置看起来总是这么多,不过实际常用的配置也就那么几个, 根据自己的需要吧,上面都已注明是否必须配置。
下面还是上个demo及时练练手吧:
------------------------------------------------------------------------下面是针对select 的练手demo---------------------------------------------------------------------------------------
数据库:新增两张表(t_course, t_student)
t_student:
其中,1个student可选择多个course进行学习。
我们还是拿上篇文章的demo, 继续写:
增加后,项目目录如下所示:
Course.java:
package com.dy.
public class Course {
private int deleteF
public int getId() {
public void setId(int id) {
public String getName() {
public void setName(String name) {
this.name =
public int getDeleteFlag() {
return deleteF
public void setDeleteFlag(int deleteFlag) {
this.deleteFlag = deleteF
Student.java:
package com.dy.
import java.util.L
public class Student {
private String idC
private List&Course& courseL
private int deleteF
public Student(int id, String idCard, String name, List&Course& courseList, int deleteFlag) {
this.idCard = idC
this.name =
this.courseList = courseL
this.deleteFlag = deleteF
public int getId() {
public void setId(int id) {
public String getIdCard() {
return idC
public void setIdCard(String idCard) {
this.idCard = idC
public String getName() {
public void setName(String name) {
this.name =
public List&Course& getCourseList() {
return courseL
public void setCourseList(List&Course& courseList) {
this.courseList = courseL
public int getDeleteFlag() {
return deleteF
public void setDeleteFlag(int deleteFlag) {
this.deleteFlag = deleteF
CourseDao.java:
package com.dy.
import com.dy.entity.C
public interface CourseDao {
public Course findCourseById(int courseId);
StudentDao.java:
package com.dy.
import com.dy.entity.S
public interface StudentDao {
public Student findStudentById(String idCard);
courseDao.xml:
&mapper namespace=&com.dy.dao.CourseDao&&
1.此处直接将resultType 设置为course, 一看就知道我设置了别名吧,如果没有设置别名,那么resultType = com.dy.entity.Course。
2.可能细心的你会发现:Course.java中的属性名与数据库字段名不一致,下面,我就在sql语句中用了as, 使之匹配,当然方法不止一种,
在学习了resultMap之后,你能看到一种更直观优雅的方式去将javabean中的属性与数据库字段名保持一致
3.findCourseById 与CourseDao中findCourseById方法对应, 那么传入的参数名称以及类型也应该保持对应关系。
4.可以看到,在sql语句中,通过#{}表达式可以获取参数。
5.下面这条sql语句,实际上的形式是怎么样的?还记得之前说过,mybatis默认为preparedStatement吧,那么,用我们jdbc代码来看,它其实就是:
select course_id as id, course_name as name, course_delete_flg as deleteFlag from t_course where course_id=?
&select id=&findCourseById&
resultType=&course& &
select course_id as id, course_name as name, course_delete_flg as deleteFlag from t_course where course_id=#{courseId}
CourseDaoTest.java:
package com.dy.
import java.io.IOE
import org.apache.ibatis.io.R
import org.apache.ibatis.session.SqlS
import org.apache.ibatis.session.SqlSessionF
import org.apache.ibatis.session.SqlSessionFactoryB
import org.junit.T
import com.dy.entity.C
public class CourseDaoTest {
public void findCourseById() {
SqlSessionFactory sqlSessionFactory = getSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
CourseDao courseDao = sqlSession.getMapper(CourseDao.class);
Course course = courseDao.findCourseById(1);
//Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
private static SqlSessionFactory getSessionFactory() {
SqlSessionFactory sessionFactory =
String resource = &mybatis-conf.xml&;
sessionFactory = new SqlSessionFactoryBuilder().build(Resources
.getResourceAsReader(resource));
} catch (IOException e) {
e.printStackTrace();
return sessionF
上面的示例,我们针对course, 简单演示了 select的用法, 不过有个问题值得思考: 一个student可以对应多个course, &那么,在mybatis中如何处理这种一对多, 甚至于多对多,一对一的关系呢?
这儿,就不得不提到 resultMap 这个东西, mybatis的resultMap功能可谓十分强大,能够处理复杂的关系映射, 那么resultMap 该怎么配置呢? 别急,这就来了:
resultMap的配置:
1.type 对应类型,可以是javabean, 也可以是其它
2.id 必须唯一, 用于标示这个resultMap的唯一性,在使用resultMap的时候,就是通过id指定
&resultMap type=&& id=&&&
&!-- id, 唯一性,注意啦,这个id用于标示这个javabean对象的唯一性, 不一定会是数据库的主键(不要把它理解为数据库对应表的主键)
property属性对应javabean的属性名,column对应数据库表的列名
(这样,当javabean的属性与数据库对应表的列名不一致的时候,就能通过指定这个保持正常映射了)
&id property=&& column=&&/&
&!-- result与id相比, 对应普通属性 --&
&result property=&& column=&&/&
constructor对应javabean中的构造方法
&constructor&
&!-- idArg 对应构造方法中的id参数 --&
&idArg column=&&/&
&!-- arg 对应构造方法中的普通参数 --&
&arg column=&&/&
&/constructor&
collection,对应javabean中容器类型, 是实现一对多的关键
property 为javabean中容器对应字段名
column 为体现在数据库中列名
ofType 就是指定javabean中容器指定的类型
&collection property=&& column=&& ofType=&&&&/collection&
association 为关联关系,是实现N对一的关键。
property 为javabean中容器对应字段名
column 为体现在数据库中列名
javaType 指定关联的类型
&association property=&& column=&& javaType=&&&&/association&
&/resultMap&
好啦,知道resutMap怎么配置后,咱们立即接着上面的demo来练习一下吧:
------------------------------------------------------------------下面是用resultMap处理一对多关系的映射的示例-------------------------------------------------------------
一个student对应多个course, 典型的一对多,咱们就来看看mybatis怎么配置这种映射吧:
studentDao.xml:
&mapper namespace=&com.dy.dao.StudentDao&&
&!-- 这儿定义一个resultMap --&
&resultMap type=&student& id=&studentMap&&
数据库中主键是id, 但是我这儿却是指定idCard为主键,为什么?
刚刚讲了,id用来表示唯一性, 我们可以认为只要idCard一样,那么他就是同一个学生。
如果此处用数据库中id, 那么mybatis将会认为数据库中每条记录都是一个student, 这显然不符合逻辑
&id property=&idCard& column=&stu_id_card&/&
&result property=&id& column=&stu_id&/&
&result property=&name& column=&stu_name&/&
&result property=&deleteFlag& column=&stu_delete_flg&/&
这儿就是实现一对多的关键。
在Student中,courseList为List&Course&, 因此,ofType也应该与之对应(当然,我用了别名,不然要蛋疼的写全名了)。
collection的子标签是在指定Course的映射关系(由于Course的javabean的属性名与数据库的列名不一致)
&collection property=&courseList& column=&stu_course_id& ofType=&Course&&
&id property=&id& column=&course_id&/&
&result property=&name& column=&course_name&/&
&result property=&deleteFlag& column=&course_delete_flg&/&
&/collection&
&/resultMap&
&!-- 这儿将返回类型设置成了上面指定的studentMap --&
&select id=&findStudentById& resultMap=&studentMap&&
SELECT s.*, c.* FROM t_student s LEFT JOIN t_course c ON s.stu_course_id=c.course_id WHERE s.stu_id_card=#{idCard}
StudentDaoTest.java:
package com.dy.
import java.io.IOE
import java.util.L
import org.apache.ibatis.io.R
import org.apache.ibatis.session.SqlS
import org.apache.ibatis.session.SqlSessionF
import org.apache.ibatis.session.SqlSessionFactoryB
import org.junit.T
import com.dy.entity.C
import com.dy.entity.S
public class StudentDaoTest {
public void findCourseById() {
SqlSessionFactory sqlSessionFactory = getSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = studentDao.findStudentById(&&);
List&Course& courseList = student.getCourseList();
for (Course course: courseList) {
System.out.println(course.getId() + &
& + course.getName());
//Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
private static SqlSessionFactory getSessionFactory() {
SqlSessionFactory sessionFactory =
String resource = &mybatis-conf.xml&;
sessionFactory = new SqlSessionFactoryBuilder().build(Resources
.getResourceAsReader(resource));
} catch (IOException e) {
e.printStackTrace();
return sessionF
相信通过以上demo, 大家也能够使用mybatis的select 和 resultMap的用法了。上面demo只演示了一对多的映射,其实多对一、多对多也与它类似,所以我就没演示了,有兴趣的可以自己动手再做做。
好啦,本次就写到这儿了。(PS,生病一周了,所以到现在才更新博客)。
另附上demo, 需要的童鞋可以前往下载:
demo 下载地址:/s/1qWjsDzA
您可能也会对以下文章感兴趣
QQ : 341470
Friend Link
New Member}

我要回帖

更多关于 mybatis中的resultmap 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信