精华内容
下载资源
问答
  • Mybatis04_多对多查询

    万次阅读 2020-05-15 09:29:17
    Mybatis03_多对多查询 customer表结构: customer表内容: goods表结构: goods表内容: 中间表customer_goods表结构: 中间表customer_goods表内容: Customer实体: package com.blu.entity; import java....

    Mybatis04_多对多查询

    customer表结构:
    在这里插入图片描述
    customer表内容:
    在这里插入图片描述
    goods表结构:
    在这里插入图片描述
    goods表内容:
    在这里插入图片描述
    中间表customer_goods表结构:
    在这里插入图片描述
    中间表customer_goods表内容:
    在这里插入图片描述
    Customer实体:

    package com.blu.entity;
    
    import java.util.List;
    import lombok.Data;
    
    @Data
    public class Customer {
    	private long id;
    	private String name;
    	private List<Goods> goods;
    }
    

    Goods实体:

    package com.blu.entity;
    
    import java.util.List;
    import lombok.Data;
    
    @Data
    public class Goods {
    	private long id;
    	private String name;
    	private List<Customer> customers;
    }
    
    查询Customer带Goods

    CustomerRepository接口:

    package com.blu.repository;
    
    import com.blu.entity.Customer;
    
    public interface CustomerRepository {
    	public Customer findById(long id);
    }
    

    CustomerRepository.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.blu.repository.CustomerRepository">
    	<resultMap id="customerMap" type="com.blu.entity.Customer">
    		<id column="cid" property="id"></id>
    		<result column="cname" property="name"></result>
    		<collection property="goods" ofType="com.blu.entity.Goods">
    			<id column="gid" property="id" />
    			<result column="gname" property="name" />
    		</collection>
    	</resultMap>
    	<select id="findById" parameterType="long" resultMap="customerMap">
    		select c.id cid,c.name cname,g.id gid,g.name gname
    		from customer c,goods g,customer_goods cg 
    		where c.id = #{id} and cg.cid = c.id and cg.gid = g.id
    	</select>
    </mapper>
    

    注册mapper

    <mapper resource="com/blu/mapper/CustomerRepository.xml"></mapper>
    

    测试方法:

    public class Test {
    	public static void main(String[] args) {
    		InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
    		SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    		SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		CustomerRepository customerRepository = sqlSession.getMapper(CustomerRepository.class);
    		Customer customer = customerRepository.findById(1L);
    		System.out.println(customer);
    		sqlSession.close();	
    	}
    }
    

    结果:

    Customer(id=1, name=张三, goods=[Goods(id=1, name=电视, customers=null), Goods(id=3, name=洗衣机, customers=null)])
    

    查询Goods带Customer

    GoodsRepository 接口:

    package com.blu.repository;
    
    import com.blu.entity.Goods;
    
    public interface GoodsRepository {
    	public Goods findById(long id);
    }
    

    GoodsRepository.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.blu.repository.GoodsRepository">
    	<resultMap id="goodsMap" type="com.blu.entity.Goods">
    		<id column="gid" property="id"></id>
    		<result column="gname" property="name"></result>
    		<collection property="customers" ofType="com.blu.entity.Customer">
    			<id column="cid" property="id" />
    			<result column="cname" property="name" />
    		</collection>
    	</resultMap>
    	
    	<select id="findById" parameterType="long" resultMap="goodsMap">
    		select c.id cid,c.name cname,g.id gid,g.name gname
    		from customer c,goods g,customer_goods cg
    		where g.id = #{id} and cg.cid = c.id and cg.gid = g.id
    	</select>
    </mapper>
    

    注册mapper

    <mapper resource="com/blu/mapper/GoodsRepository.xml"></mapper>
    

    测试方法:

    public class Test {
    	public static void main(String[] args) {
    		InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
    		SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    		SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    		SqlSession sqlSession = sqlSessionFactory.openSession();
    		GoodsRepository goodsRepository = sqlSession.getMapper(GoodsRepository.class);
    		Goods goods = goodsRepository.findById(3L);
    		System.out.println(goods);
    		sqlSession.close();
    	}
    }
    

    结果:

    Goods(id=3, name=洗衣机, customers=[Customer(id=1, name=张三, goods=null), Customer(id=3, name=李华, goods=null)])
    
    展开全文
  • SpringBoot使用Mybatis注解进行一对多和多对多查询

    万次阅读 多人点赞 2018-01-04 00:10:52
    SpringBoot使用Mybatis注解进行一对多和多对多查询 GitHub的完整示例项目地址kingboy-springboot-data 一、模拟的业务查询 系统中的用户user都有唯一对应的地址信息address,每个用户可以有多量车car,类似如下...

    SpringBoot使用Mybatis注解进行一对多和多对多查询

    GitHub的完整示例项目地址springboot-data

    一、模拟的业务查询

    系统中的用户user都有唯一对应的地址信息address,每个用户可以有多量车car,类似如下结构

    |-- user
        |-- address
        |-- carList
            |-- car1
            |-- car2
    

    二、对应的实体类如下

    @Data
    public class AddressPO {
    
        private Long id;
    
        /**
         * 省份
         */
        private String province;
    
        /**
         * 城市
         */
        private String city;
    
        /**
         * 街道
         */
        private String street;
    }
    
    @Data
    public class CarPO {
    
        private Long id;
    
        /**
         * 颜色
         */
        private String color;
    
        /**
         * 品牌
         */
        private String name;
    
        private Long userId;
    }
    
    @Data
    public class UserPO extends AbstractPO {
    
        private Long id;
    
        private String username;
    
        private String password;
    
        private Integer age;
    
        private GenderEnum gender;
    
        /**
         * 地址信息,和用户是一对一的关系
         */
        private AddressPO address;
    
        /**
         * 地址id
         */
        private Long addressId;
    
        /**
         * 用户拥有的车,和用户是一对多的关系
         */
        private List<CarPO> cars;
    
    }
    

    三、对应的建表语句和模拟数据如下

    CREATE TABLE IF NOT EXISTS `user`
    (
        `id`          int(11)     NOT NULL AUTO_INCREMENT COMMENT '主键',
        `username`    varchar(20) NOT NULL UNIQUE COMMENT '用户名',
        `password`    varchar(50) NOT NULL COMMENT '密码',
        `age`         int(2)      NOT NULL COMMENT '年龄',
        `gender`      varchar(10) NOT NULL COMMENT '性别',
        `address_id`  int(11)              DEFAULT NULL COMMENT '地址',
        `creater`     varchar(20)          DEFAULT NULL COMMENT '创建人',
        `modifier`    varchar(20)          DEFAULT NULL COMMENT '更新人',
        `create_time` datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
        `modify_time` datetime    NOT NUll DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
        PRIMARY KEY (`id`),
        KEY `index_gender` (`gender`) USING BTREE COMMENT '性别'
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8mb4
      COLLATE = utf8mb4_bin;
    
    CREATE TABLE IF NOT EXISTS `address`
    (
        `id`       int(11) NOT NULL AUTO_INCREMENT,
        `province` varchar(50) DEFAULT NULL,
        `city`     varchar(50) DEFAULT NULL,
        `street`   varchar(50) DEFAULT NULL,
        PRIMARY KEY (`id`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8mb4
      COLLATE = utf8mb4_bin;
    
    CREATE TABLE IF NOT EXISTS `car`
    (
        `id`      int(11) NOT NULL AUTO_INCREMENT,
        `color`   varchar(50) DEFAULT NULL,
        `name`    varchar(50) DEFAULT NULL,
        `user_id` int(11)     DEFAULT NULL,
        PRIMARY KEY (`id`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8mb4
      COLLATE = utf8mb4_bin;
    
    INSERT INTO `user`(username, password, age, gender, address_id)
    VALUES ('KimZing', '123456', '25', 'MAN', 1), ('kim', '123456', '25', 'MAN', 2);
    
    INSERT INTO `address`
    VALUES ('1', '北京', '北京', '王府井'),
           ('2', '天津', '天津', '周良'),
           ('3', '安徽', '宿州', '涌桥'),
           ('4', '广东', '广州', '顺德');
    
    INSERT INTO
        `car`
    VALUES
    ('1', 'green', '路虎', '1'),
    ('2', 'white', '奔驰', '2'),
    ('3', 'blue', '玛莎拉蒂', '1'),
    ('4', 'yellow', '兰博基尼', '2');
    

    四、@One一对一映射

    以获取用户的唯一地址为例,首先我们定义一个根据地址id查询地址的查询方法

    @Mapper
    public interface AddressRepository {
        /**
         * 根据地址id查询地址
         */
        @Select("SELECT * FROM `address` WHERE id = #{id}")
        AddressPO findAddressById(Long id);
    }
    

    然后我们定义一个根据用户id查询用户的方法

    @Mapper
    public interface MySqlUserRepository {
       
        @Select("SELECT * FROM `user` WHERE id = #{id}")
        UserPO find(Long id);
    
    }
    

    这个时候我们查询出来的user对象中的address属性是空的,和address并没有任何关联。
    那么我们要把user中的addressId传递给AddressRepository的查询地址的方法,
    然后把查询出的地址对象address赋值给user的address属性,那么我们怎么做呢?

    @Mapper
    public interface MySqlUserRepository {
    
        @Select("SELECT * FROM `user` WHERE id = #{id}")
        @Results({
                @Result(property = "address", column = "address_id",
                        one = @One(select = "com.kimzing.data.repository.AddressRepository.findAddressById"))
        })
        UserPO find(Long id);
    
    }
    

    我们要使用@Resutl注解对返回的结果进行配置,

    • property = “address”, 表示要将返回的查询结果赋值给user的address属性
    • column = “address_id” 是指将user表中的address_id作为com.kimzing.data.repository.AddressRepository.findAddressById的查询参数
    • one 表示这是一个一对一的查询
    • @One(select = "方法全路径) 表示我们调用的方法

    五、@Many一对多查询

    以获取用户拥有的所有车car为例,首先我们定义一个根据用户id查询车的查询方法

    @Mapper
    public interface CarRepository {
        /**
         * 根据用户id查询所有的车
         */
        @Select("SELECT * FROM `car` WHERE user_id = #{userId}")
        List<Car> findCarsByUserId(Long userId);
    }
    

    然后我们定义一个根据用户id查询用户的方法

    @Mapper
    public interface MySqlUserRepository {
       
        @Select("SELECT * FROM `user` WHERE id = #{id}")
        UserPO find(Long id);
    
    }
    

    这个时候我们查询出来的user对象中的List属性是空的,和car的查询方法并没有任何关联。
    那么我们要把user中的用户id传递给CarRepository的查询车的方法,
    然后把查询出的集合对象List赋值给user的cars属性,那么我们怎么做呢?(和获取地址是有些类似的)

    package com.kimzing.data.repository.impl;
    
    import com.kimzing.data.domain.po.UserPO;
    import org.apache.ibatis.annotations.*;
    
    import java.util.List;
    
    /**
     * 数据存储.
     *
     * @author KimZing - kimzing@163.com
     * @since 2020/1/31 13:12
     */
    @Mapper
    public interface MySqlUserRepository {
    
        @Select("SELECT * FROM `user` WHERE id = #{id}")
        @Results({
                @Result(property = "address", column = "address_id",
                        one = @One(select = "com.kimzing.data.repository.AddressRepository.findAddressById")),
                @Result(property = "cars", column = "id",
                        many = @Many(select = "com.kimzing.data.repository.CarRepository.findCarsByUserId"))
        }),
        // 对userId进行赋值
        @Result(property = "id", column = "id")
        UserPO find(Long id);
    
    
    }
    
    

    我们要使用@Resutl注解对返回的结果进行配置,

    • property = “cars”, 表示要将返回的查询结果赋值给user的cars属性
    • column = “id” 是指将user表中的用户主键id作为com.kimzing.data.repository.CarRepository.findCarsByUserId的查询参数
    • many 表示这是一个一对多的查询
    • @Many(select = "方法全路径) 表示我们调用的方法, 方法参数userId就是上面column指定的列值

    六、@One @Many的总结

    首先我们统一下概念:查询Address或Car的方法,接下来统称为User的附属查询。

    共同点:

    • 无论是一对一还是一对多,都是通过附属查询来实现的,我们需要定义这个附属查询方法。
    • 在主查询方法中通过@One、@Many指定附属查询方法的全路径。
    • 都通过column来传递参数给附属方法。

    不同点:

    • 一对一,那么附属方法返回的是一个单独的对象
    • 一对多,那么附属方法返回的是一个对象集合
    展开全文
  • 多表之间的数据交互 其实一对一和一对多映射,在前面的配置中已经接触到,我没在日志里直接说明,是...多对多查询稍微有点复杂,举个例子来说,一个商城管理系统中,一名顾客在一个购物清单中可以有多件商品,而...

    多表之间的数据交互

    其实一对一和一对多映射,在前面的配置中已经接触到,我没在日志里直接说明,是因为想要在之后写一篇总结日志(就是本篇),总结这些高级映射的配置。例如一对一查询在关联的嵌套结果集查询中就涉及到,一对多查询则在这个基础上再加上一个或多个嵌套结果集,它们可以是一个实体类,或者是一个集合。多对多查询稍微有点复杂,举个例子来说,一个商城管理系统中,一名顾客在一个购物清单中可以有多件商品,而一件商品可以被多名顾客选购,它们之间的关系是多对对。假设现在有这么一个需求,查询数据表库中,所有的顾客信息,包括它们的购物清单,以及清单里面的商品信息,怎么做?下面会说。

    无论是一对一、一对多还是多对多查询,都涉及到不同表之间的数据交互,因为它们之间需要主外键关系来关联,例如顾客表和购物清单表都有顾客id属性,根据这个属性来查询不同顾客对应的购物清单,有了主外键关系后,就可以进行高级映射了。

     

    事例模型

    为了展示三种映射示例,首先建立一个商场管理系统模型,里面有三张数据表,分别是顾客表user,购物车(商品清单)表shoppingcart和商品表products。顾客和商品清单之间是一对多的关系,因为一名顾客可以多次进商场购物,每一次购物生成一个购物清单(购物车),而每一张购物清单只属于一名顾客,所以顾客表和购物车表之间是一对多的关系。   还有商品表product,因为一张购物清单中可以有多件商品,所以商品表和购物车表为一对多的关系。因为一名顾客可以购买多件商品,一件商品也可以属于多名顾客,所以顾客和商品又构成多对多关系。我们在测试时,可以建立基本的三张表,:顾客表、购物车表和商品表(当然最好多加几张表,例如商品评价表),它们之间的查询可以组合出一对一、一对多以及多对多的关系,理清各张表的关系后,就可以进行测试了。

     

    一对一嵌套结果集查询

    从上面的事例模型中可以看到,含一对一关系的两张表有,购物车表和用户表,要注意其中的顺序不要弄乱,购物车和顾客是一对一关系,但反过来不是,顾客和购物车是一对多的关系。在查询需求中,这种多表之间一对一查询的场景,典型的有:一对一嵌套结果集查询。举个例子,假如我们要查询购物车表中,某一张购物清单信息,以及对应的该名顾客的个人信息。有两种配置方式,或是说两种方法实现:

    resultType结合查询包装类

    实现上面的一对一嵌套结果集查询,如果使用resultType来配置SQL映射的话,因为涉及到两张表的交互,且最后只能映射到一个实体类中,所以需要新建一个查询包装类,来包括其中含有的两张表的结果集字段对应的属性(这句话表述的不好- -、)。也就是说,新创建一个查询包装类,里面既含有购物车表中的字段对应的属性,也含有用户表中字段对应的属性,这样才能接收结果集中包含的两个表里的数据。来看看这个查询包装类:

    // 购物车表一对多查询包装类
    public class ShoppingCartInstance extends ShoppingCart implements Serializable {	
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	private String username; //顾客姓名
    	private String gender; //性别
    	private String province; //省会
    	private String city; //城市
    
    	public ShoppingCartInstance() {
    		
    	}
    	
    	public ShoppingCartInstance(int cartId, int userId, int productId, 
    			String productName, int number, 
    			double price, User user, String username, String gender, String province, 
    			String city) {
    		super(cartId, userId, productId, productName, number, price);
    		this.username = username;
    		this.gender = gender;
    		this.province = province;
    		this.city = city;
    	}
        // 省略get()和set()方法
    }

    我们的查询包装类采用继承的方式得到购物车实体类的所有属性,当然你也可以重新一个一个自己定义,这样来舍去一些不需要的属性。接着在查询包装类中追加顾客表中的属性,对应返回结果集中顾客数据表的字段。

          数据包装类准备好后,接下来可以写我们的SQL语句和映射配置了:

    <!-- 一对一查询:resultType实现 -->
    	<select id="queryShoppingCartInstance1" parameterType="int" resultType="ShoppingCartInstance">
    		SELECT
    			S.cartId, S.productName, S.userId, S.price, S.number,
    			U.id, U.username, U.gender, U.province, U.city
    		FROM ShoppingCart S left outer join user U on S.userId = U.id 
    		WHERE S.cartId = #{id}
    	</select>

    SQL语句根据id查询出购物清单,并根据外键,顾客id关联另一张数据表user顾客表。

    	public void TestAssociationQuery() throws IOException {
    		SqlSession sqlSession = dataConn.getSqlSession();
    		List<ShoppingCartInstance> resultList = sqlSession.selectList("queryShoppingCartInstance1", 2);
    		StringBuffer result = new StringBuffer();
    		double totalAmount;
    		
    		System.out.println("顾客姓名: " + resultList.get(0).getUsername());
    		System.out.println("性别: " + resultList.get(0).getGender());
    		System.out.println("商品清单:" + "\r\n");
    		
    		for(int i=0; i<resultList.size(); i++) {
    			ShoppingCartInstance shoppingCartInstance = resultList.get(i);
    			result.append("商品名:" + shoppingCartInstance.getProductName() + "\r\n");
    			result.append("商品数量:" + shoppingCartInstance.getNumber() + "\r\n");
    			totalAmount = (shoppingCartInstance.getPrice()*shoppingCartInstance.getNumber());
    			result.append("商品总价:" + String.format("%.2f", totalAmount) + "\r\n");
    			
    			System.out.println(result.toString());
    			result.setLength(0);
    		}
    		
    		sqlSession.close();
    	}

    最后写个简单的测试用例,查询购物车id为2的商品清单信息,以及对应的顾客信息。

     

    resultMap结合association标签

    使用resultMap配置的话,灵活性就增强了许多,首先resultMap允许我们配置返回结果集中字段名和Java包装类中属性名的一一映射关系。且resultMap中提供的如association标签和collection标签,功能强大,可以配置多表之间的交互。还是上面的例子采用resultMap配置的话,在查询包装类中,我们可以直接追加一个User类的实例:

    public class ShoppingCartInstance extends ShoppingCart implements Serializable {	
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    //	private String username; //顾客姓名
    //	private String gender; //性别
    //	private String province; //省会
    //	private String city; //城市
    	private User user; //对应用户
    	private Product products;
    
    	public ShoppingCartInstance() {
    		
    	}
    	
    	public ShoppingCartInstance(int cartId, int userId, int productId, 
    			String productName, int number, 
    			double price, User user) {
    		super(cartId, userId, productId, productName, number, price);
    //		this.username = username;
    //		this.gender = gender;
    //		this.province = province;
    //		this.city = city;
    		this.user = user;
    	}
        // 省略get()和set()方法
    }

    这个User类实例就是用来接收返回结果集中的顾客信息。接下来就配置它们的映射关系:

    <resultMap type="shoppingCartInstance" id="shoppingCartResult">
    		<id property="id" column="shoppingCart_id"/>
    		<result property="cartId" column="cart_id"/>
    		<result property="productName" column="product_name"/>
    		<result property="price" column="product_price"/>
    		<result property="number" column="product_number"/>
    		<result property="productId" column="product_id"/>
    		<association property="user" column="cartUser_id" javaType="com.mybatis.po.User" 
    		resultMap="userResult"/>
    	</resultMap>
    	
    	<resultMap type="com.mybatis.po.User" id="userResult">
    		<id property="id" column="user_id"/>
    		<!-- 配置User类中的映射关系 -->
    		<result property="username" column="user_name"/>
    		<result property="gender" column="user_gender"/>
    		<result property="province" column="user_province"/>
    		<result property="city" column="user_city"/>
    	</resultMap>

    在查询包装类的映射关系配置resultMap中,type指明接收的实体类是shoppingCartInstance,下面除了配置各个数据库字段和实体类属性的映射外,还用assocaition标签配置关联的嵌套结果集,也就是查询包装类中的User类实例,并且指明User类的映射关系resultMap是引用外部的userResult(也就是下面那个)。

          配置完resultMap,那SQL语句就很简单,把resultType修改为resultMap就可以了:

    <!-- 一对多查询SQL语句 -->
    	<select id="queryShoppingCartInstance2" parameterType="int" resultMap="shoppingCartResult">
    		SELECT
    			S.cartId	as cart_id,
    			S.productName	as product_name,
    			S.userId	as cartUser_id,
    			S.price	as product_price,
    			S.number	as product_number,
    			U.id	as user_id,
    			U.username	as user_name,
    			U.gender	as user_gender,
    			U.province	as user_province,
    			U.city	as user_city
    		FROM ShoppingCart S left outer join user U on S.userId = U.id 
    		WHERE S.cartId = #{id}
    	</select>

    最后是测试用例:

    ​
    	public void TestAssociationQuery() throws IOException {
    		SqlSession sqlSession = dataConn.getSqlSession();
    		List<ShoppingCartInstance> resultList = sqlSession.selectList("queryShoppingCartInstance2", 2);
    		StringBuffer result = new StringBuffer();
    		double totalAmount;
    		
    		System.out.println("顾客姓名: " + resultList.get(0).getUser().getUsername());
    		System.out.println("性别: " + resultList.get(0).getUser().getGender());
    		System.out.println("商品清单:" + "\r\n");
    		
    		for(int i=0; i<resultList.size(); i++) {
    			ShoppingCartInstance shoppingCartInstance = resultList.get(i);
    			result.append("商品名:" + shoppingCartInstance.getProductName() + "\r\n");
    			result.append("商品数量:" + shoppingCartInstance.getNumber() + "\r\n");
    			totalAmount = (shoppingCartInstance.getPrice()*shoppingCartInstance.getNumber());
    			result.append("商品总价:" + String.format("%.2f", totalAmount) + "\r\n");
    			
    			System.out.println(result.toString());
    			result.setLength(0);
    		}
    		
    		sqlSession.close();
    	}
    
    ​

     

    一对多查询

    一对多查询,假如我们在上面例子的基础上,加上一个,查询出购物清单中每一件商品的一些商品信息,如顾客对件商品的评价,怎么做?

    包装类和SQL映射配置

    首先看查询包装类,既然是在上一个例子的基础上,增加查询顾客对商品的评价信息,那么只需要在原有的查询包装类中,加上一个结果集属性即可,因为一件商品可以被多名顾客做评价,所以商品的评价属性我们用一个集合List来表示:

    // 一对多查询包装类
    public class ShoppingCartInstance extends ShoppingCart implements Serializable {	
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	private User user; //对应用户
    	private List<ProductAppraise> productAppraise; //商品评价集合
    
    	public ShoppingCartInstance() {
    		
    	}
    	
    	public ShoppingCartInstance(int cartId, int userId, int productId, 
    			String productName, int number, 
    			double price, User user, List<ProductAppraise> productAppraise) {
    		super(cartId, userId, productId, productName, number, price);
    		this.user = user;
    		this.productAppraise = productAppraise;
    	}   
        // 省略get()和set()方法
    }

    查询包装类定义好后,接下来到SQL语句和映射配置。因为有嵌套结果集和结合的缘故,很明显我们要用resultMap来配置映射关系:

    <!-- 一对多映射配置 -->
    	<resultMap type="shoppingCartInstance" id="multiShoppingCartResult" 
    	extends="shoppingCartResult">
    		<collection property="productAppraise" ofType="ProductAppraise">
    			<!-- 主键 -->
    			<id column="id" property="id"/>
    			<result property="productId" column="productAppraise_id"/>
    			<result property="productScore" column="product_score"/>
    			<result property="userId" column="user_id"/>
    		</collection>
    	</resultMap>

    因为我们的需求是在上面的查询基础上,增加查询商品的评价,所以映射配置我们只需继承上面的resultMap,然后增加一个嵌套集合配置,使用collection标签即可。

          配置还没完,还有最重要的SQL语句:

    <!-- 一对多查询SQL语句 -->
    	<select id="queryShoppingCartInstance2" parameterType="int" resultMap="shoppingCartResult">
    		SELECT
    			S.cartId	as cart_id,
    			S.productName	as product_name,
    			S.userId	as cartUser_id,
    			S.price	as product_price,
    			S.number	as product_number,
    			U.id	as user_id,
    			U.username	as user_name,
    			U.gender	as user_gender,
    			U.province	as user_province,
    			U.city	as user_city
    		FROM ShoppingCart S left outer join user U on S.userId = U.id 
    		WHERE S.cartId = #{id}
    	</select>

    SQL语句中,查询三张表中的数据,根据外键顾客id来关联顾客和对应的购物车,根据商品号productId来关联购物车中的商品和商品评价信息。

    测试用例

    最后是一对多查询的测试用例:

    // 一对多查询测试用例
    public void TestAssociationQuery() throws IOException {
    		SqlSession sqlSession = dataConn.getSqlSession();
    		List<ShoppingCartInstance> resultList = sqlSession.selectList("queryShoppingCartInstance4");
    		StringBuffer result = new StringBuffer();
    		double totalAmount;
    		
    		System.out.println("顾客姓名: " + resultList.get(0).getUser().getUsername());
    		System.out.println("性别: " + resultList.get(0).getUser().getGender());
    		System.out.println("商品清单:" + "\r\n");
    		
    		for(int i=0; i<resultList.size(); i++) {
    			ShoppingCartInstance shoppingCartInstance = resultList.get(i);
    			result.append("商品名:" + shoppingCartInstance.getProductName() + "\r\n");
    			result.append("商品数量:" + shoppingCartInstance.getNumber() + "\r\n");
    			totalAmount = (shoppingCartInstance.getPrice()*shoppingCartInstance.getNumber());
    			result.append("商品总价:" + String.format("%.2f", totalAmount) + "\r\n");
    			
    			List<ProductAppraise> appraiseList = shoppingCartInstance.getProductAppraise();
    			for(int j=0; j<appraiseList.size(); j++) {
    				ProductAppraise productAppraise = appraiseList.get(j);
    				System.out.println("商品评分:" + productAppraise.getProductScore());
    			}
    			
    			System.out.println(result.toString());
    			result.setLength(0);
    		}
    		
    		sqlSession.close();
    	}

    测试用例中,每一次从结果集中拿到一个shoppingCartInstance对象后,第18行,都要从对象中再获取商品评价的集合,然后从商品评价集合中在获取商品评分,这里要注意一下。

    测试结果:

     

    多对多查询

    还有更复杂的需求,就是要用到多对多查询,由前面事例模型可知,具有多对多关系的是顾客和商品之间,因为一名顾客可以购买多种商品,同一种商品也可以被多名顾客购买,这就形成了很明显的多对多关系。假如现在有这么一个需求,查询所有的顾客,以及这些顾客对应的商品清单,还有清单里所有商品的商品id信息。怎么做?还是先从查询包装类开始:

    // 多对多查询包装类
    public class ShoppingCartInstance extends ShoppingCart implements Serializable {	
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	private User user; //对应用户
    	private Product products;
    
    	public ShoppingCartInstance() {
    		
    	}
    	
    	public ShoppingCartInstance(int cartId, int userId, int productId, 
    			String productName, int number, 
    			double price, User user, Product products) {
    		super(cartId, userId, productId, productName, number, price);
    		this.user = user;
    		this.products = products;
    	}
        // 省略get()和set()方法
    }

    为了简化示例,我们只查询商品信息中的商品id信息,再查询包装类中,我们在上面的示例基础上,移除商品评价集合,追加一个商品结果集实体类实例对象products,用来接收商品信息。

    多个association标签

    接下来到SQL映射配置:

        <resultMap type="shoppingCartInstance" id="shoppingCartResult">
    		<id property="id" column="shoppingCart_id"/>
    		<result property="cartId" column="cart_id"/>
    		<result property="productName" column="product_name"/>
    		<result property="price" column="product_price"/>
    		<result property="number" column="product_number"/>
    		<result property="productId" column="product_id"/>
    		<association property="user" column="cartUser_id" javaType="com.mybatis.po.User" 
    		resultMap="userResult"/>
    		<association property="products" column="cartUser_id" javaType="com.mybatis.po.Product">
    			<result property="productId" column="products_id"/>
    		</association>
    	</resultMap>
    	
    	<resultMap type="com.mybatis.po.User" id="userResult">
    		<id property="id" column="user_id"/>
    		<!-- 配置User类中的映射关系 -->
    		<result property="username" column="user_name"/>
    		<result property="gender" column="user_gender"/>
    		<result property="province" column="user_province"/>
    		<result property="city" column="user_city"/>
    	</resultMap>

    在多对多映射配置中,注意用了两个association标签,这是可以的,因为我们的查询包装类中,嵌套了两个实体类,一个顾客类和一个商品类。两个association标签配置有一点不同就是,顾客映射关系配置使用了外部的resultMap,而商品信息映射关系配置直接在association标签内配置,两种方法都可以。SQL映射配置完后,到SQL语句:

    <!-- 多对多查询SQL示例语句 -->
    	<select id="queryShoppingCartInstance4" resultMap="shoppingCartResult">
    		SELECT
    			S.cartId	as cart_id,
    			S.productName	as product_name,
    			S.userId	as cartUser_id,
    			S.price	as product_price,
    			S.number	as product_number,
    			S.productId as product_id,
    			U.id	as user_id,
    			U.username	as user_name,
    			U.gender	as user_gender,
    			U.province	as user_province,
    			U.city	as user_city,
    			P.productId as products_id
    		FROM Products P, ShoppingCart S, user U 
    		WHERE S.userId = U.id AND S.productId = P.productId
    	</select>

    这个比较简单,注意外键的关联即可,通过顾客id关联顾客和顾客的商品清单,通过商品id关联购物清单中的商品和商品信息。最后是测试用例:

    // 多对多测试用例
    public void TestAssociationQuery() throws IOException {
    		SqlSession sqlSession = dataConn.getSqlSession();
    		List<ShoppingCartInstance> resultList = sqlSession.selectList("queryShoppingCartInstance4");
    		StringBuffer result = new StringBuffer();
    		double totalAmount;
    		
    		for(int i=0; i<resultList.size(); i++) {
    			ShoppingCartInstance shoppingCartInstance = resultList.get(i);
    			result.append("顾客姓名: " + shoppingCartInstance.getUser().getUsername() + "\r\n");
    			result.append("性别: " + shoppingCartInstance.getUser().getGender() + "\r\n");
    			result.append("商品id:" + shoppingCartInstance.getProducts().getProductId() + "\r\n");
    			result.append("商品名:" + shoppingCartInstance.getProductName() + "\r\n");
    			result.append("商品数量:" + shoppingCartInstance.getNumber() + "\r\n");
    			totalAmount = (shoppingCartInstance.getPrice()*shoppingCartInstance.getNumber());
    			result.append("商品总价:" + String.format("%.2f", totalAmount) + "\r\n");
    
    			System.out.println(result.toString());
    			result.setLength(0);
    		}
    		
    		sqlSession.close();
    	}

    也比较简洁明了,因为所有信息都在一个查询包装类中,我们可以一一拿出来:

     

    完整实现已上传GitHub:

    https://github.com/justinzengtm/SSM-Framework

    展开全文
  • Mybatis一对一、一对多、多对多查询。+MYSQL

    万次阅读 多人点赞 2018-08-09 10:03:28
    场景:使用三张数据表:student学生表、teacher教师表、position职位表 一个学生可以有多为老师、一位老师可以有多个学生、但是一个老师只能有一个...多对多关系:查找被教授教导的所有学生(首先职位对老师一对多...

    场景:使用三张数据表:student学生表、teacher教师表、position职位表

    一个学生可以有多为老师、一位老师可以有多个学生、但是一个老师只能有一个职位:教授、副教授、讲师;但是一个职位可以有多个老师:例如教授可以多人

    这里则产生了:

    一对一关系,从老师角度:老师对职位一对一

    一对多关系,从职位角度:职位对老师一对多

    多对多关系:查找被教授教导的所有学生(首先职位对老师一对多,老师再对学生再对多、这里便有了一对多对多)

    数据表:

    老师表

    CREATE TABLE `tb_teacher` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_no` varchar(20) DEFAULT NULL,
      `t_name` varchar(20) DEFAULT NULL,
      `position_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
    
    /*Data for the table `tb_teacher` */
    
    insert  into `tb_teacher`(`id`,`t_no`,`t_name`,`position_id`) values
    (1,'163314001','张文远',1),
    (2,'163314002','赵传智',1),
    (3,'163314003','风清扬',2),
    (4,'163314004','王汇智',2),
    (5,'163314005','汪思远',3);

    学生表

    CREATE TABLE `tb_student` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_stu_name` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
    
    /*Data for the table `tb_student` */
    
    insert  into `tb_student`(`id`,`t_stu_name`) values 
    
    (1,'赵依'),
    
    (2,'钱迩'),
    
    (3,'张山'),
    
    (4,'李石'),
    
    (5,'王武'),
    
    (6,'马柳');

    职位表

    CREATE TABLE `tb_position` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_pos_name` varchar(20) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    /*Data for the table `tb_position` */
    
    insert  into `tb_position`(`id`,`t_pos_name`) values 
    
    (1,'教授'),
    
    (2,'副教授'),
    
    (3,'讲师');

    最后是教师学生关系表

    CREATE TABLE `tb_stu_teach` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `t_stu_id` int(11) DEFAULT NULL,
      `t_teach_id` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
    
    /*Data for the table `tb_stu_teach` */
    
    insert  into `tb_stu_teach`(`id`,`t_stu_id`,`t_teach_id`) values 
    
    (1,1,1),
    
    (2,1,2),
    
    (3,1,3),
    
    (4,2,2),
    
    (5,2,3),
    
    (6,2,4),
    
    (7,3,3),
    
    (8,3,4),
    
    (9,3,5),
    
    (10,4,4),
    
    (11,4,5),
    
    (12,4,1);
    

    最后在eclipse中的目录结构如下:

    希望您明白sqlMapConfig该如何配置,以及jdbc.properties和log4j的作用。

    贴出POJO中的三个实体(注意:以下的POJO都用了lombok来快速生成setter和getter等,lomok具体使用,请见此文):

    Position.java

    package com.pojo;
    
    import java.io.Serializable;
    
    import lombok.Data;
    
    @Data
    public class Position implements Serializable {
    	private int id;
    	private String name;
    	
    	private Teacher teacher;
    
    }
    

    Student.java

    package com.pojo;
    
    import java.io.Serializable;
    import java.util.List;
    
    import lombok.Data;
    
    @Data
    public class Student implements Serializable {
    	private String id;
    	private String name;
    	
    	private List<Teacher> list;
    }

    Teacher.java

    package com.pojo;
    
    import java.io.Serializable;
    import java.util.List;
    
    import lombok.Data;
    
    @Data
    public class Teacher implements Serializable {
    	private int id;
    	
    	private String no;
    	private String name;
    	private List<Student> studentList;
    	
    	private Position pos;
    }
    

    注意:关系表不用以实体表示出来,表示外键关系的ID也不用写在实体中(一般我们也不使用外键)

     

    再贴另一个MybatisUtil.java工具类

    package com.util;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    public class MyBatisUtil {
    	private static SqlSessionFactory sqlSessionFactory = null;
    	
    	static {
    		String resource = "sqlMapConfig.xml";
    		// 首先要加载核心配置文件:从classpath下开始找。
    		InputStream in;
    		try {
    			in = Resources.getResourceAsStream(resource);
    			
    			sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    		} catch (IOException e) {
    			throw new RuntimeException(e.getMessage());
    		}	
    	}
    	
    	public static SqlSession getSqlSession() {
    		
    		return sqlSessionFactory.openSession();
    	}
    	
    	public static SqlSessionFactory getSqlSessionFactory() {
    		return sqlSessionFactory;
    	}
    }
    

    一对一:老师对职位

    TeacherMapper.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.mapper.TeacherMapper">
    	<resultMap type="Teacher" id="teacherPositionResultMap">
    		<id property="id" column="id"/>
    		<result property="no" column="t_no"/>
    		<result property="name" column="t_name"/>
    		<!-- association:配置的一对一属性 -->
    		<!-- property:名字
    			 javaType:类型
    		 -->
    		<association property="pos" javaType="Position">
    			<id property="id" column="id"/>
    			<result property="name" column="t_pos_name"/>
    		</association>
    	</resultMap>
    	
    	<!-- 一对一关联查询,查询老师及其对应的职位 -->
    	<!-- 注意:id不能相同,当多个值传入,比如包装类的时候,我们才能够用SQL片段的形式来做if判断,单个值是不行的 -->
    	<select id="queryTeacherPositionResultMapById" resultMap="teacherPositionResultMap" parameterType="Integer">
    		SELECT *
    		FROM tb_teacher t
    		LEFT JOIN tb_position p
    		ON t.position_id = p.id
    		where t.id = #{id}
    	</select>
    
    	<select id="queryTeacherPositionResultMap" resultMap="teacherPositionResultMap">
    		SELECT *
    		FROM tb_teacher t
    		LEFT JOIN tb_position p
    		ON t.`position_id` = p.id
    	</select> 
    </mapper>

    TeacherMapper.java接口

    package com.mapper;
    
    import java.util.List;
    
    import com.pojo.Teacher;
    
    public interface TeacherMapper {
    	public List<Teacher> queryTeacherPositionResultMap();
    	
    	public Teacher queryTeacherPositionResultMapById(Integer id);
    }
    

    测试一对一:

    package com.test;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.mapper.TeacherMapper;
    import com.pojo.Teacher;
    import com.util.MyBatisUtil;
    
    public class TestOneToOne {
    	@Test
    	public void testOneToOne() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		System.err.println(sqlSession);
    		
    		TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
    		
    		List<Teacher> list = teacherMapper.queryTeacherPositionResultMap();
    		
    		System.out.println(list);
    		
    		Teacher teacher = teacherMapper.queryTeacherPositionResultMapById(1);
    		System.out.println(teacher);
    	}
    }
    

     

    一对多:职位对老师

    PositionMapper.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.mapper.PositionMapper"> 
    	<resultMap type="Position" id="positionTeacherResultMap">
    		<id property="id" column="id"/>
    		<result property="name" column="t_pos_name"/> <!-- t_name -->
    		<!-- 
    		property同association中的一样是属性名称(javaBean中的);
    		javaType也同association中的是类型,
    		最后多了一个OfType,因为一对多,不像一对一是单个的!我们这里是List集合,list和List都可以。
    		一对多其中是放的一个集合所以这个是集合的泛型的类型,这里我们的list中放的是Teacher:
    		所以这里是Teacher。
    		 -->
    		<collection property="teacherList" javaType="list" ofType="Teacher" >
    			<!-- 
    				一对多出现的问题:
    					当数据库表中,主表的主键id和明细表的 ...
    					当表中的字段名相同时怎么办?多表联查?
    					
    					注意:Mybatis中做多表联查的时候,不管是
    					一对一、一对多、一对多对多:多对多:
    					都不能有字段重名的情况:不管是主键还是普通字段。
    					一旦字段重名的话,就会造成数据少自动赋值,或者覆盖,甚至重复赋值!
    					规避和解决此类问题的方法:
    						1.尽量不要表间重名,mybatis里处理起来很麻烦!id和普通字段都是。
    						但是在表多的时候,很难不会出现字段重名的情况。主键id最容易重名!
    						那么就要用以下的办法了!
    						
    						2.在mybatis中写原生SQL进行查询的时候,查的字段尽可能的少,这
    						也影响速率,强烈禁止使用*,用多少查多少!这样也能及时发现字段重
    						名的情况!
    						
    						3.最后如果真的需要查出重名的字段,并且修改数据库字段名造成的更改
    						过大,这里推荐的方式是给字段取别名,在写resultMap映射的时候,其
    						中的column属性就填写SQL语句中查出字段取的别名,这样就能解决重复
    						问题了!
    			 -->
    			<id property="id" column="t_id"/>
    			<result property="no" column="t_no"/>
    			<result property="name" column="t_name"/>	
    		</collection>
    	</resultMap>
    	
    	<select id="queryPositionTeacherResultMapById" resultMap="positionTeacherResultMap" 
    		parameterType="Integer">
    		<!-- 
    		SELECT *
    		FROM tb_position p
    		LEFT JOIN tb_teacher t
    		ON p.id = t.position_id
    		WHERE p.id = #{id}
    		-->
    		
    		SELECT 
    		p.*, 
    		t.id t_id,
    		t.t_name,
    		t.t_no
    		FROM tb_position p
    		LEFT JOIN tb_teacher t
    		ON p.id = t.position_id
    		WHERE p.id = #{id}
    	</select>
    	
    	<select id="queryPositionTeacherResultMap" resultMap="positionTeacherResultMap" >
    		<!-- 
    		SELECT *
    		FROM tb_position p
    		LEFT JOIN tb_teacher t
    		ON p.id = t.position_id
    		-->
    		
    		SELECT 
    		p.*, 
    		t.id t_id,
    		t.t_name,
    		t.t_no
    		FROM tb_position p
    		LEFT JOIN tb_teacher t
    		ON p.id = t.position_id
    		
    	</select>
    </mapper>
    
    

    TeacherMapper.java接口

    package com.mapper;
    
    import java.util.List;
    
    import com.pojo.Position;
    
    public interface PositionMapper {
    	public Position queryPositionTeacherResultMapById(Integer id);
    	
    	public List<Position> queryPositionTeacherResultMap();
    }
    

    测试一对多:

    package com.test;
    
    import java.util.List;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.mapper.PositionMapper;
    import com.pojo.Position;
    import com.util.MyBatisUtil;
    
    public class TestOneToMany {
    	
    	@Test
    	public void testOneToMany() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		PositionMapper positionMapper = sqlSession.getMapper(PositionMapper.class);
    		List<Position> list = positionMapper.queryPositionTeacherResultMap();
    		
    		System.out.println(list);
    		
    		Position pos = positionMapper.queryPositionTeacherResultMapById(1);
    		
    		System.out.println(pos);
    	}
    }
    

    多对多:职位是教授的老师教授的所有学生(一对多对多:只要你愿意可以一直对多下去...)

    PositionMapper.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.mapper.PositionMapper"> 
    	<resultMap type="Position" id="positionStudentResultMap">
    		<!-- <id property="id" column="id"/> -->
    		<result property="name" column="t_pos_name"/>
    		<collection property="teacherList" javaType="list" ofType="Teacher" >
    			<result property="name" column="t_name"/>	
    			<collection property="studentList" javaType="list" ofType="Student">
    				<result property="name" column="t_stu_name"/>
    			</collection>
    		</collection>
    	</resultMap>
    	
    	<select id="selectPositionStudentByPosId" resultMap="positionStudentResultMap" parameterType="Integer">
    		SELECT p.t_pos_name, t.t_name, s.t_stu_name
    		FROM tb_position p
    		INNER JOIN tb_teacher t ON p.id = t.position_id
    		LEFT JOIN tb_stu_teach st ON st.t_teach_id = t.id
    		LEFT JOIN tb_student s ON s.id = st.t_stu_id
    		WHERE p.id = #{id}
    	</select>
    </mapper>
    
    

    PositionMapper.java接口

    package com.mapper;
    
    import com.pojo.Position;
    
    public interface PositionMapper {
    	public Position selectPositionStudentByPosId(Integer id);
    	
    }
    

    测试:

    package com.test;
    
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import com.mapper.PositionMapper;
    import com.pojo.Position;
    import com.util.MyBatisUtil;
    
    public class TestManyToMany {
    	
    	@Test
    	public void testManyToMany() {
    		SqlSession sqlSession = MyBatisUtil.getSqlSession();
    		PositionMapper positionMapper = sqlSession.getMapper(PositionMapper.class);
    		Position pos = positionMapper.selectPositionStudentByPosId(1);
    		
    		System.out.println(pos);
    	}
    }

     

    展开全文
  • 【MyBatis框架】高级映射-多对多查询

    千次阅读 2015-06-26 09:32:25
    多对多查询 1.需求 查询用户及用户购买商品信息。 2.sql语句 查询主表是:用户表 关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表: orders、orderdetail、items SELECT orders.*,...
  • mysql多对一、多对多查询实践

    万次阅读 2018-05-16 16:36:09
    最近做的功能涉及这方面,算是练了一下... 多对多: 设备和用户多对多,一个用户可有多台设备,一个设备可供多个用户使用。 首先设备表 dev: 用户表 user: 然后创建中间表user_dev 其中user_id 对应user表id ...
  • 1.1 一对多查询 案例:查询所有订单信息及订单下的订单明细信息。 订单信息与订单明细为一对多关系。 使用resultMap实现如下: 1.1.1 Sql语句:三张表的关联查询 标红的分别为查询字段,查询的表,关联查询的条件 ...
  • mybatis一对多再多对多查询

    千次阅读 2018-08-20 19:57:23
    数据库直接查询可以查出某一试卷下有两个班级且两个班级有很学生,但是service调用mybaits查询出来的对象却不对,求看下要怎么写,谢谢! 这是我的映射关系和sql: pojo对象: dao和service: service查询结果: ...
  • mybatis的一对多和多对多查询

    万次阅读 2016-08-14 09:00:32
    一对多和多对多的关系我是以你平时买东西为例子的,一个用户对应多个订单,一个订单对应多个订单明细,一个订单明细对应一个商品,根据这些关系来进行实例演示。实例演示 一对多(一个订单对应多个订单明细) 1)...
  • mybatis学习笔记(12)-多对多查询

    千次阅读 2016-03-01 09:36:17
    本文实现多对多查询,查询用户及用户购买商品信息。示例查询主表是:用户表关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表:orders、orderdetail、items
  • -- 多对多查询:一个用户创建多个订单,一个订单包含多个订单明细,一个订单明细包含一个商品 --&gt; &lt;resultMap type="com.hbut.po.User" id="findUserItemsMap"&gt; &lt...
  • 【MyBatis学习10】高级映射之多对多查询

    万次阅读 多人点赞 2016-06-14 17:32:05
    本文来总结一下mybatis中的多对多映射,从第8节的文章中可以看出,用户表和商品表示多对多关系,它们两的多对多是通过订单项和订单明细这两张表所关联起来的,那么这一节主要来总结一下用户表和商品表之间的多对多...
  • 查询配置 &lt;!-- 一查询 ,一个订单对应一个用户--&gt; &lt;select id="findOrdersUser" resultType="com.OrdersCustom" resultMap="OrdersUserResultMap"...
  • spring data jpa 多对多查询

    万次阅读 2018-07-18 12:28:53
    原文:...以用户-角色 读多为例: User类,用户 @Entity public class User { private String username; private String nickname; private String pass...
  • dapper 多对多查询对象和对象列表

    万次阅读 2017-03-31 16:33:52
    查询一个Operator对象: public Operator Get(string id) { using (MySqlConnection conn = DapperFactory.CrateMySqlConnection()) { string sql = "SELECT a.*,c.*,e.* FROM t_operator a left join t_...
  • Django中多对多查询方式

    万次阅读 2017-08-28 11:27:36
    增与改(增添子表或母表数据参照一对一的增,多对多重点在于关系表的对应关系变更) 创建商家C添加全部分类 Store .objects .create (s_name= "商家C" ) .sc .add (*(Category .objects .all ())) #如果商户已存在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,921,488
精华内容 768,595
关键字:

多对多查询