上一章节中我们已经完成了对单表的CRUD操作,接下来今天这一讲讲述的是关于Mybatis在多表查询时候的应用,毕竟实际业务中也是多表的联合查询比较多嘛~

还记得最一开始我们新建过一张Website表吗,在那张表里有个VisitorId字段,表示访问者访问过哪些网站,现在我们先按照上一张中的要求把关于Website的JavaBean实体先建立出来。

还是在david.mybatis.model包下面新建一个Website类,用来持久化数据之用,重写下相应toString()方法,方便测试程序之用。

package david.mybatis.model;

import java.text.SimpleDateFormat;
import java.util.Date; public class Website {
private int id;
private String name;
private int visitorId;
private int status;
private Date createTime;
private Visitor visitor; public Website() {
// TODO Auto-generated constructor stub
createTime = new Date();
visitor = new Visitor();
} public Website(String name, int visitorId) {
this.name = name;
this.visitorId = visitorId;
visitor = new Visitor();
status = 1;
createTime = new Date();
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public Visitor getVisitor() {
return visitor;
} public void setVisitor(Visitor visitor) {
this.visitor = visitor;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getStatus() {
return status;
} public void setStatus(int status) {
this.status = status;
} public Date getCreateTime() {
return createTime;
} public void setCreateTime(Date createTime) {
this.createTime = createTime;
} public int getVisitorId() {
int id = 0;
if (visitor == null)
id = visitorId;
else
id = visitor.getId();
return id;
} public void setVisitorId(int visitorId) {
this.visitorId = visitorId;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder(String.format("Website=> {Id:%d, Name:%s, CreateTime:%s}\r\n", id, name,
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTime)));
if (visitor != null)
sb.append(String.format("Visitor=> %s", visitor.toString()));
return sb.toString();
}
}

Website实体类

在david.mybatis.demo下面分别新建相应的操作接口:

package david.mybatis.demo;

import java.util.List;
import david.mybatis.model.Website; public interface IWebsiteOperation { public int add(Website website); public int delete(int id); public int update(Website website); public Website query(int id); public List<Website> getList(); }

Website操作接口

在mapper文件夹下新建WebsiteMapper.xml映射文件,分别参照上一张所说的把增删改查的单表操作配置分别放进去,这样你可以建造一点测试数据。如下

<?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="david.mybatis.demo.IWebsiteOperation">
<sql id="getListSql">
select id,
name, VisitorId, status, createTime from Website
where status>0
</sql>
<insert id="add" parameterType="Website" useGeneratedKeys="true"
keyProperty="Id">
insert into Website (Name, VisitorId, Status, CreateTime)
values (#{name}, #{visitorId}, #{status}, #{createTime})
</insert>
<delete id="delete" parameterType="int">
delete from website where
status>0 and id = #{id}
</delete>
<update id="update" parameterType="Website">
update website set
name=#{name} where status>0 and id=#{id}
</update>
<select id="query" parameterType="int" resultMap="websiteRs">
select
Website.id siteId, Website.name siteName, Visitor.Id visitorId,
Visitor.name visitorName,
Website.status siteStatus, Website.createtime
siteCreateTime from Website
inner join Visitor on Website.visitorid =
Visitor.id where Website.status>0 and
Website.id=#{id}
</select>
<resultMap type="Website" id="websiteRs">
<id column="siteId" property="id" />
<result column="siteName" property="name" />
<result column="siteStatus" property="status" />
<result column="siteCreateTime" property="createTime" />
<association property="visitor" javaType="Visitor" resultMap="visitorRs" />
</resultMap>
<resultMap type="Visitor" id="visitorRs">
<id column="visitorId" property="id" />
<result column="visitorName" property="name" />
</resultMap>
<select id="getList" resultMap="websiteByVisitorIdRs">
<include refid="getListSql" />
</select>
</mapper>

WebsiteMapper配置

这里今天主要说的就是那个查,现在我们想要查询网站的同时分别把相应的访问者信息一起拿出来,怎么做呢,大家可以参照配置中的query,写下联表查询的SQL,

这里主要要注意的是,Website实体与Visit的实体里面Id与Name这2个属性都是一样的,所以为了避免映射出现出错现象,把相应的查询结果列起上不一样的别名,这样绑定的时候就可以避免

假如我像下面一样配置会得到什么呢?

<select id="query" parameterType="int" resultMap="websiteRs">
select
Website.id, Website.name siteName, Visitor.Id,
Visitor.name visitorName,
Website.status siteStatus, Website.createtime
siteCreateTime from Website
inner join Visitor on Website.visitorid =
Visitor.id where Website.status>0 and
Website.id=#{id}
</select>
<resultMap type="Website" id="websiteRs">
<id column="id" property="id" />
<result column="siteName" property="name" />
<result column="siteStatus" property="status" />
<result column="siteCreateTime" property="createTime" />
<association property="visitor" javaType="Visitor"
resultMap="visitorRs" />
</resultMap>
<resultMap type="Visitor" id="visitorRs">
<id column="id" property="id" />
<result column="visitorName" property="name" />
</resultMap>

可能引起错误的配置

有木有发觉,Visitor的Id也变成2了,这个其实它默认映射了Website的ID,因为SQL语句查询出来的结果2个ID都是变成2了,有人会问为什么不是4呢,因为他默认匹配第一个如果你把Website.Id与Visit.Id的位置,相互换下就会发现结果又神奇的变了

所以需要起个别名避免这种情况,这样你就会发现真相其实只有一个就是下面的:

大家可以看到其实多表处理resultMap的方式和单表是一致的,也无非是吧列明与Javabean属性名成对应上去,可以看到在Website的<resultMap>节点里面前台另外一个resultMap,他就是代表Visit实体所需要映射的实体,可以使用以下方式进行关联

<association property="visitor" javaType="Visitor" resultMap="visitorRs" />

其中的visitor就是Website实体中的visit字段名,必须保证名称一致,否则就会抛出There is no getter for property named 'XXX' in 'class david.mybatis.model.Website'的异常,这在上几章已经讲述了,当然如果你觉得不用嵌套resultMap也行,嵌套也是出于其他地方可以还要用到这个配置那就提炼出来的过程,也是抽象出来的一种思想。具体使用<resultMap>中的ID与Result可以从官网查找相应区别说明:http://mybatis.github.io/mybatis-3/sqlmap-xml.html#Result_Maps

这样,一个简单的多表联合查询就出来啦~,如果还有更加复杂的查询业务费是在这个基础上些许的变通修改。

这章就到此为止啦,下一章会继续跟讲下,如何弄一个简单的Mybatis下的分页效果~^0^

一步步学Mybatis-实现多表联合查询(4)的更多相关文章

  1. Mybatis oracle多表联合查询分页数据重复的问题

    Mybatis oracle多表联合查询分页数据重复的问题 多表联合查询分页获取数据时出现一个诡异的现象:数据总条数正确,但有些记录多了,有些记录却又少了甚至没了.针对这个问题找了好久,最后发现是由于 ...

  2. mybatis Plus 多表联合查询

    //实体类package com.sk.skkill.entity; import com.baomidou.mybatisplus.annotation.TableField;import com. ...

  3. mybatis实现多表联合查询

    本文转自:http://www.cnblogs.com/xdp-gacl/p/4264440.html#!comments 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) ...

  4. MyBatis 多表联合查询及优化 以及自定义返回结果集

    下面就来说一下 mybatis 是通过什么来实现多表联合查询的.首先看一下表关系,如图: 这 里,我已经搭好了开发的环境,用到的是 SpringMVC + Spring + MyBatis,当然,为了 ...

  5. 一步步学Mybatis-实现单表情况下的CRUD操作 (3)

    今天这一章要紧接上一讲中的东西,本章中创建基于单表操作的CRUD与GetList操作,此示例中以Visitor表为范例,为了创建一点测试数据我们先弄个Add方法吧 继续在上次的IVisitorOper ...

  6. MyBatis之三:多表联合查询

    在这篇文章里面主要讲解如何在mybatis里面使用一对一.一对多.多表联合查询(类似视图)操作的例子. 注:阅读本文前请先大概看一下之前两篇文章. 一.表结构 班级表class,学生表student, ...

  7. MyBatis 多表联合查询,字段重复的解决方法

    MyBatis 多表联合查询,两张表中字段重复时,在配置文件中,sql语句联合查询时使用字段别名,resultMap中对应的column属性使用相应的别名: <resultMap type=&q ...

  8. mybatis:开发环境搭建--增删改查--多表联合查询(多对一)

    什么是mybatisMyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML或 ...

  9. MVC5+EF6简单实例---以原有SQLServer数据库两表联合查询为例

    有二三年没写代码了,**内的工作就是这样,容易废人!看到园子里这么多大侠朝气蓬勃的,我想也要学点东西并和大家分享,共同进步!快乐每一天,进步每一天!言归正传! 通过最近一段时间对MVC5.EF6的学习 ...

随机推荐

  1. python中隐式的内存共享

    在python中,基本上使用的是引用,那么就会造成一个隐式的内存共享,特别是在容器对象中,例如list,dictionary 对于不可变对象,是不会造成隐式的内存共享情况,如下所示: >> ...

  2. python中的多线程【转】

    转载自: http://c4fun.cn/blog/2014/05/06/python-threading/ python中关于多线程的操作可以使用thread和threading模块来实现,其中th ...

  3. 【加解密】关于DES加密算法的JAVA加密代码及C#解密代码

    JAVA加密: package webdomain; import java.security.Key; import java.security.spec.AlgorithmParameterSpe ...

  4. java多线程之Lock线程同步

    1.线程同步: package cn.itcast.heima2; import java.util.concurrent.locks.Lock; import java.util.concurren ...

  5. Node-APN 开源推送服务

    Node-APN是一个开放的结合了苹果推送通知的Node.js模块,该源码模块使用简单,反馈服务支持.错误处理,在发送出错时自动重发.遵从苹果的最佳实践. Node-APN(github)

  6. HTTP Status 500 - Servlet.init() for servlet htmlWebConfig threw exception

    HTTP Status 500 - Servlet.init() for servlet htmlWebConfig threw exception

  7. 转】使用log4jdbc记录SQL信息

    原博文出自于: http://www.cnblogs.com/xdp-gacl/p/4081848.html 感谢! 一.log4jdbc的简单介绍 使用log4jdbc在不改变原有代码的情况下,就可 ...

  8. xcode报错:Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/b

    今天使用xcode编译工程发现一个问题,这里记录一下防止忘记 xcode报错: Command /Applications/Xcode.app/Contents/Developer/Toolchain ...

  9. 一、 使用存储过程实现数据分页(Sql Server 2008 R2)

    1.废话不多说了,直接上代码.调用这个存储过程只需要传递 表名,排序字段,搜索字段,以及页码,页码数量,搜索值(可空) create PROCEDURE NewPage --通用的分页存储过程,百万数 ...

  10. Codeforces Round #368 (Div. 2) A. Brain's Photos (水题)

    Brain's Photos 题目链接: http://codeforces.com/contest/707/problem/A Description Small, but very brave, ...