您的位置:首页 > 其它

MyBatis关系映射

2017-07-12 18:32 281 查看

概述+数据模型

Mybatis关系映射主要是包括一对一,一对多,多对一,和多对多关系。

再进行我们关系映射的时候,我们需要有一个数据模型来模拟我们对应的相应关系,我们采用的数据模型为用户和订单,订单和订单明细,以及商品之间的关系。

数据库表:

用户表user:记录了购买商品的用户信息。

订单表orders:记录了用户所创建的订单(购买商品的订单)。

订单明细表orderdetail:记录了订单的详细信息即购买商品的信息。

商品表items:记录商品信息。

数据模型图:



数据表之间的关系:

先分析数据级别之间有关系的表之间的业务关系:

usre和orders:

user —-> orders:一个用户可以创建多个订单,一对多

orders —-> user:一个订单只由一个用户创建,一对一

orders和orderdetail:

orders —-> orderdetail:一个订单可以包括 多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在orderdetail记录,一对多关系。

orderdetail —-> orders:一个订单明细只能包括在一个订单中,一对一

orderdetail和itesm:

orderdetail —-> itesms:一个订单明细只对应一个商品信息,一对一

items —-> orderdetail:一个商品可以包括在多个订单明细 ,一对多

再分析数据库级别没有关系的表之间是否有业务关系:

orders和items:

orders和items之间可以通过orderdetail表建立 关系。

一对一查询

实例:查询订单信息,关联查询创建订单的用户信息。

SELECT orders.*,user.username,user.sex,user.address FROM orders,USER WHERE orders.user_id = user.id

主查询表:orders

关联查询表:user

联结查询:内联结

利用ResultType

1、SQL语句的书写要领:先确定查询的主表,在确定查询的关联表,关联查询是使用内联结还是外联结。

2、POVO扩展类创建。(这是由于关联查询出来的信息是多张表的综合字段,所以我们可以根据POJO创建我们的扩展类)

3、Mapper.xml和Mapper.java的代理编写

4、进行测试

相关代码:

//  POJO基础类
public class Orders {
private int id;
private int userid;
//  private int user_id;

private String number;
private Date createtime;
private String note;
}

// POVO扩展类   Orders的扩展类,通过此类可以映射订单和用户查询的结果。
public class OrdersExtends  extends Orders{
private String username;
private String sex;
private String address;
}

// Mapper.xml配置
<select id="findorderanduser" resultType="com.wf.model.OrdersExtends">
SELECT orders.*,user.username,user.sex,user.address FROM orders,USER WHERE     orders.user_id = user.id
</select>

//Mapper.java 代理接口
public interface OrdersExtendsMapper {
public List<OrdersExtends> findorderanduser();
}

//测试代码
@Test
public void testOrdersExtendsMapper() {

SqlSession session = sqlsessionfactory.openSession();
OrdersExtendsMapper orderextendsmapper = session.getMapper(OrdersExtendsMapper.class);
List<OrdersExtends> list = orderextendsmapper.findorderanduser();
for(OrdersExtends o :list){             System.out.println(o.getId()+":"+o.getUserid()+":"+o.getUsername()+":"+o.getAddress());

//System.out.println(o.getId()+":"+o.getUser_id()+":"+o.getUsername()+":"+o.getAddress());          //getUserid没有和数据库对应,所以无法获取默认为0
}
}


注意:上述测试代码中,由于userid没有和数据库中的字段进行对应(user_id),所以会造成数据映射不成功而默认为0

利用ResultMap

思路:利用 ResultMap 有点类似于Hibernate中POJO类中的设置。将我们对应的属性关联到类中。

1、使用resultMap将查询结果中的订单信息映射到Orders对象中,

2、在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。

// POJO基础类
public class Orders {
private User user;     //  在Orders类中配置我们的User属性

private int id;
private int userid;
private String number;
private Date createtime;
private String note;
}

// Mapper.xml

public interface OrdersExtendsMapper {
public List<Orders> findorderanduserResultMap();
}
// Mapper.java
<mapper namespace="com.wf.dao.OrdersExtendsMapper">

<!-- 订单查询关联用户的查询 -->
<resultMap type="com.wf.model.Orders" id="OrderUserResultMap">
<!-- 配置映射的订单信息 -->
<id column="id" property="id"/>
<result column="user_id" property="userid"/>       <!--    ???????? -->
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>

<!-- 配置关联的用户信息
association:用来映射关联查询单个对象的信息
property :将关联信息映射到Order的哪个属性中去
javaType 映射到那个java类中
-->
<association property="user" javaType="com.wf.model.User">
<!-- id  关联查询用户的唯一标识 ,外键
column 指定唯一标识用户信息的字段,property表示类中属性
-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>

</resultMap>

<select id="findorderanduserResultMap" resultMap="OrderUserResultMap">
SELECT orders.*,user.username,user.sex,user.address FROM orders,USER WHERE
orders.user_id = user.id
</select>

</mapper>


说明:

利用 ResultMap,我们可以利用其中的association 属性将外键关联的相关类进行映射。这也是使用ResultMap 的便利之一。

ResultType和ResultMap实现一对一查询比较

1、resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用resultType。

2、resultMap需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。

3、resultMap可以实现延迟加载,resultType无法实现延迟加载。

一对多查询

实例:查询订单及订单明细的信息。

SELECT orders.*,

user.username,user.sex,user.address ,

