多表联查
在数据库查询中,很多时候不只是查询一张表,而是需要将多张表结合起来才能获得需要的数据,下面介绍在mybatis中怎么实现多表联查(前提是所有的依赖均已配置完成)
一、步骤一:创建pojo实体类
将需要用到的表全部创建成java的实体类,导入lombok依赖(自动生成get、set等方法)
User 用户表 Order 订单表
@Datapublic class User { private Integer ID; private String username; private String PASSWORD; private String sex; private Date brithday; private String address;}
二、步骤二:明确两个实体类之间的关系
一个用户可以有多条订单,而一条订单只属于一个用户
所以;:用户对订单是1对多
的关系
在设计数据库时(黄色部分)
:在多的一方(tb_order)中添加一个外键,与tb_user的主键对应(图中为uid)
在设计java对象时(红色部分)
: 需要根据题目进行pojo类的编写(具体看步骤三)
三、步骤三:修改pojo实体类
先分析清楚题目 如:
①:根据id查询订单以及订单的所属用户信息
=>
返回的数据是tb_order表中的数据+tb_user表中的数据,需要修改的实体类是Order,因为是根据order的id查询的
//需要在Order的实体类中引入User对象public class Order { private Integer id; private Integer userid; private Date createtime; private String state;// 多对一 private User user = new User();}
②:根据用户id查询她的各类订单
=>
返回的数据是tb_user+tb_order表中的数据,但是不同与上面的是:由于订单有多条所以订单需要用集合来装,而查询出的数据是要根据用户的id查询所有需要修改User类
// 需要在User表中的实体类中引入数据类型为Order的集合public class User implements Serializable { private Integer ID; private String username; private String PASSWORD; private String sex; private Date brithday; private String address;// 一对多 private List<Order> orders = new ArrayList<>();}
四、步骤四:编写Mapper接口
public interface UserMapper {// 通过订单id查询订单详情以及所属用户 Order selectOrderAndInfoById(@Param("oid") int id);// 通过用户id查询该用户的所有订单 User selectByUserIdForOrder(@Param("uid") int id);// 根据id查询用户 User selectUserByid(@Param("uid") int id);}
五、步骤五:编写Mapper映射文件
需要指定该映射文件是步骤四的Mapper,在namespace中指定
重点来了:
题目1:通过订单id查询订单详情以及所属用户
需要知道的是我们关联的是两张表
,如果直接用下面的sql语句则只能查出订单的信息而订单所属用户则为空
,这是因为在执行过程中Order会自动映射到tb_order的内容,但是在Order表中定义的User对象则无法自动映射
到tb_user表中的内容
SELECT u.ID ,u.username,u.PASSWORD,u.sex,u.brithday,u.address,o.id oid,o.userid,o.createtime,o.stateFROM tb_user u JOIN tb_order oON u.ID = o.useridWHERE u.id= #{uid}
所以我们得手动映射User类
,需要使用到resultMap
总体代码如下:
<!-- todo 根据id查询订单以及对应的用户 --> <sql id="selectById"> u.ID ,u.username,u.PASSWORD,u.sex,u.brithday,u.address, o.id oid,o.userid,o.createtime,o.state </sql> <resultMap id="selectParent" type="Order"> <id property="id" column="oid"/> <result property="userid" column="userid"/> <result property="createtime" column="createtime"/> <result property="state" column="state"/> </resultMap> <resultMap id="selectChildren" type="Order" extends="selectParent"> <association property="user" javaType="User" select="selectUserByid" column="userid"/> </resultMap> <select id="selectOrderAndInfoById" resultMap="selectChildren"> SELECT <include refid="selectById"/> FROM tb_user u JOIN tb_order o ON u.ID = o.userid WHERE o.id = #{oid} </select> <!-- 根据id查询用户--> <select id="selectUserByid" resultType="User"> SELECT * FROM tb_user WHERE ID = #{uid} </select>
selectParent
为手动映射的Order类的Map,selectChildren
为手动映射的User类的Map,由于需要返回的订单类
的数据所有type
中填写Order类,children
继承了parent
那么children中也会有parent的映射,所有selectChildren
的map中就有了Order+User
的映射
这个时候再标签
resultMap
中只需要传入selectChildren
就可以了
<association property="user" javaType="User" select="selectUserByid" column="userid"/>
association
:因为在Order类中的User对象是单
个,所以使用该关键字
property
:对应Order表中的创建的User对象名
javaType
:property对应的数据类型
select
:就是指映射user对象去改方法中找,刚刚selectUserByid
方法返回的就是一个User
对象,这样就免去了手动一 一映射的麻烦
column
:但是selectUserByid
需要传入一个参数,这里传入的userid是从Order
中查询得到的然后再传给该方法去查询对应的User
题目2:通过用户id查询用户信息以及她所有的订单
学会了上面的知识后,这里就只是发生了一点点的变化
同样也是,是根据用户的id查询所以需要在User类中进行操作,而一个用户有多条订单,所以需要在用户类User中定义一个Order类型的集合,mybatis也只能映射User类和tb_user表,无法映射Order类和tb_order表,所以我们也需要手动映射
总体代码如下:
<!-- todo 根据用户id查询订单 --> <resultMap id="Userparent" type="User"> <id column="ID" property="ID"/> <result column="username" property="username"/> <result column="PASSWORD" property="PASSWORD" /> <result column="sex" property="sex" /> <result column="brithday" property="brithday" /> <result column="address" property="address" /> <collection property="orders" ofType="Order" > <id column="oid" property="id"/> <result column="userid" property="userid"/> <result column="createtime" property="createtime"/> <result column="state" property="state" /> </collection> </resultMap> <select id="selectByUserIdForOrder" resultMap="Userparent" parameterType="int"> SELECT <include refid="selectById"/> FROM tb_user u JOIN tb_order o ON u.ID = o.userid WHERE u.id= #{uid} </select>
与上面不同的是集合映射使用关键字collection
,并且返回类型不再使用type
而是使用ofType
来指定
前面题目一映射是使用的继承
,现在题目二映射是直接在父映射中
继续映射,并且没有使用方法
六、补充
id | 唯一标识符 |
type | 写返回的类的类名 |
| 对非主键的映射 |
对主键的映射 | |
property | 关联属性名 也就是User类中定义的各属性 |
column | 关联属数据库的字段 |
javaType | 关联属性的数据类型 在集合属性时不要写,但是在题目一的情况下就需要使用 |
ofType | 关联属性的数据类型 在集合属性时写,但是在题目一的情况下就不要使用 |
来源地址:https://blog.csdn.net/qq_52998673/article/details/128121638