MyBatis关联关系映射

简介: MyBatis关联关系映射

MyBatis关联关系映射

MyBatis是一种ORM(Object-Relational Mapping)框架,支持将Java对象和关系数据库之间的数据进行映射。在MyBatis中,关联关系映射是一种处理实体对象之间关联关系的方法

配置mybatis关联映射

使用ehcache做为二级缓存,这个工具类是由桥接包提供的  

  注意:与hibernate二级缓存不同之处

  hibernate默认会缓存单条、不会缓存多条,想要缓存多条,那么需要通过代码手动开启使用缓存

  mybatis默认就会缓存单条以及多条,如果不想缓存多条,那么在具体的方法sql添加属性值userCache=false

一对多关系配置 :

注意事项,使用左外连接而非内连接!

实体类:

在多的一方(例如Order表)中,需要定义一个表示一的一方(例如User表)的属性,通常是一个对象或集合。


在表示一的一方(例如User表)的实体类中,不需要再定义对应多的一方(例如Order表)的属性。


使用注解或XML文件来配置映射关系时,需要在多的一方(例如Order表)的实体类中,使用一对多的注解或XML配置来指定对应的一的一方(例如User表)的属性,并指定双方的关联列。


在进行一对多关系配置时,需注意双方的关联列(例如Order表中的user_id列与User表中的id列)需要保持一致。

public class Order {
    private Long id;
    private String orderNo;
    private List<OrderItem> orderItems;
    // 省略getter和setter方法
}
public class OrderItem {
    private Long id;
    private String productName;
    // 省略getter和setter方法
}
package com.yuan.vo;
import com.yuan.model.Order;
import com.yuan.model.OrderItem;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhanghao
 * @site
 * @company s 集团
 * @create 2023-09-04 10:48
 */
public class OrderVO extends Order {
    private List<OrderItem> list = new ArrayList<>();
    public List<OrderItem> getList() {
        return list;
    }
    public void setList(List<OrderItem> list) {
        this.list = list;
    }
}
public class Order {
    private Long id;
    private String orderNo;
    private List<OrderItem> orderItems;
    // 省略getter和setter方法
}
public class OrderItem {
    private Long id;
    private String productName;
    // 省略getter和setter方法
}
package com.yuan.vo;
import com.yuan.model.Order;
import com.yuan.model.OrderItem;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhanghao
 * @site
 * @company s 集团
 * @create 2023-09-04 10:48
 */
public class OrderVO extends Order {
    private List<OrderItem> list = new ArrayList<>();
    public List<OrderItem> getList() {
        return list;
    }
    public void setList(List<OrderItem> list) {
        this.list = list;
    }
}
Mapper接口和XML文件
  1. Mapper接口名称必须与对应的XML文件名称相同,并且位于同一个包下。
  2. Mapper接口中的方法名必须与对应的XML文件中的SQL语句ID相同。
  3. 在Mapper接口中定义方法时,需要与XML文件中对应的SQL语句的参数类型、返回值类型、方法名都一致。
  4. 在使用Mapper接口进行CRUD操作时,需要在XML文件中定义对应的SQL查询语句、参数映射以及结果集映射。
  5. 在使用Mapper接口进行查询操作时,需要定义对应的查询结果映射,通常可以使用ResultMap或ResultType来实现。
  6. 在进行Mapper接口和XML文件编写时,需要注意SQL语句的参数名与实体类属性名需要一致,否则可能会出现SQL执行异常。
  7. 当进行多表查询时,需要在XML文件中使用join语句,同时需要注意多表查询的性能问题。
<!-- OrderMapper.xml -->
<mapper namespace="com.zhanghao.mapper.OrderMapper">
    <resultMap id="OrderVoMap" type="com.zhanghao.vo.OrderVO" >
    <result column="order_id" property="orderId"></result>
    <result column="order_no" property="orderNo"></result>
    <collection property="list" ofType="com.zhanghao.model.OrderItem">
      <result column="order_item_id" property="orderItemId"></result>
      <result column="product_id" property="productId"></result>
      <result column="quantity" property="quantity"></result>
      <result column="oid" property="oid"></result>
    </collection>
  </resultMap>
     <select id="demo1" resultMap="OrderVoMap" parameterType="java.lang.Integer" >
    select * from t_hibernate_order o ,t_hibernate_order_item oit where o.order_id = oit.oid and o.order_id = #{oid}
  </select>
</mapper>
查询的方法:
package com.zhanghao.Biz;
import com.zhanghao.vo.OrderVO;
/**
 * @author zhanghao
 * @site
 * @company s集团
 * @create 2023-09-04 10:08
 */
