MyBatis多对多级联查询

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis多对多级联查询相关的知识,希望对你有一定的参考价值。

MyBatis多对多级联查询

级联关系是数据库实体的概念,有3种级联关系,分别为1对1级联,1对多级联,多对多级联。
级联的优点:关联数据十分方便。
缺点:级联过多会增加数据库系统的复杂度,同时降低系统性能。
如果表A引用了表B的主键,A表就是主表,B表就是父表,当查询表A数据时,通过A的外键将B的相关记录返回,这就是级联查询。例如,当查询一个人的个人信息,可以通过身份证号返回他的身份信息。
其实,MyBatis并没有实现多对多级联查询,这是因为多对多级联可以通过两个一对多级联查询进行替换。例如:一个订单可以有多个商品,一个商品可以属于多个订单,使用一张中间表(订单记录表)就可以将多对多级联关系转换为两个一对多级联关系。
下面通过订单和商品之间多对多级联关系,查询订单以及每个订单对应的商品信息。
1-在mysql中创建名为spring的数据库,在该数据库中创建订单表orders,商品表product,订单记录表orders_detail
订单表orders:


商品表product:


订单记录表orders_detail:


2-在IDEA中创建web应用Mappers,在web目录下的WEB-INF文件夹下导入相关jar包,并将jar包添加为库项目。

3-在src目录下创建com.po包,在该包中创建数据表product的持久化类Product,订单表orders的持久化类Orders,中间表订单记录表不需要持久化类。
Orders类:

import java.util.List;

/**
 * spring数据库中orders表的持久化类
 * 一个用户可以有多个订单,订单只属于一个用户,
 * 根据uid查询用户即其关联的订单信息
 */
public class Orders {
    private Integer id ;
    private String ordersn ;
    //多对多中的另一个一对多
    private List<Product> products ;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getOrdersn() {
        return ordersn;
    }

    public void setOrdersn(String ordersn) {
        this.ordersn = ordersn;
    }

    public List<Product> getProducts() {
        return products;
    }

    public void setProducts(List<Product> products) {
        this.products = products;
    }

    @Override
    public String toString(){
        return "Orders [id = " + id + " ordersn = " + ordersn + " products = " + products + "]" ;
    }
}

Product类:

import java.util.List;

/**
 * 产品product的持久化类
 */
public class Product {
    private Integer id ;
    private String name ;
    private Double price ;
    //多对多中的一个一对多
    private List<Orders> orders ;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public List<Orders> getOrders() {
        return orders;
    }

    public void setOrders(List<Orders> orders) {
        this.orders = orders;
    }
    public String toString(){
        return "Products [id = " + id + " name = " + name + " price = " + price + "]" ;
    }

}

4-在src目录下创建com.mybatis包,在该包中创建订单表的映射文件OrdersMapper.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 = "com.dao.OrdersDao">
    <!--多对多级联查询,查询所有订单以及所有订单对应的产品信息-->
    <resultMap type = "com.po.Orders" id ="allOrdersAndProducts">
        <id property = "id" column = "id"/>
        <result property = "ordersn" column = "ordersn"/>
        <!--多对多级联查询-->
        <collection property = "products" ofType = "com.po.Product">
            <id property = "id" column = "pid"/>
            <result property = "name" column = "name"/>
            <result property = "price" column = "price"/>
        </collection>
    </resultMap>
    <select id = "selectAllOrdersAndProducts" resultMap = "allOrdersAndProducts">
        select o.*, p.id as pid, p.name, p.price
        from orders o,  orders_detail od, product p
        where od.orders_id = o.id and od.product_id = p.id
    </select>
</mapper>

5-在com.mybatis下创建MyBatis核心配置文件mybatis-config.xml,需要在该配置文件中指明SQL映射文件的位置。

