Mybatis入门---一对多、多对多

前几天自己配置了Mybatis的高级查询:一对多和多对多,现在记录一下,方便以后用到的时候再回顾,下面是具体的操作步骤

一、首先就是配置Mybatis的xml文件及mapper的xml文件,在这里就不多说了,之前写过这个基本的配置,可以参考:https://www.cnblogs.com/blogs-of-xiu/p/10405407.html

经过配置完基本的xml文件之后,我们就开始实现一对多和多对多的需求。

我这里举的例子是用户和订单,一个用户可以对应多个订单,所以需要的表也是用户表和订单表。数据结构如下:之前的文章中是一对一查询,只用到了user表,现在多了三个表分别是orders【订单表】、order_detail【订单详情】、product【商品表】。

用户与订单的关系为一对多,订单与订单明细的关系是一对多,订单明细与商品表的关系是一对一,用户与商品的关系是多对多。

在这里我们使用的关系是用户与订单【一对多】和用户与商品的关系【多对多】,下面会说明多对多的关系如何配置。

整个数据库的sql结构如下【从逻辑上面推敲,可能有些字段设置的不合适】:

/*
Navicat MySQL Data TransferSource Server         : xxx
Source Server Version : 50540
Source Host           : localhost:3306
Source Database       : mybatisTarget Server Type    : MYSQL
Target Server Version : 50540
File Encoding         : 65001Date: 2019-03-14 11:07:30
*/SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for orders
-- ----------------------------
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) DEFAULT NULL,`order_number` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `user_id` (`user_id`),CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for order_detail
-- ----------------------------
DROP TABLE IF EXISTS `order_detail`;
CREATE TABLE `order_detail` (`id` int(11) NOT NULL AUTO_INCREMENT,`order_id` int(11) NOT NULL,`product_id` int(255) DEFAULT NULL,PRIMARY KEY (`id`),KEY `order_id` (`order_id`),KEY `product_id` (`product_id`),CONSTRAINT `order_id` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,CONSTRAINT `product_id` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for product
-- ----------------------------
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (`id` int(11) NOT NULL AUTO_INCREMENT,`product_name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(255) DEFAULT NULL,`password` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

二、经过数据库的设计之后,我们开始进行实现代码,下面是主要的类:

1、实体类中除了product类不需要加入其它类的对象之外,另外几个类中都需要加入其它实体类的对象。

【原因:例如用户 UserBean 中,属性需要加上订单 Orders 的对象,因为订单对于用户来说是多的一方】

具体的代码如下:

UserBean:

package bean;import java.util.List;public class UserBean {private int id;private String username;private String password;private List<Orders> ordersList;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public List<Orders> getOrdersList() {return ordersList;}public void setOrdersList(List<Orders> ordersList) {this.ordersList = ordersList;}@Overridepublic String toString() {return "UserBean [id=" + id + ", username=" + username + ", password=" + password + ", ordersList=" + ordersList+ "]";}public UserBean(String username, String password) {super();this.username = username;this.password = password;}public UserBean(int id, String username, String password, List<Orders> ordersList) {super();this.id = id;this.username = username;this.password = password;this.ordersList = ordersList;}public UserBean() {super();}}

订单类  Orders:

package bean;import java.util.List;public class Orders {private int id;private int user_id;private String number;private List<Order_Detail> order_detail;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getUser_id() {return user_id;}public void setUser_id(int user_id) {this.user_id = user_id;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public List<Order_Detail> getOrder_detail() {return order_detail;}public void setOrder_detail(List<Order_Detail> order_detail) {this.order_detail = order_detail;}@Overridepublic String toString() {return "Orders [id=" + id + ", user_id=" + user_id + ", number=" + number + ", order_detail=" + order_detail+ "]";}public Orders(int id, int user_id, String number, List<Order_Detail> order_detail) {super();this.id = id;this.user_id = user_id;this.number = number;this.order_detail = order_detail;}public Orders() {super();}}

订单明细 Order_Detail:

package bean;public class Order_Detail {private int id;private int order_id;private int product_id;private Product product;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getOrder_id() {return order_id;}public void setOrder_id(int order_id) {this.order_id = order_id;}public int getProduct_id() {return product_id;}public void setProduct_id(int product_id) {this.product_id = product_id;}public Product getProduct() {return product;}public void setProduct(Product product) {this.product = product;}@Overridepublic String toString() {return "Order_Detail [id=" + id + ", order_id=" + order_id + ", product_id=" + product_id + ", product="+ product + "]";}public Order_Detail(int id, int order_id, int product_id, Product product) {super();this.id = id;this.order_id = order_id;this.product_id = product_id;this.product = product;}public Order_Detail() {super();}
}

商品类  Product:

package bean;public class Product {private int id;private String product_name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getProduct_name() {return product_name;}public void setProduct_name(String product_name) {this.product_name = product_name;}@Overridepublic String toString() {return "Product [id=" + id + ", product_name=" + product_name + "]";}public Product(int id, String product_name) {super();this.id = id;this.product_name = product_name;}public Product() {super();}}

2、mapper 接口和mapper.xml文件:

UserMapper 接口:

package mapper;import java.util.List;import bean.Orders;
import bean.UserBean;public interface UserMapper {/*** description select all users*/public List<UserBean> selectAllUser();/*** description insert*/public int insertUser(UserBean userbean);/*** description delete user by id* */public int deleteUserById(int id);/*** description update user* */public int updateUser(UserBean userbean);/*** description select user by id* */public UserBean selectUserById(int id);// 一对多 查询一个用户对应的多个订单public List<Orders> selectOrdersOfUser();// 多对多 查询一个用户对应的多个商品public List<Orders> selectProductOfUser();}

xml文件 UserMapper.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserMapper"><resultMap id="usermap" type="UserBean"><id property="id" column="id" javaType="java.lang.Integer" /><result property="username" column="username" javaType="java.lang.String" /><result property="password" column="password" javaType="java.lang.String" /></resultMap><!-- 一对多 查询用户的订单 --><resultMap id="ordersmap" type="UserBean"><!--这个id的column是你要映射到SQL语句中的,这个property是你从真实的beans实体类的属性中的id --><id column="id" property="id" /><result column="username" property="username" /><result column="password" property="password" /><!--因为这个地方的是一对多,要关联到的是一个集合所以使用collection --><collection property="ordersList" ofType="Orders"><id column="id" property="id" /><result column="order_number" property="number" /></collection></resultMap><resultMap id="selectProductOfUserMap" type="UserBean"><id column="id" property="id" /><result column="username" property="username" /><result column="password" property="password" /><!-- 通过用户查询订单  ordersList  字段来自UserBean实体类中声明的Order对象名,以下的情况都是--> 
    <collection property="ordersList" ofType="Orders">
    <id column="id" property="id" /> 
<result column="order_number" property="number" />
<!-- 通过订单查询订单明细 --> <collection property="order_detail" ofType="Order_Detail">
<id column="id" property="id" />
<result column="order_id" property="order_id" />
<result column="product_id" property="product_id" />
<!-- 通过订单明细查询商品 --> <association property="product" javaType="Product">
<id column="id" property="id" /> <result column="product_name" property="product_name" />
</association> </collection> </collection> </resultMap>
<select id="selectAllUser" resultMap="usermap">
select
* from user </select> <insert id="insertUser">
insert into user(username,password)values(#{username},#{password})
</insert>
<delete id="deleteUserById"> delete from user where id=#{id} </delete>
<update id="updateUser"> update user set username=#{username},password=#{password} where id=#{id} </update>
<select id="selectUserById" resultMap="usermap"> select * from user where id=#{id} </select>
<!-- 一对多 查询用户的订单 -->
<select id="selectOrdersOfUser" resultMap="ordersmap"> select t1.*, t2.order_number from user t1, orders t2 where t1.id=t2.user_id </select>
<select id="selectProductOfUser" resultMap="selectProductOfUserMap">

select t1.id as user_id,t1.username, t2.id as order_id,t2.order_number, t3.id as order_detail_id,t3.product_id, t4.id as product_id,t4.product_name
from user t1, orders t2, order_detail t3, product t4 where t1.id
=t2.user_id and t3.order_id=t2.id and t3.product_id=t4.id </select> </mapper>

3、逻辑层和测试 我写在了service类,但是这样不太符合规范

UserService类:

package service;import java.util.List;import org.apache.ibatis.session.SqlSession;import bean.UserBean;
import mapper.UserMapper;
import tools.DB;public class UserService {public static void main(String[] args) {// selectAllUser();// insertUser();// deleteUserById();// updateUser();// 一对多 查询用户的订单// selectOrdersOfUser();// 多对多 查询用户对应的商品
        selectProductOfUser();}private static void selectAllUser() {SqlSession session = DB.getSession();UserMapper mapper = session.getMapper(UserMapper.class);try {List<UserBean> user = mapper.selectAllUser();System.out.println(user.toString());session.commit();} catch (Exception e) {e.printStackTrace();session.rollback();}}private void insertUser() {SqlSession session = DB.getSession();UserMapper mapper = session.getMapper(UserMapper.class);try {UserBean userbean = new UserBean("zs", "123");mapper.insertUser(userbean);System.out.println(userbean.toString());session.commit();} catch (Exception e) {e.printStackTrace();session.rollback();}}private static void deleteUserById() {SqlSession session = DB.getSession();UserMapper mapper = session.getMapper(UserMapper.class);try {mapper.deleteUserById(3);System.out.println("删除成功");session.commit();} catch (Exception e) {e.printStackTrace();session.rollback();}}private static void updateUser() {SqlSession session = DB.getSession();UserMapper mapper = session.getMapper(UserMapper.class);UserBean userbean = mapper.selectUserById(4);System.out.println("修改之前的userbean:" + userbean);try {userbean.setUsername("hhh");userbean.setPassword("111");mapper.updateUser(userbean);System.out.println("修改之后的userbean:" + userbean);session.commit();} catch (Exception e) {e.printStackTrace();session.rollback();}}// 一对多 查询用户订单private static void selectOrdersOfUser() {SqlSession session = DB.getSession();UserMapper mapper = session.getMapper(UserMapper.class);System.out.println(mapper.selectOrdersOfUser().toString());}// 多对多 查询用户对应的商品private static void selectProductOfUser() {SqlSession session = DB.getSession();UserMapper mapper = session.getMapper(UserMapper.class);System.out.println(mapper.selectProductOfUser().toString());}
}

4、mybatis.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><typeAliases><typeAlias type="bean.UserBean" alias="UserBean"/><typeAlias type="bean.Orders" alias="Orders"/><typeAlias type="bean.Order_Detail" alias="Order_Detail"/><typeAlias type="bean.Product" alias="Product"/></typeAliases><environments default="cybatis"><environment id="cybatis"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><package name="mapper"/></mappers>
</configuration>

5、一对多的关键点是collection标签的配置,多对多中的关键点事collection和association标签的配置。collection里面property的值是来自一对多中多的那方的对象。

多对多的关系中,我们需要将多对多关系拆分成一对多来实现。

【例如多个用户对应多个商品,可以拆分成 :

一个用户对应多个订单(一对多)+ 一个订单对应多个订单明细(一对多) + 一个订单明细对应一个商品(一对一),最终实现用户->商品的联系。】

6、以上就是主要的代码实现,但是这样正常运行的话,在控制台出现的结果和我们将sql语句粘贴到数据库中运行得到的结果不一致。不一致的现象就是在数据库中正常得到我们需要的数据,但是在控制台中得出的却是相同用户id多个订单的情况,只能查到一条数据,原因是mybatis查到主键为id的数据,只会查到第一条。解决办法就是将表中的主键为id的修改一下,不让主键名为id,这样查到的结果就是我们得到的全部数据了。

 

转载于:https://www.cnblogs.com/blogs-of-xiu/p/10528791.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/425405.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Leedcode][第215题][JAVA][数组中的第K个最大元素][快排][优先队列]

【问题描述】[中等] 在未排序的数组中找到第 k 个最大的元素。请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。示例 1:输入: [3,2,1,5,6,4] 和 k 2 输出: 5 示例 2:输入: [3,2,3,1,2,4,5,5,6] 和 k 4 输出: 4 说明:你可…

CF#420 B. Okabe and Banana Trees 思维|暴力|几何

Okabe needs bananas for one of his experiments for some strange reason. So he decides to go to the forest and cut banana trees. Consider the point (x, y) in the 2D plane such thatx andy are integers and0 ≤ x, y. There is a tree in such a point, and i…

30jquery-qrcode生成二维码

链接&#xff1a;https://pan.baidu.com/s/1KHzX_jFFBaw4QBKBR8UrgA 提取码&#xff1a;qmdo 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 如上所示&#xff0c;建立一个web程序 <% page language"java" contentType"text/html; charsetUTF-…

[剑指offer]面试题第[50]题[JAVA][第一个只出现一次的字符][哈希表][HashMap]

【问题描述】[简单] 在字符串 s 中找出第一个只出现一次的字符。如果没有&#xff0c;返回一个单空格。 s 只包含小写字母。示例:s "abaccdeff" 返回 "b"s "" 返回 " "【解答思路】 1. 哈希表 时间复杂度&#xff1a;O(N) 空间复…

31.javaweb简介

1 2 3 4 5 6 7javaweb程序简介

[剑指offer]面试题第[38]题[JAVA][字符串的排列][回溯法]

【问题描述】[中等] 输入一个字符串&#xff0c;打印出该字符串中字符的所有排列。 你可以以任意顺序返回这个字符串数组&#xff0c;但里面不能有重复元素。示例: 输入&#xff1a;s "abc" 输出&#xff1a;["abc","acb","bac",&qu…

32tomcat的目录结构

<% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>歌谣</title> </head> <bod…

[剑指offer]面试题第[52]题[Leedcode][第160题][JAVA][相交链表][双指针]

【问题描述】[简单] 【解答思路】 1. 双指针法 时间复杂度&#xff1a;O(N^2) 空间复杂度&#xff1a;O(1) public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA null || headB null) return null;ListNode pA headA, pB headB;while (pA !…

33tomcat目录结构

1创建一个myhome文件 2创建一个index.jsp文件 <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%><!DOCTYPE html><html><head><meta charset"utf-8"><title>歌…

复合数据类型,英文词频统计

作业要求&#xff1a;https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2696 1.列表&#xff0c;元组&#xff0c;字典&#xff0c;集合分别如何增删改查及遍历。 列表的增删改查list1 list(this is a list)#增加list1.append(!) #末尾增加元素list1.insert(2,this i…

34tomcat设置默认页面

如何让hah.jsp成为欢迎界面&#xff1f; 在web-inf文件夹中配置项目部署文件web.xml。 添加标签 <welcome-file-list> <welcome-file>/hah.jsp</welcome-file> <welcome-file-list> 改变web.xml文件首页&#xff0c;报 将文件变成hah.jsp 默认页就设置…

[Leetcode][第718题][JAVA][最长重复子数组][动态规划][滑动窗口][暴力]

【问题描述】[中等] 给两个整数数组 A 和 B &#xff0c;返回两个数组中公共的、长度最长的子数组的长度。示例 1:输入: A: [1,2,3,2,1] B: [3,2,1,4,7] 输出: 3 解释: 长度最长的公共子数组是 [3, 2, 1]。 说明:1 < len(A), len(B) < 1000 0 < A[i], B[i] < 100…

[剑指offer]面试题第[53-1]题[JAVA][在排序数组中查找数字-1][二分法][暴力法]

【问题描述】[中等] 统计一个数字在排序数组中出现的次数。 示例 1:输入: nums [5,7,7,8,8,10], target 8 输出: 2 示例 2:输入: nums [5,7,7,8,8,10], target 6 输出: 0【解答思路】 1. 暴力法/遍历 时间复杂度&#xff1a;O(N) 空间复杂度&#xff1a;O(1) public int…

[剑指offer]面试题第[53-2]题[JAVA][0-n-1中缺失的数字][二分法][暴力法]

【问题描述】[简单] 一个长度为n-1的递增排序数组中的所有数字都是唯一的&#xff0c;并且每个数字都在范围0&#xff5e;n-1之内。在范围0&#xff5e;n-1内的n个数字中有且只有一个数字不在该数组中&#xff0c;请找出这个数字。示例 1:输入: [0,1,3] 输出: 2 示例 2:输入: …

过拟合问题详解

具体内容来自于读芯术&#xff1a;https://mp.weixin.qq.com/s?__bizMzI2NjkyNDQ3Mw&mid2247487002&idx1&sn05d13bd67a31e38434285c5f0262b95d&chksmea87f6ccddf07fdae17a71819ba0577d099bb49b291093e7c6c7927456febfb3d8d308c30ad6&scene21#wechat_redir…

[Leetcode][第378题][JAVA][有序矩阵中第K小的元素][二分法][归并排序][暴力]

【问题描述】[中等] 给定一个 n x n 矩阵&#xff0c;其中每行和每列元素均按升序排序&#xff0c;找到矩阵中第 k 小的元素。 请注意&#xff0c;它是排序后的第 k 小元素&#xff0c;而不是第 k 个不同的元素。示例&#xff1a; matrix [[ 1, 5, 9],[10, 11, 13],[12, 13…

设计模式-Builder和Factory模式区别

Builder和Factory模式区别 Builder模式结构&#xff1a; Factory模式一进一出,Builder模式是分步流水线作业。当你需要做一系列有序的工作或者按照一定的逻辑来完成创建一个对象时 Builder就派上用场啦。我们可以看到&#xff0c;Builer模式与工厂模式是极为相似的&#xff0c;…

[剑指offer]面试题第[54]题[JAVA][二叉搜索树的第k大节点][递归][迭代]

【问题描述】[简单] 给定一棵二叉搜索树&#xff0c;请找出其中第k大的节点。示例 1: 输入: root [3,1,4,null,2], k 13/ \1 4\2 输出: 4 示例 2:输入: root [5,3,6,2,4,null,null,1], k 35/ \3 6/ \2 4/1 输出: 4【解答思路】 反向中序遍历 遍历到第k个节点时&…