public interface OrderBiz {
    OrderVO demo1(Integer oid);
}
一对多的查询:
package com.zhaghao.Biz.Impl;
import com.zhaghao.Biz.OrderBiz;
import com.zhaghao.vo.OrderVO;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * @author zhaghao
 * @site
 * @company s集团
 * @create 2023-09-04 10:13
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-context.xml"})
public class OrderBizImplTest {
    @Autowired
    private  OrderBiz orderBiz;
    @Test
    public void demo1() {
        OrderVO orderVO = orderBiz.demo1(7);
        System.out.println(orderVO);
        orderVO.getList().forEach(System.out::println);
    }
}

多对一 关系配置 :

实体类
  1. 实体类中需要包含与关联表对应的属性,并且需要使用相应的注解进行注解。一般来说,多对一关系中需要使用@ManyToOne注解表示多个表与一个表的关联关系。
  2. 在使用@ManyToOne注解时,需要指定关联关系的属性,如@JoinColumn注解表示关联外键的名称。
  3. 在实体类中还需要定义与关联表相关的getter和setter方法。
  4. 在多对一关系中,由于多个表关联同一个表,因此需要在实体类中使用关联表的实体类作为属性类型。
  5. 实体类中还需要定义与关联表相关的getter和setter方法。
  6. 在多对一关系中,需要使用@OneToMany注解表示关联表与多个表的关系。
  7. 在使用@OneToMany注解时,需要指定关联关系的属性,如@JoinColumn注解表示关联外键的名称。
  8. 在进行多对一关系的实体类编写时,需要注意两张表之间的外键关系是否正确,否则可能会出现数据一致性问题。
public class Order {
    private Long id;
    private String orderNo;
    private List<OrderItem> orderItems;
    // 省略getter和setter方法
}
public class OrderItem {
    private Long id;
    private String productName;
    // 省略getter和setter方法
}
package com.zhanghao.vo;
import com.zhanghao.model.Order;
import com.zhanghao.model.OrderItem;
/**
 * @author zhanghao
 * @site
 * @company s集团
 * @create 2023-09-04 10:58
 */
public class OrderItemVo extends OrderItem {
   private Order order;
    public Order getOrder() {
        return order;
    }
    public void setOrder(Order order) {
        this.order = order;
    }
}
Mapper接口和XML文件
  1. 在Mapper接口中定义方法时,需要使用@Result注解映射查询结果到实体类。通常情况下,@Result注解需要指定两个属性,一个是column,表示查询结果中的列名,另一个是property,表示映射到实体类的属性名。
  2. 在Mapper接口中定义查询方法时,需要使用@Select注解指定SQL语句,并使用@ResultMap注解指定查询结果映射关系。
  3. 在XML文件中,需要定义一个<resultMap>元素,用于映射查询结果到实体类。<resultMap>元素需要指定id属性、type属性和<id>、<result>子元素。
  4. 在<resultMap>元素中定义<association>元素,用于映射关联表的查询结果到对应实体类的属性上。<association>元素需要指定属性名、column属性和javaType属性,以及<id>、<result>子元素。
  5. 在XML文件中定义查询语句时,需要使用<include>元素引用<resultMap>元素,并且还需要使用<join>元素进行关联查询。
  6. 在<join>元素中需要指定关联表名、关联条件,以及使用<association>元素映射关联表查询结果到实体类的属性。
package com.zhanghao.model;
import lombok.ToString;
@ToString
public class HBook {
    private Integer bookId;
    private String bookName;
    private Float price;
    public HBook(Integer bookId, String bookName, Float price) {
        this.bookId = bookId;
        this.bookName = bookName;
        this.price = price;
    }
    public HBook() {
        super();
    }
    public Integer getBookId() {
        return bookId;
    }
    public void setBookId(Integer bookId) {
        this.bookId = bookId;
    }
    public String getBookName() {
        return bookName;
    }
    public void setBookName(String bookName) {
        this.bookName = bookName;
    }
    public Float getPrice() {
        return price;
    }
    public void setPrice(Float price) {
        this.price = price;
    }
}
package com.yuan.model;
import lombok.ToString;
@ToString
public class HBookCategory {
    private Integer bcid;
    private Integer bid;
    private Integer cid;
    public HBookCategory(Integer bcid, Integer bid, Integer cid) {
        this.bcid = bcid;
        this.bid = bid;
        this.cid = cid;
    }
    public HBookCategory() {
        super();
    }
    public Integer getBcid() {
        return bcid;
    }
    public void setBcid(Integer bcid) {
        this.bcid = bcid;
    }
    public Integer getBid() {
        return bid;
    }
    public void setBid(Integer bid) {
        this.bid = bid;
    }
    public Integer getCid() {
        return cid;
    }
    public void setCid(Integer cid) {
        this.cid = cid;
    }
}
package com.yuan.model;
import lombok.ToString;
@ToString
public class HCategory {
    private Integer categoryId;
    private String categoryName;
    public HCategory(Integer categoryId, String categoryName) {
        this.categoryId = categoryId;
        this.categoryName = categoryName;
    }
    public HCategory() {
        super();
    }
    public Integer getCategoryId() {
        return categoryId;
    }
    public void setCategoryId(Integer categoryId) {
        this.categoryId = categoryId;
    }
    public String getCategoryName() {
        return categoryName;
    }
    public void setCategoryName(String categoryName) {
        this.categoryName = categoryName;
    }
}
package com.zhaghao.vo;
import com.zhaghao.model.HBook;
import com.zhaghao.model.HCategory;
import java.util.List;
/**
 * @author zhaghao
 * @site
 * @company s集团
 * @create 2023-09-04 10:35
 */
