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提供的延迟加载机制,即在查询一端的时候只查询一端的属性,待需要获取多端的数据时再进行查询。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alone秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值