orderdetail.id,orderdetail_id,orderdetail.items_id,orderdetail.items_num,orderdetail.orders_id

FROM orders,USER,orderdetail

WHERE orders.user_id = user.id AND orderdetail.orders_id = orders.id

主查询表:orders

确定关联查询表:orderdetail

联结查询:内联结

利用resultType将上边的 查询结果映射到pojo中,订单信息的就是重复。而我们对于对orders映射不能出现重复记录。所以我们这里只能利用ResultMap。

利用ResultMap

// POJO类
public class User {
private int id;
private String username;
private Date birthday;
private String address;
private String sex;
}

public class Orders {

private User user;

private int id;
private int userid;
private String number;
private Date createtime;
private String note;

private List<OrdersDetail> orderdetails;  //  一对多关系设置

}

public class OrdersDetail {
private int id;
private int ordersId;
private int itemsId;
private int itemsNum;

}

//Mapper.java
public interface OrdersExtendsMapper {
// 查询订单(关联用户)订单明细
public List<Orders> findOrderAndDetailResultMap();
}

//Mapper.xml
<resultMap type="com.wf.model.Orders" id="findOrderAndDetailResultMap" >
<!-- 配置映射的订单信息 -->
<id column="id" property="id"/>
<result column="user_id" property="userid"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>

<!-- 配置关联的用户信息
association:用来映射关联查询单个对象的信息    一对多的逆向使用
property :将关联信息映射到Order的哪个属性中去
javaType 映射到那个java类中
-->
<association property="user" javaType="com.wf.model.User">
<!-- id  关联查询用户的唯一标识 ,外键
column 指定唯一标识用户信息的列
-->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>

<!-- 订单明细信息
一个订单包含多条明细,要使用collection进行映射         一对多使用 配置在一的一方添加属性
collection:对关联查询的多条记录映射到集合对象中去
property: 将关联查询出来的多条记录映射到类中的那个属性中 list
ofType : 指定映射到集合属性中的pojo类,list的泛型
-->
<collection property="orderdetails" ofType="com.wf.model.OrdersDetail">
<!-- id 订单明细唯一标识 -->
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>
</collection>

</resultMap>

// 测试代码

@Test
public void testfindOrderAndDetailResultMap() {

SqlSession session = sqlsessionfactory.openSession();
OrdersExtendsMapper orderextendsmapper = session.getMapper(OrdersExtendsMapper.class);
List<Orders> list = orderextendsmapper.findOrderAndDetailResultMap();
// 断点查看,打印查询4条,list存储2条,自动去重了
for(Orders o :list){
System.out.println(o.getId()+":"+o.getUser().getId()+":"+o.getUser().getUsername()+":"+o.getUser().getAddress());
}
}


注意:对于一对多或者多对一的查询,建议使用ResultMap映射进行代码编写,

mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。

使用resultType实现:

将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderdetails中。

多对多查询

实例:查询用户及用户购买商品信息。

查询主表是:user

关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表:

orders、orderdetail、items

联结查询:内联结

利用ResultMap

// POJO类
public class User {
private int id;
private String username;
private Date birthday;
private String address;
private String sex;
private List<Orders> orderslist;    //一对多
}

public class Orders {
private User user;      // 用户信息
private int id;
private int userid;
private String number;
private Date createtime;
private String note;
private List<OrdersDetail> orderdetails;    //商品信息存放集合
}

public class OrdersDetail {
private int id;
private int ordersId;
private int itemsId;
private int itemsNum;
private Items items;    //商品信息
}

public class Items {
private int id;
private String name;
private double price;
private String detail;
private String pic;
private Date createtime;
}

// Mapper.java
public interface OrdersExtendsMapper {
public List<User>  findUserAndItemResultMap();
}

//Mapper.xml

<!-- 用户及用户购买的商品明细 -->
<resultMap type="com.wf.model.User" id="UserAndItemResultMap">
<!-- 映射用户信息 -->
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>

<!-- 订单信息
一个用户创建多个订单    使用collection
-->
<collection property="orderslist" ofType="com.wf.model.Orders">
<id column="id" property="id"/>
<result column="user_id" property="userid"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>

<!--  订单明细
一个订单包含多个订单明细  所以写在订单信息里面
-->

<collection property="orderdetails" ofType="com.wf.model.OrdersDetail">
<!-- id 订单明细唯一标识 -->
<id column="orderdetail_id" property="id"/>
<result column="items_id" property="itemsId"/>
<result column="items_num" property="itemsNum"/>
<result column="orders_id" property="ordersId"/>

<!-- 商品信息
一个订单明细对应一个商品
-->
<association property="items" javaType="com.wf.model.Items">
<id column="items_id" property="id"/>
<result column="items_name" property="name"/>
<result column="item_price" property="price"/>
<result column="item_datail" property="detail"/>
</association>
</collection>
</collection>
</resultMap>

//测试代码
@Test
public void testfindUserAndItemResultMap() {
SqlSession session = sqlsessionfactory.openSession();
OrdersExtendsMapper orderextendsmapper = session.getMapper(OrdersExtendsMapper.class);
List<User> list = orderextendsmapper.findUserAndItemResultMap();
for(User o :list){
System.out.println(o.getId()+":"+o.getUsername()+":"+o.getAddress()
+":"+o.getOrderslist().get(0).getOrderdetails().get(0).getItems().getName());
}
}


注意:我们在利用多对多的情况下,一定要主要ResultMap的嵌套关系。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mybatis