多对多关联关系

说明:从一对一到一对多再到多对多,都是在一个工程里面添加的,涉及到的包也不多,故贴出打码后的工程结构,只保留了跟多对多相关的类。


废话不多说,下面开始贴代码。。


1.SQL脚本

#创建用户表
CREATE TABLE tb_user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(18),
loginname VARCHAR(18),
PASSWORD VARCHAR(18),
phone VARCHAR(18),
address VARCHAR(18)
);
#插入用户测试数据
INSERT INTO tb_user (username,loginname,PASSWORD,phone,address)
VALUES('杰克','jack','123456','15656322223','广州');
#创建商品表
CREATE TABLE tb_article (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(18),
price DOUBLE,
remark VARCHAR(18)
);
#插入商品表测试数据
INSERT INTO tb_article(NAME,price,remark)
VALUES('疯狂Java讲义',108.9,'李刚老师经典著作'),
('疯狂Android讲义',199.9,'李刚老师经典著作'),
('疯狂IOS讲义',89.9,'李刚老师经典著作');
INSERT INTO tb_article(NAME,price,remark)
VALUES('Spring+Mybatis',108.9,'李刚老师经典著作');
#创建订单表
CREATE TABLE tb_order (
id INT PRIMARY KEY AUTO_INCREMENT,
CODE VARCHAR(32),
total DOUBLE,
user_id INT,
FOREIGN KEY (user_id) REFERENCES tb_user(id)
);
#插入订单测试数据
INSERT INTO tb_order(CODE,total,user_id)
VALUES('aaaaa11111',388.6,1), 
('bbbbb22222',217.8,1);
#创建中间表
CREATE TABLE tb_item (
order_id INT ,
article_id INT,
PRIMARY KEY(order_id,article_id),
FOREIGN KEY (order_id) REFERENCES tb_order(id),
FOREIGN KEY (article_id) REFERENCES tb_article(id)
 );
#创建插入中间表数据
INSERT INTO tb_item(order_id,article_id)
VALUES(1,1),
(1,2),
(1,3),
(2,4),

(2,1);


2.实体类和对应的映射文件(注意,在测试过程中,映射文件对应的Mapper接口还是要写的,此处就省略了)

用户类User.java

public class User implements Serializable{
private static final long serialVersionUID = 1L;

private int id;
private String loginname;
private String username;
private String password;
private String phone;
private String address;

//用户和订单是一对多关系,即一个用户可以由多个订单

private List<Order> orders;

        /**省略set和get方法*/

}

UserMapper.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="org.fkit.mapper.UserMapper">
<select id="selectUserById" parameterType="int" resultMap="UserResultMap">
select * from tb_user
where id = #{id}
</select>

<resultMap type="org.fkit.domain.User" id="UserResultMap">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="loginname" column="loginname"/>
<result property="password" column="password"/>
<result property="phone" column="phone"/>
<result property="address" column="address"/>
<!-- 一对多关联映射:collection -->
<collection property="orders" javaType="ArrayList" ofType="org.fkit.domain.Order"
column="id" select="org.fkit.mapper.OrderMapper.selectOrderByUserId" fetchType="lazy">
<id property="id" column="id"/>
<result property="code" column="code"/>
<result property="total" column="total"/>
</collection>
</resultMap>

</mapper>


订单类Order.java

public class Order implements Serializable{
private static final long serialVersionUID = 1L;

private int id;
private String code;
private double total;

//订单和用户是多对一的关系,即一个订单只属于一个用户
private User user;
//订单和商品是多对多的关系,即一个订单可以包含多种商品

private List<Article> articles;

        /**省略set和get方法*/

}

OrderMapper.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="org.fkit.mapper.OrderMapper">
<!-- 注意查询出来的列同名,例如tb_user表的id和tb_order表的id都是id,
同名,需要使用别名区分 -->
<select id="selectOrderById" parameterType="int" resultMap="orderResultMap">
select u.*,o.id as oid,code,total,user_id
from tb_user u ,tb_order o
where u.id = o.user_id  AND o.id = #{id}
</select>

<select id="selectOrderByUserId" parameterType="int" resultMap="orderResultMap">
select * from tb_order 
where user_id = #{id}
</select>

