## 自动Fetch
有时候查询结果出来后需要自动加载额外的数据,类似Hibernate 的关系映射。BeetlSQL3也支持这种自动抓取。不同hibernate的是,他不强制要求有外键关系
> 越来越多数据库设计不考虑外键,这样能提升一些性能。系统从某种角度来说也好维护。
>
> Fetch不支持复合主键,只支持单主键
自动抓取通过@Fetch注解,提醒BeetlSQL3在执行完查询操作后有自动抓取需要完成,BeetlSQL3会解析此POJO的属性,如果一旦有@FetchMany或者@FetchOne,或者@FetchSql,则会执行查询操作
```java
@Data
@Table(name="sys_order")
@Fetch(level =2)
public class CustomerOrder {
@AutoID
Integer id;
String name;
Integer customerId;
@FetchOne(value="customerId")
Customer customer;
}
@Data
@Fetch(level = 2)
@Table(name="sys_customer")
public class Customer {
@AutoID
Integer id;
String name;
@FetchMany("customerId")
List<CustomerOrder> order;
}
@Table(name="sys_order")
@Fetch(level =2)
public class CustomerOrder2 {
@AutoID
Integer id;
String name;
Integer customerId;
@FetchSql("select * from sys_customer where id =#{customerId}")
Customer customer;
@FetchSql("select * from sys_customer s where s.id =#{customerId} order by s.id desc")
List<Customer> customers;
}
```
@Fetch的level属性表示抓取数据的深度,默认是一层,CustomerOrder设定为2,则不仅仅会自动抓取Customer数据,也会抓取Customer的CustomerOrder数据。如果CustomerOrder设定为3,那么,还会从CustomerOrder再次抓取Customer,实现3层抓取
> BeetlSQL3在Fetch过程中把已经抓取的过数据放入内存里,根据各自POJO类的主键判断,数据一旦曾经抓取过,则不会再从数据库里获取。因此不需要担心出现死循环.同时,缓存有利于性能优化,不需要查询数据库
@FetchOne 表示抓取一个,其value值是POJO的一个属性名,该属性名对应的值作为需要·抓取对象的主键,因此CustomerOrder的@FetchOne注解表明了需要使用CustomerOrder.customerId属性值作为主键来查询Customer。因此BeetlSQL3会发起类似如下查询
```java
Integer customerId = getAttrValue(customerOrderIns,"customerId")
Customer customer = sqlMqnager.unique(Customer,customerId);
```
对于Customer对象,需要自动抓取多个CustomerOrder,注解@FetchMany("customerId") 告诉BeetlSQL3.启用模板查询功能查询CustomerOrder,模板的key是“customerId”(也就是CustomerOrder属性customerId),值是POJO的主键,就是Customer.id.因此BeetlSQL会发起类似入如下查询
```java
Integer customerId = getPrimakeyValue(customerIns);
CustomerOrder template = new CustomerOrder();
tempalte.setCustomerId(customerId);
List<CustomerOrder> list = sqlManager.template(tempalte);
```
BeetlSQL3 的FetchOne操作会进行合并查询,比如查询所有CustomerOrder
```java
List<CustomerOrder> orders = sqlManager.all();
```
在BeetlSQL3 进行自动抓取的时候,并不会逐一抓取Customer对象,而是调用sqlManager.selectByIds 一次性抓取所有Customer,提高性能
当使用自动Fetch,设置level=2的时候,出现A引用B,B又引用A的时候,需要特别设计A和B对象的hashcode方法和equals方法,避免出现无限循环,比如
```java
@Fetch(level = 2)
@Table(name="sys_customer")
@EqualsAndHashCode(of="id")
public class Customer {
@AutoID
Integer id;
String name;
@FetchMany("customerId")
List<CustomerOrder> order;
}
```
如果没有`@EqualsAndHashCode(of="id")` 那么Customer的hashcode方法包括CustomerOrder,而CustomerOrder又包含Customer,这样导致hashcode无需循环,出现StackOverflowError。 这并不是BeetlSQL的问题,是hash设计的问题
FetchOne和FetchMany支持符合条件时候抓取。如下
```java
@Data
@Table(name="sys_order")
@Fetch
public class CustomerOrder {
@AutoID
Integer id;
String name;
Integer customerId;
@FetchOne(value="customerId",enableOn="x")
Customer customer;
@FetchOne(value="customerId"")
Account account;
}
```
enableOn表示但BeetlSQL 存在变量x的时候,FetchOne才生效。 sql语句可以通过函数fetchEnableOn 来申明一个变量,如sql语句
```sql
dynamicFetchOrder1
===
select * from sys_order where id = #{id}
-- @ fetchEnableOn("c");
```
fetchEnableOn的实现类是DynamicFetchEnableOnFunction,它能接受多个变量名字,并赋值一个固定值。FetchOne和FetchMany将检测是否存在此变量,如果不存在,则不会实现Fetch操作
- BeetlSQL 3 指南
- 数据访问框架
- 适合用户
- 编译源码
- 直接看代码
- 闲大赋介绍
- BeetlSQL3 特点
- 数据库访问工具的痛点
- BeetlSQL3 例子
- 基础例子
- 结果集映射
- 翻页查询
- 演示like,batchUpdate,in 操作
- 自动fetch
- 多数据库
- 代码生成框架
- 安装BeetlSQL
- 直接安装
- 框架集成
- 编译源码
- 快速开始
- 环境准备
- 环境搭建
- 使用BeetlSQL
- 按照主键查寻
- 更新
- 按照模板查询
- 执行SQL
- 执行模板SQL
- 使用Query
- 使用Mapper
- 使用模板文件
- SQLManager
- 内置语句
- 内置查询API
- template查询
- 更新操作
- 执行SQL
- 执行模板SQL
- 把SQL放到文件里
- 翻页查询
- SQLResult
- Stream查询
- 存储过程调用
- NameConversion(重要)
- DBStyle
- Inerceptor
- SQLManagerExtend
- 强制使用数据源
- Mapper
- 实现Mapper
- @Sql
- @Update @BatchUpdate
- @Template
- 参数名称
- 参数返回值
- 执行SQL文件
- 翻页查询
- @SqlProvider
- @SpringData
- @SubQuery
- @InheritMapper
- @Call
- StreamData
- Default Method
- 定义自己的BaseMapper
- 限制Java代码中SQL长度
- 数据模型
- POJO
- 不严格的POJO
- 交集(重要)
- @Table 注解
- @Column 注解
- 主键
- RowMapper
- ResultSetMapper
- Json配置映射
- Json自动映射
- XML支持
- 自动Fetch
- AttributeConvert
- BeanConvert
- 枚举
- 混合模型
- Map模型
- 动态模型
- 模型其他注解
- 安全扩展注解
- BeetlSql 单表查询工具Query
- Query使用方式和风格介绍
- Query主要操作简介
- 查询器获取
- SELECT简单的条件查询
- 复杂的条件查询
- 查询字段智能处理
- 健壮的变量
- 自定义实现
- INSERT操作
- UPDATE操作
- DELETE操作
- single查询和unique
- COUNT查询
- GROUP分组查询和Having子句
- 分页查询
- ORDER BY 排序
- page分页查询
- 方法调用顺序
- Markdown文件
- Beetl 入门
- 定界符号
- 变量
- 算数表达式
- 逻辑表达式
- 控制语句
- 访问变量属性
- 判断对象非空(重要)
- 调用方法
- 自定义方法
- 内置方法
- 标签功能
- 附录
- Idea 插件
- 代码生成
- 多库使用
- 业务主从库
- 主从库延迟问题
- 多个业务库
- 合并多个业务库 1
- 合并多个业务库 2
- 单表多租户
- 每个租户一个表
- 多库多租户
- 使用ShardingSphere
- Saga(试验)
- 关于Saga的一些认识
- 关于隔离性
- BeetlSQL Saga
- SagaMapper
- Saga 多库事务实现
- Saga 微服务 实现
- 配置 Saga Server
- Swagger
- BeetlSQL 性能
- 测试方法
- 最新
- 2021-11-21
- 2020-9-28
- Spring 快速开始
- 环境准备
- 环境搭建
- SpringBoot 快速开始
- 环境准备
- 环境搭建
- 扩展BeetlSQL3
- 完整配置
- BaseMapper定制
- 代码生成
- SQLExecutor定制
- 第三方
- MetadataManager
- JFinal集成
- ExecuteContext
- 参考ACT
- 数据库表到Java对象
- Solon
- NameConversion
- ViewType
- RowMapper
- ResultSetMapper
- AttributeConvert
- BeanConvert
- Fetch
- 代码生成
- 扩展BeetlSQL3
- BaseMapper定制
- SQLExecutor定制
- MetadataManager
- ExecuteContext
- 数据库表到Java对象
- NameConversion
- ViewType
- RowMapper
- ResultSetMapper
- AttributeConvert
- BeanConvert
- Fetch
- 代码生成
- BeetlSQL 多数据库支持
- 多库之间的不同
- 跨库支持实现
- DBStyle
- MySqlStyle 例子
- H2Style例子
- ClickHouseStyle例子
- HBaseStyle例子
- DruidStyle例子
- MetadataManager
- BeanProcessor
- 与BeetlSQL2的区别
- 使用区别