Mybatis&MySQL 实现多表联查

需求分析,现有三个表:
user表,存储用户信息,包含用户id,姓名,手机号

请添加图片描述
product表,存储产品的信息,包含产品的id,产品名,产品的分类目录
请添加图片描述
transaction表,是一张中间表,存储user表的id、以及product表的id
请添加图片描述

【一对一查询】
需求:根据用户的id查询用户信息

  1. 在UserMappper.java中声明一个方法,用于查找信息时调用
    //根据用户的id进行查找,查找的内容是多个对象,所以用集合进行封装
    List<User> selectByPrimaryKey(Long id);
  1. 在对应的UserMapper.xml中写SQL语句
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from user
        where  ID = #{id,jdbcType=INTEGER} 
    </select>

防止sql注入,以及防止查找的内容出现null 的现象我们使用resultMap

<resultMap id="BaseResultMap" type="com.jyc.pojo.User">
            <id property="id" column="ID" jdbcType="INTEGER"/>
            <result property="username" column="UserName" jdbcType="VARCHAR"/>
            <result property="tel" column="Tel" jdbcType="VARCHAR"/>
    </resultMap>
  1. 编写测试方法
public class UserTest {
    SqlSession sqlSession;
    UserMapper mapper;

    @Before
    public void before() throws Exception{
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        sqlSession = sqlSessionFactory.openSession(true);
        mapper = sqlSession.getMapper(UserMapper.class);
    }

    @After
    public void after() {
        sqlSession.close();
    }

    @Test
    public void selectByPrimaryKeyTest(){
        List<User> user = mapper.selectByPrimaryKey(1L);
        System.out.println(user);
    }
}

至此,一对一查询就结束了。

【多对多查询】
需求1:根据用户的id查询用户所购买的商品全部信息
注:这里我们需要创建一个DTO(数据传输对象)包,用于存储封装查询的结果

  1. 创建TransactionProductDTO.java
package com.jyc.DTO;

import lombok.Data;

@Data
public class TransactionProductDTO {

    private Integer userid;//用户的id
    private Integer productid;//商品的id
    private String productname;//商品的名
    private String catalog;//商品的目录

}
  1. 创建一个方法,用于查询信息时调用
    注:这里需要说明一下,创建的方法可以在任意存在的mapper类下,只要最后测试方法中扫描的“.class”文件是该方法所在的文件中即可
   //我写在了ProductMapper.java中
    List<TransactionProductDTO> findUserProductByUserId(int userid);
  1. 根据DTO类,需要新创建一个resultMap来定义【字段】和【属性】的映射关系
    在ProductMapper.xml输入以下内容
    <resultMap id="TestResultMap1" type="com.jyc.DTO.TransactionProductDTO">
    	<!--    “property” 的值是DTO类中声明的变量     “column”  的值是数据库中的列名,需要保持一致  -->
        <id property="userid" column="UserId" jdbcType="INTEGER"/>
        <id property="productid" column="ProductId" jdbcType="INTEGER"/>
        <result property="productname" column="ProductName" jdbcType="VARCHAR"/>
        <result property="catalog" column="Catalog" jdbcType="VARCHAR"/>
    </resultMap>
  1. 书写SQL语句
<select id="findUserProductByUserId" resultMap="TestResultMap1" >
        select transaction.userId,transaction.productId,product.ProductName,product.Catalog
        from transaction,product
        where transaction.productId = product.id and transaction.userId = #{userid}
    </select>

注:这里需要特别说明,新创建的resultMap需要和对应的SQL语句连在一起,中间不能出现其他代码
在这里插入图片描述

  1. 在ProductTest.java中写测试方法
    首先先把以下内容写在测试是方法前
package com.jyc;

public class TransactionTest {
    SqlSession sqlSession;
    ProductMapper mapper;

    @Before
    public void before() throws Exception{
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        sqlSession = sqlSessionFactory.openSession(true);
        //因为我的方法声明在了ProductMapper.class中,所以扫包是扫描这个类
        mapper = sqlSession.getMapper(ProductMapper.class);
    }

    @After
    public void after(){
        sqlSession.close();
    }

}

测试方法

    @Test
    public void findUserProductByUserId(){
    	//传入要查找的用户id,封装在list集合中
        List<TransactionProductDTO> list = mapper.findUserProductByUserId(1);
        System.out.println(list);
    }

需求2 :根据用户id 查找用户购买的商品信息以及用户的信息
注:这里我们就需要用到中间表Transaction,作为中间的条件

  1. 创建UserTransactionProductDTO.java类,用于封装存储查找的内容
package com.jyc.DTO;

import lombok.Data;

