MyBatis是一种ORM(Object-Relational Mapping)框架,支持将Java对象和关系数据库之间的数据进行映射。在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 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 list = new ArrayList<>();
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
}
public class Order {
private Long id;
private String orderNo;
private List 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 list = new ArrayList<>();
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
}
Mapper接口名称必须与对应的XML文件名称相同,并且位于同一个包下。
Mapper接口中的方法名必须与对应的XML文件中的SQL语句ID相同。
在Mapper接口中定义方法时,需要与XML文件中对应的SQL语句的参数类型、返回值类型、方法名都一致。
在使用Mapper接口进行CRUD操作时,需要在XML文件中定义对应的SQL查询语句、参数映射以及结果集映射。
在使用Mapper接口进行查询操作时,需要定义对应的查询结果映射,通常可以使用ResultMap或ResultType来实现。
在进行Mapper接口和XML文件编写时,需要注意SQL语句的参数名与实体类属性名需要一致,否则可能会出现SQL执行异常。
当进行多表查询时,需要在XML文件中使用join语句,同时需要注意多表查询的性能问题。
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);
}
}
实体类中需要包含与关联表对应的属性,并且需要使用相应的注解进行注解。一般来说,多对一关系中需要使用@ManyToOne注解表示多个表与一个表的关联关系。
在使用@ManyToOne注解时,需要指定关联关系的属性,如@JoinColumn注解表示关联外键的名称。
在实体类中还需要定义与关联表相关的getter和setter方法。
在多对一关系中,由于多个表关联同一个表,因此需要在实体类中使用关联表的实体类作为属性类型。
实体类中还需要定义与关联表相关的getter和setter方法。
在多对一关系中,需要使用@OneToMany注解表示关联表与多个表的关系。
在使用@OneToMany注解时,需要指定关联关系的属性,如@JoinColumn注解表示关联外键的名称。
在进行多对一关系的实体类编写时,需要注意两张表之间的外键关系是否正确,否则可能会出现数据一致性问题。
public class Order {
private Long id;
private String orderNo;
private List 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接口中定义方法时,需要使用@Result注解映射查询结果到实体类。通常情况下,@Result注解需要指定两个属性,一个是column,表示查询结果中的列名,另一个是property,表示映射到实体类的属性名。
在Mapper接口中定义查询方法时,需要使用@Select注解指定SQL语句,并使用@ResultMap注解指定查询结果映射关系。
在XML文件中,需要定义一个
元素,用于映射查询结果到实体类。 元素需要指定id属性、type属性和 、 子元素。 在
元素中定义 元素,用于映射关联表的查询结果到对应实体类的属性上。 元素需要指定属性名、column属性和javaType属性,以及 、 子元素。 在XML文件中定义查询语句时,需要使用
元素引用 元素,并且还需要使用 元素进行关联查询。 在
元素中需要指定关联表名、关联条件,以及使用 元素映射关联表查询结果到实体类的属性。
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 categories ;
public List getCategories() {
return categories;
}
public void setCategories(List 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提供的延迟加载机制,即在查询一端的时候只查询一端的属性,待需要获取多端的数据时再进行查询。