<?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>
    <!--在使用MyBatis嵌套查询方式进行关联查询时,使用MyBatis延时加载可以在一定程度上提高查询效率-->
    <settings>
        <!--打开延时加载开关-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--将积极加载改成按需加载-->
        <setting name = "aggressiveLazyLoading" value = "false"/>
    </settings>
    <!--告诉MyBatis映射文件的位置-->
    <mappers>
        <mapper resource = "com/mybatis/UserMapper.xml"/>
        <mapper resource = "com/mybatis/IdCardMapper.xml"/>
        <mapper resource = "com/mybatis/PersonMapper.xml"/>
        <mapper resource = "com/mybatis/OrdersMapper.xml"/>
        <mapper resource=  "com/mybatis/ProductMapper.xml"/>
    </mappers>
</configuration>

6-在src目录下创建spring配置文件applicationContetx.xml,在该文件扫描有注解的包,使得注解生效,同时需要配置数据源等。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--指定需要扫描的包,是注解生效-->
    <context:component-scan base-package="com.dao"/>
    <context:component-scan base-package="com.controller"/>
    <!--配置数据源-->
    <bean id = "dataSource" class = "org.apache.commons.dbcp2.BasicDataSource">
        <!--配置数据库驱动-->
        <property name = "driverClassName" value = "com.mysql.jdbc.Driver"/>
        <!--配置连接数据库的url-->
        <property name = "url" value = "jdbc:mysql://localhost:3306/spring?characterEncoding=utf8"/>
        <!--连接数据库的用户名-->
        <property name = "username" value = "root"/>
        <!--连接数据库的密码-->
        <property name = "password" value = "123456"/>
        <!--最大连接数-->
        <property name = "maxTotal" value = "30"/>
        <!--最大空闲连接数-->
        <property name = "maxIdle" value = "10"/>
        <!--初始化最大连接数-->
        <property name = "initialSize" value = "5"/>
    </bean>
    <!--添加事务支持-->
    <bean id = "txManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name = "dataSource" ref = "dataSource"/>
    </bean>
    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="txManager"/>
    <!--配置MyBatis工厂,同时指定数据源,并与MyBatis完美整合-->
    <bean id = "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean">
        <property name = "dataSource" ref = "dataSource"/>
        <!--configLocation的属性值为MyBatis的核心配置文件-->
        <property name = "configLocation" value = "classpath:com/mybatis/mybatis-config.xml"/>
    </bean>
    <!--Mapper代理开发,使用Spring自动扫描MyBatis接口并装配,Spring将指定包中的所有被@Mapper注解过的接口自动装配为MyBatis的映射接口-->
    <bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--mybatis-spring的组件扫描器-->
        <property name = "basePackage" value = "com.dao"/>
        <property name = "sqlSessionFactoryBeanName" value = "sqlSessionFactory"/>
    </bean>
</beans>

7-在src目录下创建com.dao包,在该包中创建数据操作接口OrdersDao

import com.po.Orders;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@Mapper
public interface OrdersDao {
    public List<Orders> selectAllOrdersAndProducts() ;
}

8-在src目录下创建包com.controller,并在该包中创建MoreToMoreController类,在该类中调用接口方法

import com.dao.OrdersDao;
import com.po.Orders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;
@Controller
public class MoreToMoreController {
     @Autowired
    private OrdersDao ordersDao ;
     public void test(){
         List <Orders> os = ordersDao.selectAllOrdersAndProducts() ;
         for(Orders os1 : os){
             System.out.println(os1) ;
         }
     }
}

9-在com.controller包中创建测试类TestMoreToMore

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestMoreToMore {
    public static void main(String[] args){
        ApplicationContext appCon = new ClassPathXmlApplicationContext("applicationContext.xml") ;
        MoreToMoreController mtm = (MoreToMoreController) appCon.getBean("moreToMoreController");
        mtm.test() ;
    }
}

10-测试结果

以上是关于MyBatis多对多级联查询的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis一对多级联查询

MyBatis一对一级联查询

java,mybatis 一对多级联查询,怎么给多的一方添加条件啊???

实体框架 CTP5,代码优先。多对多级联删除

MyBatis-记录

Mybatis_多对一关联查询