@Data
public class UserTransactionProductDTO {

    private Integer userId;//用户的id
    private String userName;//用户名
    private String userTel;//用户电话号
    private Integer productId;//所购买商品id
    private String productName;//所购买的商品名
    private String productCatalog;//所构面的商品对应的目录
}
  1. 在ProductMapper.java中声明查找信息的方法
    List<UserTransactionProductDTO> findUserProductAndUserInfoByUserId(int userid);
  1. 根据DTO类,需要新创建一个resultMap来定义【字段】和【属性】的映射关系
    在ProductMapper.xml输入以下内容
 <resultMap id="TestResultMap2" type="com.jyc.DTO.UserTransactionProductDTO">
 		<!--    
 		“property” 的值是DTO类中声明的变量     “column”  的值是数据库中的列名,需要保持一致  
		这里由于user表中用户的id名是ID,product表中的商品id 也是ID,
		所以在对应的 “column”  中就不能同时赋值为“ID”
		这里使用中间表Transaction中的列名,UserId、ProductId
		我试了使用【数据库.列名】的方式,出现的查询结果是null
		所以采用的中间表的列名
		-->
        <id property="userId" column="UserId" jdbcType="INTEGER"/>
        <id property="productId" column="ProductId" jdbcType="INTEGER"/>
        <result property="userName" column="userName" jdbcType="VARCHAR"/>
        <result property="userTel" column="Tel" jdbcType="VARCHAR"/>
        <result property="productName" column="ProductName" jdbcType="VARCHAR"/>
        <result property="productCatalog" column="Catalog" jdbcType="VARCHAR"/>
    </resultMap>
  1. 编写SQL语句
<select id="findUserProductAndUserInfoByUserId" resultMap="TestResultMap2">
        select transaction.userid,user.UserName,user.Tel,transaction.productid,product.productname,product.Catalog
        from user inner join transaction on user.id = transaction.UserId
                    inner join product on transaction.productid = product.id
        where user.id = #{userid}
    </select>

在这里插入图片描述

  1. 编写测试方法
@Test
    public void findUserProductAndUserInfoByUserId(){
    //传入需要查找的用户id
        List<UserTransactionProductDTO> userProductAndUserInfoByUserId = mapper.findUserProductAndUserInfoByUserId(1);
        System.out.println(userProductAndUserInfoByUserId);
    }

另外说明:我的包结构如下
在这里插入图片描述
在这里插入图片描述

至此,全部的需求已完成,感谢阅读,存在不足之处,还请指点!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis Plus实现多表联查有两种方式:使用MyBatis Plus的Wrapper类或者使用MyBatis原生的@Results和@ResultMap注解。 1. 使用Wrapper类 使用Wrapper类可以方便地实现多表联查,具体步骤如下: (1)创建Wrapper对象,例如: ``` QueryWrapper<User> wrapper = new QueryWrapper<>(); ``` (2)使用Wrapper对象进行多表联查,例如: ``` wrapper.select("user.id", "user.name", "user.age", "order.order_no") .leftJoin("order", "order.user_id = user.id") .eq("user.id", 1); ``` 其中,select方法用于指定查询的列,leftJoin方法用于指定关联的和关联条件,eq方法用于指定查询条件。 2. 使用@Results和@ResultMap注解 使用@Results和@ResultMap注解可以实现更灵活的多表联查,具体步骤如下: (1)在Mapper接口中定义查询方法,并使用@Select注解指定SQL语句和返回类型,例如: ``` @Select("SELECT u.id, u.name, u.age, o.order_no FROM user u LEFT JOIN order o ON u.id = o.user_id WHERE u.id = #{userId}") @Results(id = "userOrderMap", value = { @Result(column = "id", property = "id"), @Result(column = "name", property = "name"), @Result(column = "age", property = "age"), @Result(column = "order_no", property = "orderNo") }) UserOrderDTO getUserOrderById(@Param("userId") Long userId); ``` 其中,@Results注解用于定义返回结果的映射关系,@Result注解用于定义列名和属性名的对应关系。 (2)在Mapper接口中定义返回结果的DTO类,例如: ``` public class UserOrderDTO { private Long id; private String name; private Integer age; private String orderNo; // 省略getter和setter方法 } ``` (3)在XML配置文件中使用@ResultMap注解引用上述定义的映射关系,例如: ``` <resultMap id="userOrderMap" type="com.example.dto.UserOrderDTO"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="age" property="age"/> <result column="order_no" property="orderNo"/> </resultMap> ``` 使用以上两种方式可以方便地实现多表联查。需要注意的是,在进行多表联查时,需要注意列名的唯一性,避免重复列名导致查询失败。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值