<resultMap type="org.fkit.domain.Order" id="orderResultMap">
<id property="id" column="id"/>
<result property="code" column="code"/>
<result property="total" column="total"/>
<!-- 
多对一关联映射:association 
下面这个映射关系只是简单的填充数据,没有再次执行查询
(两种情况:
1.查询User信息:在查询User信息的时候关联查询了Order信息,此时映射的信息中已经包含User信息,所以不需要再执行查询,只需要填充数据即可
2.查询Order信息:在查询Order信息的时候本省执行的就是多表查询,所以User的数据也已经获取到,所以只需要填充数据即可。

-->
<association property="user" javaType="org.fkit.domain.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="loginname" column="loginname"/>
<result property="password" column="password"/>
<result property="phone" column="phone"/>
<result property="address" column="address"/>
</association>
<!-- 多对多关联映射:collection -->
<collection property="articles" javaType="ArrayList" column="oid"
ofType="org.fkit.domain.Article" fetchType="lazy"
select="org.fkit.mapper.ArticleMapper.selectArticleByOrderId">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="price" column="price"/>
<result property="remark" column="remark"/>
</collection>
</resultMap>

</mapper>


商品类Article.java

public class Article implements Serializable{
private static final long serialVersionUID = 1L;

private int id;
private String name;
private double price;
private String remark;

//商品和订单是多对多的关系,即一种商品可以出现在多个订单中

private List<Order> orders;

        /**省略set和get方法*/

}

ArticleMapper.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="org.fkit.mapper.ArticleMapper">
<!-- 注意:该查询的子查询是从中间表中查询数据 -->
<select id="selectArticleByOrderId" parameterType="int" resultType="org.fkit.domain.Article">
select * from tb_article 
where id in(select article_id from tb_item where order_id = #{id})
</select>

</mapper>


3.测试类:

public class ManyToManyTest {

public static void main(String[] args) throws Exception {
// 读取mybatis-config.xml文件
InputStream inputStream = Resources.getResourceAsStream("mybatis/mybatis-config.xml");
// 初始化mybatis,创建SqlSessionFactory类的实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 创建Session实例
SqlSession session = sqlSessionFactory.openSession();

ManyToManyTest t = new ManyToManyTest();

// 根据用户id查询用户,测试一对多
// t.testSelectUserById(session);
// 根据订单id查询订单,测试多对多
t.testSelectOrderById(session);

// 提交事务
session.commit();
// 关闭Session
session.close();
}

// 测试一对多,查询班级User(一)的时候级联查询订单Order(多)  
public void testSelectUserById(SqlSession session){
// 获得UserMapper接口的代理对象
UserMapper um = session.getMapper(UserMapper.class);
// 调用selectUserById方法
User user = um.selectUserById(1);
// 查看查询到的user对象信息
System.out.println(user);
// 查看user对象关联的订单信息
List<Order> orders = user.getOrders();
for(Order order : orders){
System.out.println(order);
}
}

// 测试多对多,查询订单Order(多)的时候级联查询订单的商品Article(多)  
public void testSelectOrderById(SqlSession session){
// 获得OrderMapper接口的代理对象
OrderMapper om = session.getMapper(OrderMapper.class);
// 调用selectOrderById方法
Order order = om.selectOrderById(1);
// 查看查询到的order对象信息
System.out.println(order);
// 查看order对象关联的用户信息
User user = order.getUser();
System.out.println(user);
// 查看order对象关联的商品信息
List<Article> articles = order.getArticles();
for(Article article : articles){
System.out.println(article);
}

}

}

测试结果:

a.


b.




总结:以前就学过Hibernate的关联映射,但那是刚接触框架的时候学的,可以说真的真的只是过了一遍,几乎忘了什么是什么了。然后最近在看黑马程序员官网的一个‘SSH搭的OA系统’,虽然我现在转成学SSM,但是一个系统的开发过程上还是大体一致的,所以看了两天的视频下来感受还是颇多的。受了这个影响,我刚好捡起手头一本SSM开发的书,花了两天时间学习了关联关系,虽然看这个例子赶紧好像有点懂了,但我相信自己还是不太懂的,毕竟要实际运用之后才会加深认知。但是这两天也不算完全没有收获,总之呢,书不要只看一遍,多看几遍,总会有不一样的感触的!以前学这个的时候就是书上说什么就是什么,照着代码敲出来就好了,今天早上在做多对多的时候,联想到很多东西,会去想为什么不那样做,或者说那样做会怎么样之类的。废话说多了,,总之呢,不要急。一步一个脚印的慢慢来吧,要学的东西还有很多呢……

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值