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 Transfer

Source Server         : xxx
Source Server Version : 50540
Source Host           : localhost:3306
Source Database       : mybatis

Target Server Type    : MYSQL
Target Server Version : 50540
File Encoding         : 65001

Date: 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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

时间: 2024-10-01 04:10:52

Mybatis入门---一对多、多对多的相关文章

mybatis 一对一 一对多 多对多

一对一 一对多 多对多 原文地址:https://www.cnblogs.com/cwone/p/11909271.html

MyBatis入门(二)---一对一,一对多

一.创建数据库表 1.1.创建数据表同时插入数据 /* SQLyog Enterprise v12.09 (64 bit) MySQL - 5.6.27-log : Database - mybatis ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @[emai

mybatis的一对多,多对一,以及多对对的配置和使用

1.本文章是无意中看见易百教程的Mybatis教程才注意到这个问题,平时都仅仅是在用CRUD,忽略了这方面的问题,真实十分羞愧 2.首先我们开始对mybatis的一对多的探究 根据这个应用场景,我们需要获取在查询一个用户信息的时候还要去读取这个用户发布的帖子 现在我们来看一看用户级联文章在JavaBean中的编写方式,这就是一对多在JavaBean中的配置 现在我们再来看一看Mybatis的Mapper该如何编写一对多?很简单,就是在resultMap标签中配置<collection>标签,用

mybatis入门(一):jdbc的缺点

mybatis的基础内容 1.mybatis的框架原理 2.mybatis开发dao两种方法: a.原始dao开发方法(程序需要编写dao接口和dao实现类) b.mybatis的mapper接口(相当于dao接口)代理开发方法 3.mybatis配置文件:SqlMapConfig.xml 4.mybatis核心: mybatis输入映射 mybatis输出映射 5.mybatis的动态sql mybatis的高级知识 1.高级结果集映射(一对一,一对多,多对多) 2.mybatis延迟加载 3

mybatis学习笔记(11)-多对多查询

mybatis学习笔记(11)-多对多查询 mybatis学习笔记11-多对多查询 示例 多对多查询总结 resultMap总结 本文实现多对多查询,查询用户及用户购买商品信息. 示例 查询主表是:用户表 关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表:orders.orderdetail.items sql SELECT orders.*, user.username, user.sex, user.address, orderdetail.id orderdeta

MyBatis入门(五)---延时加载、缓存

一.创建数据库 1.1.建立数据库 /* SQLyog Enterprise v12.09 (64 bit) MySQL - 5.7.9-log : Database - mybatis ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @[email protec

Java Persistence with MyBatis 3(中文版) 第一章 MyBatis入门

本章将涵盖以下话题: ž  MyBatis是什么? ž  为什么选择MyBatis? ž  MyBatis安装配置 ž  域模型样例 1.1 MyBatis是什么 MyBatis是一个简化和实现了Java数据持久化层(persistencelayer)的开源框架,它抽象了大量的JDBC冗余代码,并提供了一个简单易用的API和数据库交互. MyBatis的前身是iBATIS,iBATIS于2002年由ClintonBegin创建.MyBatis 3 是iBATIS的全新设计,支持注解和Mapper

hibernate 一对多|多对一

一对多:(一个客户对应多个联系人) 客户实体:Customer.java package cn.future.domain; import java.util.HashSet; import java.util.Set; public class Customer { /* * CREATE TABLE `cst_customer` ( `cust_id` BIGINT(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)', `cust_name` VAR

MyBatis1:MyBatis入门

MyBatis是什么 MyBatis是什么,MyBatis的jar包中有它的官方文档,文档是这么描述MyBatis的: MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of para