public class HbookVo extends HBook {
    private List<HCategory> categories ;
    public List<HCategory> getCategories() {
        return categories;
    }
    public void setCategories(List<HCategory> categories) {
        this.categories = categories;
    }
}
查询方法
package com.zhanghao.Biz.Impl;
import com.zhanghao.Biz.HBookBiz;
import com.zhanghao.mapper.HBookMapper;
import com.zhanghao.vo.HbookVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * @author zhanghao
 * @site
 * @company s集团
 * @create 2023-09-04 11:23
 */
@Service
public class HBookBizImpl implements HBookBiz {
    @Autowired
    private HBookMapper hBookMapper;
    @Override
    public HbookVo demo3(Integer bid) {
        return hBookMapper.demo3(bid);
    }
}
多对多关系查询
package com.zhanghao.Biz.Impl;
import com.zhanghao.Biz.HBookBiz;
import com.zhanghao.vo.HbookVo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * @author zhanghao
 * @site
 * @company s集团
 * @create 2023-09-04 11:24
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring-context.xml"})
public class HBookBizImplTest {
    @Autowired
    private HBookBiz hBookBiz;
    @Test
    public void demo3() {
        HbookVo hbookVo = hBookBiz.demo3(8);
        System.out.println(hbookVo);
        hbookVo.getCategories().forEach(System.out::println);
    }
}

总结:

在使用一对多关系映射的时候,使用group by和聚合函数会影响查询性能,数据库中大量数据可能会使查询变慢。此时可以使用MyBatis提供的延迟加载机制,即在查询一端的时候只查询一端的属性,待需要获取多端的数据时再进行查询。


目录
相关文章
|
2月前
|
XML Oracle Java
mybatis反向生成实体类、dao层以及映射文件
mybatis反向生成实体类、dao层以及映射文件
15 1
|
2月前
|
SQL Java 数据库连接
|
3月前
|
Java 数据库连接 Maven
使用mybatis插件generator生成实体类,dao层和mapper映射
使用mybatis插件generator生成实体类,dao层和mapper映射
61 0
|
4月前
|
SQL Java 数据库连接
MyBatis映射文件深入
MyBatis映射文件深入
62 0
|
4月前
|
SQL Java 数据库连接
Mybatis之Mybatis简介、搭建Mybatis相关步骤(开发环境、maven、核心配置文件、mapper接口、映射文件、junit测试、log4j日志)
【1月更文挑战第2天】 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下,iBatis3.x正式更名为MyBatis。代码于2013年11月迁移到Github iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
208 3
Mybatis之Mybatis简介、搭建Mybatis相关步骤(开发环境、maven、核心配置文件、mapper接口、映射文件、junit测试、log4j日志)
|
2月前
|
XML Java 数据库连接
【MyBatis】1、MyBatis 核心配置文件、多表查询、实体映射文件 ......
【MyBatis】1、MyBatis 核心配置文件、多表查询、实体映射文件 ......
91 0
|
10天前
|
SQL Java 数据库连接
15:MyBatis对象关系与映射结构-Java Spring
15:MyBatis对象关系与映射结构-Java Spring
30 4
|
16天前
|
SQL Java 数据库连接
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
【Mybatis】深入学习MyBatis:概述、主要特性以及配置与映射
|
26天前
|
XML Java 数据库连接
java对象有集合mybatis如何映射
java对象有集合mybatis如何映射
19 4
|
2月前
Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)
Mybatis+mysql动态分页查询数据案例——配置映射文件(HouseDaoMapper.xml)
17 1