精华内容
下载资源
问答
  • 主要介绍了Mybatis 一对多和多对一关联查询问题,需要的朋友可以参考下
  • 主要介绍了mybatis 一对一、一对多和多对多查询的实例代码,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 今天小编就为大家分享一篇关于mybatis关系映射之一对多和多对一,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
  • 使用mybatis操作数据库也有好一阵时间了,本篇记录并解释一下使用mybatis进行一对多,多对一查询显示数据。(一对一此处不讲解,会了一对多查询,一对一也就会了) 本例用员工表部门表作为讲解,首先看员工表...

    使用mybatis操作数据库也有好一阵时间了,本篇记录并解释一下使用mybatis进行一对多,多对一查询显示数据。(一对一此处不讲解,会了一对多查询,一对一也就会了)

    本例用员工表和部门表作为讲解,首先看员工表和部门表的表结构:

    在这里插入图片描述
    解释:部门表就包含两个字段,员工表的部门编号作为外键指向部门表的部门号(员工表是子表(这里可以理解为从表),部门表是父表(这里可以理解为主表))
    (一般存在关系的表,在多的一方(员工表)存一(部门表)的字段(此例是存部门表的部门号)作为外键)

    员工表:
    在这里插入图片描述
    部门表:
    在这里插入图片描述
    写java接口之前先把sql写出来,一般来说,进行关联查询(一对一,一对多,多对一),至少要用两张表以上,

    首先看多对一,意思是说。多个员工对应一个部门,先看sql:

    #查询全部员工信息
    SELECT e.id,emp_name,emp_pwd, sex,age,phone,iner_date,job,d.depart_name
    FROM employee e
    LEFT JOIN department d ON e.depart_id = d.id;

    在上面就讲述了存在关系的表,用关联字段把两张表连接起来(此例是用员工表的部门编号关联部门表的部门号),也就是两表关联查询

    查看结果:
    (数据有点少啊哈哈哈)
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190908175213520.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NfYmlhbmNoZW5neGlhb2JhaQ==,size_16,color_FFFFFF,t_70
    上面相信有sql基础的朋友都能写出来,那怎么在java上表示这种关系呢。
    首先java先创建员工类和部门类的javaBean:
    员工类:
    在这里插入图片描述
    (注意要遵循javabean规范,此处的构造器和setget方法省略)

    部门类:
    在这里插入图片描述
    有朋友会问,员工表不是有个部门编号吗,为什么不把部门编号作为员工类的属性
    这就是sql和java 的区别了

    在数据库中,员工表是通过字段(部门编号)去关联部门表的,那么在java上,则是用部门类作为员工类的属性,这样两者就有关联了!

    员工类:
    在这里插入图片描述
    部门类:
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190908180239226.png
    员工类存单个部门类,部门类存员工类的集合(前者为多对一,一个员工对应一个部门,后者为一对多,一个部门对应多个员工)

    理解这种关系后,就可以写mapper了(用注解也行)。
    (多对一)
    首先写dao接口:
    在这里插入图片描述
    对应的mapper:
    在这里插入图片描述
    因为是两张表,所以返回的是resultMap
    resultMap:
    在这里插入图片描述
    主要是看红色圈:该标签是用来关联“一”的(此例关联部门类),把查询到的关于部门的数据(此例为部门名)放到该属性上,形成多对一。
    写完后,单元测试一下:
    在这里插入图片描述
    数据就出来了:
    在这里插入图片描述
    在这里插入图片描述
    红圈处为部门表的数据

    再来看一对多:一个部门对应多个员工,先看sql:
    #查询部门对应的员工信息
    SELECT d.id,depart_name,e.id eid,emp_name,phone
    FROM department d LEFT JOIN employee e ON
    d.id = e.depart_id;
    结果:
    在这里插入图片描述
    先写dao接口:

    对应的mapper:
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190908211016171.png![在这里插入图片描述](https://img-blog.csdnimg.cn/20190908213513603.png
    此处注意:因为查询的字段有两个相同名字的,所以后者用别名区别一下
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190908211041924.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NfYmlhbmNoZW5neGlhb2JhaQ==,size_16,color_FFFFFF,t_70
    主要看红色大框的地方,上处框了两个红框,先看第一个,由于是一对多关联,所以使用的标签把查到的属于员工表的字段映射员工类的属性上。
    第二个框(根据需要)的意思是把查到的字段再映射到员工类下的部门属性字段:
    在这里插入图片描述
    可以进行级联映射。
    写测试查看结果:
    在这里插入图片描述在这里插入图片描述
    至此,一对多的结果就出来了

    最后说一下本人用mybatis查询踩的一些坑:
    首先是别名问题,比如上例
    SELECT d.id,depart_name,e.id eid,emp_name,phone
    FROM department d LEFT JOIN employee e ON
    d.id = e.depart_id
    不要别名eid,直接在column写e.id员工id是出不来的(显示null)

    再看一下类型区别:
    resultMap中的type指的是返回的整个类型,这里返回的是Department(不设置别名的话要写全限定名(包名+类名))
    collection上的property是Department类中的员工属性名,ofType是指该属性的元素值(属性employees是List类型,用ofType表示List下的Employee元素 javaType是写java类型,比如List的实现类ArrayList)
    在这里插入图片描述

    一对多和多对一的本质都差不多,一对多会了,一对一,多对一也就会了。

    展开全文
  • 主要介绍了Mybatis一对多关联关系映射实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了 Mybatis 中的一对一,一对多,多对多的配置原则示例代码,需要的朋友可以参考下
  • mybatis 一对多性能优化 demo mybatis 一对多性能优化 demo
  • mybatis递归 一对多的实现方法示例
  • mybatis一对多的查询方法详解! mybatis一对多的查询方法详解! mybatis一对多的查询方法详解! mybatis一对多的查询方法详解!
  • MyBatis一对多和多对

    万次阅读 多人点赞 2013-10-29 23:40:22
    在做这个实验的时候,也因为没有理解清楚id含义而导致一对多的“多”中也只有一条数据。idresult的唯一不同是id表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存嵌入结果映射。...
         在学习MyBatis3的过程中,文档上面一直在强调一个id的东西!在做这个实验的时候,也因为没有理解清楚id含义而导致
    一对多的“多”中也只有一条数据。id和result的唯一不同是id表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存和嵌入结果映射。
    所以不同数据的id应该唯一区别,不然导致数据
    结果集只有一条数据。 
    

    一、表


    二、实体

    1.person

    package com.kerwin.mybatis.pojo;
    
    import java.util.List;
    
    public class Person {
    
    	private int id;
    	private String name;
    	private List<Orders> orderList;
    
    	public int getId() {
    		return id;
    	}
    
    	public void setId(int id) {
    		this.id = id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public List<Orders> getOrderList() {
    		return orderList;
    	}
    
    	public void setOrderList(List<Orders> orderList) {
    		this.orderList = orderList;
    	}
    
    	@Override
    	public String toString() {
    		return "Person [id=" + id + ", name=" + name + "]";
    	}
    
    	public Person() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    
    	public Person(int id, String name, List<Orders> orderList) {
    		super();
    		this.id = id;
    		this.name = name;
    		this.orderList = orderList;
    	}
    
    }
    

    2.order


    package com.kerwin.mybatis.pojo;
    
    public class Orders {
    	private int id;
    	private double price;
    	private Person person;
    	
    	
    	
    	public Person getPerson() {
    		return person;
    	}
    
    	public void setPerson(Person person) {
    		this.person = person;
    	}
    
    	public int getId() {
    		return id;
    	}
    
    	public void setId(int id) {
    		this.id = id;
    	}
    
    
    
    	public double getPrice() {
    		return price;
    	}
    
    	public void setPrice(double price) {
    		this.price = price;
    	}
    
    
    	
    
    	@Override
    	public String toString() {
    		return "Orders [id=" + id + ", price=" + price + "]";
    	}
    
    	public Orders() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    
    }
    

    三、映射mapper文件

    1. PersonMapper.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.kerwin.mybatis.pojo.Person">
    	<resultMap type="com.kerwin.mybatis.pojo.Person" id="personreSultMap">
    		<id column="p_id" property="id"/>
    		<result column="name" property="name"/>
    		<collection property="orderList" ofType="com.kerwin.mybatis.pojo.Orders" column="pid">
    			<id column="o_id" property="id"/>
    			<result column="price" property="price"/>
    		</collection>
    		
    	</resultMap>
    	
    	<select id="selectPersonFetchOrder" parameterType="int" resultMap="personreSultMap" >
    		select p.*,o.* from person p,orders o where o.pid=p.p_id and p.p_id=#{id}
    	</select>
    	
    	
    </mapper>

    2.     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.kerwin.mybatis.pojo.Orders">
    	<resultMap type="com.kerwin.mybatis.pojo.Orders" id="OrdersResultMap">
    		<id column="o_id" property="id"/>
    		<result column="price" property="price"/>
    		<association property="person" javaType="com.kerwin.mybatis.pojo.Person">
    			<id column="p_id" property="id"/>
    			<result column="name" property="name"/>
    		</association>
    	</resultMap>
    	
    	<select id="selectOrdersFetchPerson" resultMap="OrdersResultMap">
    		select p.*,o.* from person p,orders o where o.pid=p.p_id and o.o_id=#{id} 
    	</select>
    
    </mapper>

    3.sqlMapConfig.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="com.kerwin.mybatis.pojo.Author" alias="Author"/>
    </typeAliases>
      <environments default="development">
        <environment id="development">
          <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="root"/>
          </dataSource>
        </environment>
      </environments>
      <mappers>
    	<mapper resource="com/kerwin/mybatis/pojo/AuthorMapper.xml"/>
    	<mapper resource="com/kerwin/mybatis/pojo/PostMapper.xml"/>
    	<mapper resource="com/kerwin/mybatis/pojo/PersonMapper.xml"/>
    	<mapper resource="com/kerwin/mybatis/pojo/OrdersMapper.xml"/>
      </mappers>
    </configuration>

    四。测试类

    /**
     * 
     */
    package com.kerwin.mybatis.test;
    
    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;
    import org.junit.BeforeClass;
    import org.junit.Test;
    
    import com.kerwin.mybatis.pojo.Orders;
    import com.kerwin.mybatis.pojo.Person;
    
    /**
     * @author Administrator
     * 
     */
    public class PersonAndOrderTest {
    
    	private static SqlSessionFactory sessionFactory;
    	
    	/**
    	 * @throws java.lang.Exception
    	 */
    	@BeforeClass
    	public static void setUpBeforeClass() throws Exception {
    		SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
    		InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    		sessionFactory = factoryBuilder.build(inputStream);
    
    	}
    	
    	//一对多,查询person(一)级联查询订单order(多)
    	@Test
    	public void testSelectPersonFetchOrder() throws Exception {
    		SqlSession session = sessionFactory.openSession();
    		Person person = session.selectOne("com.kerwin.mybatis.pojo.Person.selectPersonFetchOrder", 1);
    		System.out.println(person);
    		System.out.println(person.getOrderList().size());
    		for(Orders orders : person.getOrderList()){
    			System.out.println(orders);
    		}
    		session.close();
    	}
    	
    	//多对一,查询订单order(多)级联查询person(一)
    	@Test
    	public void testSelectOrdersFetchPerson() throws Exception{
    		SqlSession session = sessionFactory.openSession();
    		Orders orders = session.selectOne("com.kerwin.mybatis.pojo.Orders.selectOrdersFetchPerson", 1);
    		System.out.println(orders);
    		System.out.println(orders.getPerson());
    		session.close();
    	}
    	
    }
    

    五、测试结果

    1.一对多,查询person(一)级联查询订单order(多)


    2.多对一,查询订单order(多)级联查询person(一)


    注意:两张表中的主键id字段名要唯一,例如不能都写id,不然的话,在一对多查询的时候就会出现:级联出来的订单项只有一条记录。我之前就是将两张表的主键id字段名都写为id,导致测试结果级联出来的多一直只有一条数据,具体如下:



    展开全文
  • 使用MyBatis写的一对多关联映射查询的web,在eclipse上写的,使用的Mysql进行数据连接,内含数据库脚本,直接导入数据库即可建数据库建表,不用再编写,非常方便
  • 主要给大家介绍了关于Spring boot整合Mybatis实现级联一对多CRUD操作的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • MyBatis一对多映射

    2017-05-26 10:59:39
    MyBatis一对多映射实例,代码完整,可运行
  • 、整合mybatis 1、建表phone_type DROP TABLE IF EXISTS `phone_type`; CREATE TABLE `phone_type` ( `type_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '类型id', `number_part` varchar(50) DEFAULT NULL ...

    一、整合mybatis

    1、建表phone_type

    DROP TABLE IF EXISTS `phone_type`;
    CREATE TABLE `phone_type` (
      `type_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '类型id',
      `number_part` varchar(50) DEFAULT NULL COMMENT '号码段',
      `type_name` varchar(50) DEFAULT NULL COMMENT '类型名称',
      `type_remark` varchar(255) DEFAULT NULL COMMENT '类型备注',
      PRIMARY KEY (`type_id`),
      KEY `type_id` (`type_id`,`type_name`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    INSERT INTO `phone_type` VALUES ('1', '131', '中国联通', '老号码');
    
    

    在这里插入图片描述

    2、导入依赖

     <!-- mybatis -->
       <dependency>
           <groupId>org.mybatis.spring.boot</groupId>
           <artifactId>mybatis-spring-boot-starter</artifactId>
           <version>2.1.3</version>
       </dependency>
    

    3、model

    @Entity
    @Table(name = "phone_type")
    public class PhoneType {
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        private String type_id;
        private String number_part;
        private String type_name;
        private String type_remark;
    
        // 省略get/set方法
    }
    

    4、dao

    @Mapper
    public interface PhoneTypeDao {
        PhoneType findByNumber(@Param("number") String number);
    }
    

    5、mapper

    <?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.example.jpa.demo_jpa.dao.PhoneTypeDao" >
    
        <resultMap id="phoneTypeMap" type="com.example.jpa.demo_jpa.model.PhoneType" >
            <id column="type_id" property="type_id" jdbcType="INTEGER" />
            <result column="number_part" property="number_part" jdbcType="VARCHAR" />
            <result column="type_name" property="type_name" jdbcType="VARCHAR" />
            <result column="type_remark" property="type_remark" jdbcType="VARCHAR" />
        </resultMap>
        <select id="findByNumber" resultMap="phoneTypeMap" parameterType="String">
            select * from phone_type
            <where>
                number_part = #{number}
            </where>
        </select>
    
    </mapper>
    

    6、配置文件

    server.port=8080
    
    spring.datasource.url=jdbc:mysql://xxx/xxx?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    spring.datasource.username=
    spring.datasource.password=
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    
    # mybatis
    mybatis.type-aliases-package=com.example.jpa.demo_jpa.dao
    mybatis.mapper-locations=classpath:/mappers/*Mapper.xml
    
    

    注意这里配置mybatis的路径,要跟自己的包所对应

    在这里插入图片描述
    在这里插入图片描述

    7、service

    public interface PhoneTypeService {
    	//通过号码查找信息
        PhoneType findByNumber(String number);
    }
    

    8、serviceImpl

    @Service
    public class PhoneTypeServiceImpl implements PhoneTypeService {
    
    	   @Autowired
    	   private PhoneTypeDao phoneTypeDao;
    	
    	   @Override
    	    public PhoneType findByNumber(String number) {
    	        return phoneTypeDao.findByNumber(number);
    	    }
    }
    

    9、controller

    @RestController
    public class HelloController {
    
        @Autowired
        PhoneTypeService phoneTypeService;
        
        @RequestMapping("/findByNumber")
        public PhoneType findByNumber(String number){
            return phoneTypeService.findByNumber("131"); //这里为了方便测试,直接写定了这个“131”,实际应该是由前端传来的。
        }
        
    }
    

    10、测试

    成功查询到号码为“131”的数据信息:

    在这里插入图片描述

    11、增删改查的mapper(示例)

        <!--通过文章标题和内容精准查询-->
        <select id="findByTitleText" resultType="com.tweet.tweetapi.domain.Tweet" resultMap="TweetResultMap">
            select *
            from tweet
            where title = #{title} and text = #{text}
        </select>
    
        <!--添加-->
        <insert id="save" parameterType="com.tweet.tweetapi.domain.Tweet" >
             insert into tweet values (#{id}, #{title},#{caid},#{tid},#{text})
        </insert>
    
        <!--删除-->
        <delete id="delete" parameterType="String">
            delete from tweet where id = #{id}
        </delete>
    
        <!--修改-->
        <update id="update" parameterType="com.tweet.tweetapi.domain.Tweet">
            update tweet
            set title = #{title}, caid = #{caid}, tid = #{tid}, text = #{text}
            where id = #{id}
        </update>
    

    二、mybatis一对多查询

    场景: 一篇文章(tweet)有多个关键词(keyword),多个关键词对应一篇文章

    在这里插入图片描述

    1、文章实体类

    在这里插入图片描述

    2、xml文件

    在这里插入图片描述

    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.tweet.tweetservice.dao.TweetDao">
    
        <resultMap id="TweetResultMap" type="com.tweet.tweetapi.domain.Tweet">
            <result column="id" property="id" jdbcType="VARCHAR"/>
            <result column="title" property="title" jdbcType="VARCHAR"/>
            <result column="caid" property="caid" jdbcType="VARCHAR"/>
            <result column="tid" property="tid" jdbcType="VARCHAR"/>
            <result column="text" property="text" jdbcType="VARCHAR"/>
            <collection  property="keyWordList" ofType="com.tweet.tweetapi.domain.KeyWord">
                <result column="kwid" property="kwid"/>
                <result column="kwname" property="kwname"/>
                <result column="twid" property="twid"/>
            </collection>
        </resultMap>
    
        <!--通过id查询-->
        <select id="findById"  resultMap="TweetResultMap">
            select *
            from tweet t,keyword k
            where t.id = k.twid and t.id = #{twid}
        </select>
        
    </mapper>
    

    3、效果展示

    在这里插入图片描述

    三、mybatis多对一查询

    1、关键词实体类

    在这里插入图片描述

    2、xml文件

    在这里插入图片描述

    3、效果展示

    在这里插入图片描述

    展开全文
  • 主要介绍了Mybatis中的高级映射一对一、一对多、多对多的相关资料,需要的朋友可以参考下
  • 什么是一对多?  一对多关系应该是开发人员接触得最多的关联关系。打个比方,淘宝上,一个用户他拥有多个订单,而这几个订单单独属于此用户,这个关联关系就叫一对多关系。在数据库中则表示为两张表互相关联,如...
  • 最近做项目遇到这样的需求要求将表中的数据,按照一级二级分类返回给前端json数据,下面通过本文给大家分享通过Mybatis实现单表内一对多的数据展示示例代码,感兴趣的朋友参考下吧
  • mybatis 一对多 多对一

    2014-08-05 14:48:35
    mybatis 一对多 多对一
  • mybatis一对多查询功能

    2020-08-31 09:33:15
    主要介绍了mybatis一对多查询功能,非常不错,具有参考借鉴价值,需要的朋友可以参考下
  • mybatis一对多小例子

    2011-09-30 15:58:38
    一对多,从多得一方取出一的一方.只是一个小例子,表结构能才出来的
  • NULL 博文链接:https://yuanleilei628.iteye.com/blog/2209753
  • 1. 一对一关系和一对多关系 2.准备 2.1创建两张表 2.2 创建工程 2.3 创建实体类 2.4 创建Mybatis-config.xml文件 2.5 创建SessionFactory的Util类 3. 实现一对一 3.1 创建订单类的sql映射文件:OrderMapper....

    目录

    1.  一对一关系和一对多关系

    2.准备

    2.1创建两张表

    2.2 创建工程

    2.3 创建实体类

    2.4 创建Mybatis-config.xml文件

    2.5 创建SessionFactory的Util类

    3. 实现一对一

    3.1 创建订单类的sql映射文件:OrderMapper.xml

    3.2 创建接口类:OrderMapper

    3.3 测试类:MapperTest

    4.实现一对多


     

    项目结构图

    环境:

    开发工具:Intellij idea 2018.3版本

    JDK:1.8

    数据库:Mysql 8.0.11

    Mybatis:3.4.1

     

     

    在讲案例前先明确什么是一对一,一对多。

    1.  一对一关系和一对多关系

    (以下来自于黑马程序员的视频笔记) 

    • 什么关系属于一对一

         一个身份证对应着一个公民,一个公民也对应着一张身份证

    • 一对一的建表原则:

    两种对应方式:

    唯一外键对应:在任意一方加一个外键,然后加个unique约束条件。本文中采用这种

    主键对应:就是主键对主键

    • 什么样关系属于一对多?

       一个用户对应多个订单,一个订单只能属于一个用户

       一个客户对应多个联系人,一个联系人只能属于某一个客户。

    • 一对多的建表原则:

           在多的一方创建外键指向一的一方的主键

     


     这里用到的是两张表,订单表(Orders)和用户表(User)。一个订单对应一个用户,一个用户可以对应着多个订单。虽然这是一对多关系,但是如果从订单角度看,一个订单只能对应一个用户。勉强可以算作一对一,本文中为了缩减代码量,就直接用两个表演示一对一和一对多。下面进入案例。有些代码是重复的,因此得先把这些准备工作做了

    2.准备

    2.1创建两张表

      创建User表,插入三条数据

    CREATE TABLE `user` (
                          `uid` int(11) NOT NULL AUTO_INCREMENT,
                          `username` varchar(32) NOT NULL COMMENT '用户名称',
                          `birthday` date DEFAULT NULL COMMENT '生日',
                          `sex` char(1) DEFAULT NULL COMMENT '性别',
                          `address` varchar(256) DEFAULT NULL COMMENT '地址',
                          PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=UTF8MB4;
    
    INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
    INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
    INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');

     

    创建Orders表,插入两条数据

    CREATE TABLE `orders` (
                            `id` int(11) NOT NULL AUTO_INCREMENT,
                            `user_id` int(11) NOT NULL COMMENT '下单用户id',
                            `number` varchar(32) NOT NULL COMMENT '订单号',
                            `createtime` datetime NOT NULL COMMENT '创建订单时间',
                            `note` varchar(100) DEFAULT NULL COMMENT '备注',
                            PRIMARY KEY (`id`),
                            KEY `FK_orders_1` (`user_id`),
                            CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=UTF8MB4;
    
    INSERT INTO `orders` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
    INSERT INTO `orders` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);

    2.2 创建工程

    可以创建java工程也可以创建javaEE项目,反正测试使用Junit。具体如何创建可以参考我另外一篇文章https://blog.csdn.net/Vibugs/article/details/85246420

    项目结构图

     

    导入jar包:

     

    2.3 创建实体类

    创建Order实体类

    根据一对一的实体类原则,在没有外键的一方实体类中包含外键一方的对象 , 因此Order类中要有User的对象

     

    创建User类

     根据一对多的建立实体类的原则,在没有外键的一方(user)的实体类创建另一方的List集合(List<order>),因此 User类中带有order类的list集合。

     

    2.4 创建Mybatis-config.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>
        <!-- 通过properties导入外部配置文件-->
        <properties resource="MySql.properties"/>
    
        <!--配置别名
          * 1:可以直接设置别名;
          * 2:如果实体类的别名太多了,可以将实体类都放在一个包下,然后这里直接导入包就好了 
          -->
       <typeAliases>
           <typeAlias type="cn.svllen.mybatis.domain.User" alias="user"/>
          <!-- <package name="cn.svllen.mybatis.domain" /> -->
    
       </typeAliases>
    
        <!-- 和spring整合后 environment配置将废除-->
        <environments default="development">
            <environment id="development">
                <!-- 使用jdbc事务管理-->
                <transactionManager type="JDBC"/>
    
                <!-- 数据库连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
    
                </dataSource>
            </environment>
        </environments>
        
        <!--引入map文件 -->
        <mappers>
            <mapper resource="cn/svllen/mybatis/domain/UserMapper.xml"/>
            <mapper resource="cn/svllen/mybatis/domain/OrderMapper.xml"/>
        </mappers>
    </configuration>

    MySql.properties配置文件

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false
    jdbc.username=root
    jdbc.password=12315

    2.5 创建SessionFactory的Util类

    package cn.svllen.mybatis.util;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.InputStream;
    
    /**
     * @program: MybatisDay01
     * @description: 创建SessionFactory的util类
     * @author: svllen
     * @create: 2019-03-23 10:52
     **/
    
    public class SessionFactoryUtil {
    
        public static SqlSessionFactory sqlSessionFactory;
    
        static{
            try{
                InputStream inputStream = Resources.getResourceAsStream("Mybatis-config.xml");
                //构建工厂
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        public static SqlSession getCurrentSession(){
            return sqlSessionFactory.openSession();
        }
    }
    

     

     

    3. 实现一对一

    需求:使用一对一的查找方式,输入订单id查询订单信息,嵌套用户顺便查询出订单所属的用户信息。在sql映射文件中用resultMap标签输出

    实现思路:根据一对一的建表原则,在任意一方(订单表)建立唯一外键指向另一方的主键,确定要查询的唯一订单唯一用户。再根据一对一建立实体类的原则,在没有外键的一方实体类中包含外键一方的对象,显示时通过这个对象获取到关联的用户信息。

    实现过程:sql查询语句中设置两个条件:

        条件1 订单的外键user_id =用户的主键id 

        条件2: 订单的主键id=你要查询的值。

    结果用resultMap结果集返回,类型是Order型,order实体类中有user对象,因此关联的用户信息就可以从里面获取到(即order.getUser()) 。实体类时关联了,但是映射的时候还是得指明关联关系,因此需要在resultMap标签中使用association标签指定。

     

    3.1 创建订单类的sql映射文件:OrderMapper.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="cn.svllen.mybatis.domain.OrderMapper">
    
       <!-- 使用一对一的查找方式,输入订单id查询订单信息,嵌套用户顺便查询出订单所属的用户信息-->
        <select id="OneToOneByOrder"  parameterType="int" resultMap="oneToOneOrderResultMap">
            SELECT
                o.id as order_id,
                user_id, number, createtime, note,
                u.id as user_id,
                username, birthday, sex, address
            FROM orders o, user u WHERE o.user_id = u.id and o.id=#{id}
    
        </select>
        <!-- 使用resultMap输出结果-->
        <resultMap id="oneToOneOrderResultMap" type="cn.svllen.mybatis.domain.Order" >
            <!--要输出的Order的信息 -->
            <id column="order_id" property="id" />
            <result column="number" property="number"/>
            <result column="createtime" property="createtime"/>
            <result column="note" property="note"/>
            <!-- 一对一的关系映射,需要使用association标签
             * property:对象属性的名称
             * javaType:对象属性的类型
             * column:所对应的外键字段名称
             * select:使用另一个查询封装的结果
            -->
            <association property="user" javaType="User" column="user_id" resultMap="UserMap" />
        </resultMap>
    
        <!-- 将一对一的User抽出来,封装重用-->
        <resultMap id="UserMap" type="User">
            <!--要输出的User的信息 -->
            <id column="user_id" property="uId" javaType="int"  />
            <result column="username" property="username"/>
            <result column="birthday" property="birthday"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
        </resultMap>
    
    </mapper>

     

    select标签:

                 1.我给两个表的主键id都起了别名,因为两个表的主键都是一样的名称,当你把结果映射到resultMap的时候会出现显示错误的bug。具体可查看我另一篇文章 https://blog.csdn.net/Vibugs/article/details/86540185

                 2.我们的查询条件有两个,一个是通过order_id查询用户信息,第二是通过外键查询用户信息。因此在sql语句中查询条件是 o.user_id = u.id(即订单表中的user_id外键 = 用户表中的id主键)。但是要插入匹配符#{}的应该是订单的id主键,毕竟我们是通过订单id查询订单信息。

    • 属性:id的值就是OrderMapper接口类 的方法名,parameterType是输入的参数,这里是int型。resultMap:将结果以结果集的形式显示。
    • SQL语句:这里有两个点需要知道。

           

    resultMap标签:

    属性

    id当前命名空间中的一个唯一标识,用于标识一个结果映射。
    type类的完全限定名, 或者一个类型别名(就是决定resultMap的类型)
    autoMapping如果设置这个属性,MyBatis将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。默认值:未设置(unset)

    字段

    • constructor - 用于在实例化类时,注入结果到构造方法中
      • idArg - ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
      • arg - 将被注入到构造方法的一个普通结果
    • id – 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
    • result – 注入到字段或 JavaBean 属性的普通结果
    • association – 一个复杂类型的关联;许多结果将包装成这种类型
      • 嵌套结果映射 – 关联本身可以是一个 resultMap 元素,或者从别处引用一个
    • collection – 一个复杂类型的集合
      • 嵌套结果映射 – 集合本身可以是一个 resultMap 元素,或者从别处引用一个
    • discriminator – 使用结果值来决定使用哪个 resultMap
      • case – 基于某些值的结果映射
        • 嵌套结果映射 – case 本身可以是一个 resultMap 元素,因此可以具有相同的结构和元素,或者从别处引用一个

    本例中两个resultMap的type不一样,select标签指定的oneToOneOrderResultMap是Order类型的,而association关联的UserMap是User类型的。那输出时怎么输出呢,是输出order对象还是user对象呢。其实是输出Order对象,我们在Order实体类中不是定义了user对象吗,可以直接通过order.getUser.getXxx()方法输出User信息。

     

    association标签:

    这个标签上面代码注释里面有对它几个属性的解释。在这里就不多说了

    记得将OrderMapper.xml导入到Mybatis-config.xml文件中

     

     3.2 创建接口类:OrderMapper

    package cn.svllen.mybatis.domain;
    
    
    /**
     * @program: MybatisDay01
     * @description: orderMapper的接口类,用来跟OrderMapper.xml关联起来。里面的一个select标签(也可以回其他标签,insert,update)对应这里的一个方法
     * @author: svllen
     * @create: 2019-03-26 15:30
     **/
    
    public interface OrderMapper {
    
        //使用一对一的查找方式,输入订单id查询订单信息,嵌套用户顺便查询出订单所属的用户信息
        Order OneToOneByOrder(int orderId);
    
        
    }
    

     

    3.3 测试类:MapperTest

     
    public class MapperTest {
    
    
    /**
        * @Description: 一对一的测试,输入订单id查询订单信息,嵌套用户顺便查询出订单所属的用户信息
        * @Param:
        * @return:
        * @Author: svllen
        * @Date: 2019/3/27
        */
        @Test
        public void OneToOneByOrderTest(){
            SqlSession sqlSession = SessionFactoryUtil.getCurrentSession();
            OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
            int orderId = 4;
            //查询结果
            Order order = orderMapper.OneToOneByOrder(orderId);
            //显示结果
            System.out.println("查询到的订单为:" + order);
            System.out.println("该订单用户为:" + order.getUser());
            sqlSession.commit();
            sqlSession.close();
        }
    
    }

    结果:

     

    4.实现一对多

    需求:通过输入用户id查询多个订单信息,用户信息也要返回

    实现思路:根据一对多建表原则(在order创建外键指向user的主键),通过order的外键确定要查找的唯一用户至少一个的订单的关系,再根据一对多建实体类的原则,在user实体类中有order的List<order>集合,通过这个集合获取唯一用户下的所有订单。

    过程很相似,直接附上步骤

    创建userMapper接口类:

    package cn.svllen.mybatis.domain;
    
    
    
    import java.util.List;
    
    /**
     * @program: MybatisDay01
     * @description: usermapper的接口类,实现Mapper动态代理开发。取代传统的Dao,DaoImpl这种开发模式。与userMapper形成关联
     * @author: svllen
     * @create: 2019-03-25 10:03
     **/
    
    public interface UserMapper {
    
        /*为了跟mapper.xml文件产生关联,这里有四个原则
        * 1. 接口方法名等于id名
        * 2. 返回值类型与resultType的一样
        * 3. 方法的形参跟parameterType一样
        * 4. 在.xml文件中,命名空间的值是接口类的全路径
         */
    
       
    
        //测试一对多的关系,通过输入用户id查询多个订单信息,用户信息也要返回
        User oneToManyByUser(int userId);
    
    
    
    
    
    
    }
    

     

    创建userMapper.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">
    <!--写sql语句的 -->
    <mapper namespace="cn.svllen.mybatis.domain.UserMapper">
     <!--一对多的测试,通过输入用户id查询多个订单信息,用户信息也要返回 -->
        <select id="oneToManyByUser" parameterType="int" resultMap="userResultMap">
            select
            o.id as order_id,
            user_id, number, createtime, note,
            u.id as user_id,
            username, birthday, sex, address
            FROM orders o ,user u  WHERE o.user_id = u.id and u.id=#{id}
        </select>
    
        <resultMap id="userResultMap" type="user">
            <id column="user_id" property="uId"/>
            <result column="username" property="username"/>
            <result column="birthday" property="birthday"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
            <!-- 一对多的关系。使用collection标签
               * property:指定集合属性的名(User实体类中list集合名)
               * ofType:指的是集合中元素的值,一般是类的完全限定名
            -->
            <collection property="orderList" ofType="order" resultMap="orderResultMap" />
        </resultMap>
    
        <!--可重用的order的resultMap -->
        <resultMap id="orderResultMap" type="order">
            <id column="order_id" property="id" />
            <result column="number" property="number"/>
            <result column="createtime" property="createtime"/>
            <result column="note" property="note"/>
        </resultMap>
    
    </mapper>

     

    创建测试方法:

     /**
        * @Description: 一对多的测试, 通过输入用户id查询多个订单信息,用户信息也要返回
        * @Param:
        * @return:
        * @Author: svllen
        * @Date: 2019/3/29
        */
        @Test
        public void oneToManyByUserTest(){
            SqlSession sqlSession = SessionFactoryUtil.getCurrentSession();
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            //设置查询条件
            int userId = 16;
            User user = userMapper.oneToManyByUser(userId);
            System.out.println("你查到的用户信息为:" + user +"\n该用户下的订单有:");
            List<Order> orderList = user.getOrderList();
            for (Order order : orderList){
                System.out.println(order);
            }
            sqlSession.commit();
            sqlSession.close();
        }

     

    测试结果:

     

    结束语:希望各位点赞 

    展开全文
  • NULL 博文链接:https://qihaibo1989.iteye.com/blog/2354597
  • MyBatis框架的学习(五)——一对一关联映射和一对多关联映射
  • Mybatis实现关联查询一对一和一对多实现,具体效果看博文 http://blog.csdn.net/evankaka/article/details/45674101
  • mybatis一对一,一对多

    2015-11-03 10:50:35
    自己根据mybatis文档测试其中的一对一,一对多,association,collection的使用,更有利于理解。
  • 今天使用mybatis一对多的时候,多的一方只查询出来了一条数据,研究好久才发现问题所在。 出错原因: 我是因为两张表的id字段名称相同造成的,这样子会让后面一条数据覆盖前面一条数据。 问题解决: 修改id字段名,...
  • myBatis一对和一对多

    2011-08-11 16:39:31
    MyBatis简单的一对一和一对多测试,表根据JavaBean自己创建,测试已通过
  • NULL 博文链接:https://yiminhu.iteye.com/blog/2019722
  • mybatis框架(一对多、多对一)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 171,798
精华内容 68,719
关键字:

mybatis一对多和多对一