Explicit Join
2/12/25About 4 minGuidemulti-table
Multi-Table Query
For multi-table queries, eq has two standards that can be mixed together
Implicit joinhas very convenient writing standards and user experience, and can automatically sense dynamic joinsExplicit joinhas the same conventional writing experience as SQL, and users can control the whole situation
API Changes
After using join operations
wherehas two overloads: the first is a single parameter, the second is two parameters. The single parameter operates on the main table, and the two parameters correspond to the table order. The same applies toselect,groupBy, etc.
leftJoin
Topic topic = easyEntityQuery
.queryable(Topic.class)
.leftJoin(BlogEntity.class, (t, t1) -> t.id().eq(t1.id()))
.where(o -> o.id().eq("3"))
.firstOrNull();
==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM t_topic t LEFT JOIN t_blog t1 ON t1.`deleted` = ? AND t.`id` = t1.`id` WHERE t.`id` = ? LIMIT 1
==> Parameters: false(Boolean),3(String)
<== Total: 1innerJoin
List<BlogEntity> blogEntities = easyEntityQuery
.queryable(Topic.class)
.innerJoin(BlogEntity.class, (t, t1) -> t.id().eq(t1.id()))
.where((t, t1) ->{
t1.title().isNotNull();
t.id().eq("3");
})
.select((t, t1) -> t1)
// .select(BlogEntity.class, (t, t1) -> t1.FETCHER.allFields())
.toList();
==> Preparing: SELECT t1.`id`,t1.`create_time`,t1.`update_time`,t1.`create_by`,t1.`update_by`,t1.`deleted`,t1.`title`,t1.`content`,t1.`url`,t1.`star`,t1.`publish_time`,t1.`score`,t1.`status`,t1.`order`,t1.`is_top`,t1.`top` FROM t_topic t INNER JOIN t_blog t1 ON t1.`deleted` = ? AND t.`id` = t1.`id` WHERE t1.`title` IS NOT NULL AND t.`id` = ?
==> Parameters: false(Boolean),3(String)
<== Total: 1Join with Multiple ON Conditions
Topic topic = easyEntityQuery
.queryable(Topic.class)
.leftJoin(BlogEntity.class, (t, t1) ->{
t.id().eq(t1.id());
t1.title().like("234");
})
.where(o -> o.id().eq("3"))
.singleOrNull();
==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic` t LEFT JOIN `t_blog` t1 ON t1.`deleted` = ? AND t.`id` = t1.`id` AND t1.`title` LIKE ? WHERE t.`id` = ?
==> Parameters: false(Boolean),%234%(String),3(String)Query Returns Partial Fields from Two Tables
//Define a return result VO
@Data
@EntityProxy
public class TopicAndBlogVO {
private String column1;
private String column2;
}
List<TopicAndBlogVO> list1 = easyEntityQuery.queryable(BlogEntity.class)
.leftJoin(Topic.class, (t_blog, t_topic) -> t_blog.id().eq(t_topic.id()))
.select((t_blog, t_topic) -> new TopicAndBlogVOProxy()
.column1().set(t_blog.title()) //column1
.column2().set(t_topic.title()) //column2
)
.toList();
-- 1st SQL data
SELECT
t.`title` AS `column1`,
t1.`title` AS `column2`
FROM
`t_blog` t
LEFT JOIN
`t_topic` t1
ON t.`id` = t1.`id`
WHERE
t.`deleted` = falseNested Join
EntityQueryable<TopicProxy, Topic> sql = easyEntityQuery
.queryable(Topic.class)
.where(o -> o.id().eq("3"));
List<BlogEntity> list = easyEntityQuery.queryable(BlogEntity.class)
.leftJoin(sql, (t_blog, t2) -> t_blog.id().eq(t2.id()))
.where((t_blog, t_topic) -> {
t_blog.id().eq("345");
t_topic.id().eq("789");
}).toList();
-- 1st SQL data
SELECT
t.`id`,
t.`create_time`,
t.`update_time`,
t.`create_by`,
t.`update_by`,
t.`deleted`,
t.`title`,
t.`content`,
t.`url`,
t.`star`,
t.`publish_time`,
t.`score`,
t.`status`,
t.`order`,
t.`is_top`,
t.`top`
FROM
`t_blog` t
LEFT JOIN
(
SELECT
t1.`id`,
t1.`stars`,
t1.`title`,
t1.`create_time`
FROM
`t_topic` t1
WHERE
t1.`id` = '3'
) t2
ON t.`id` = t2.`id`
WHERE
t.`deleted` = false
AND t.`id` = '345'
AND t2.`id` = '789'Group Join
EntityQueryable<TopicGroupTestDTOProxy, TopicGroupTestDTO> sql = easyEntityQuery
.queryable(Topic.class)
.where(o -> o.id().eq("3"))
.groupBy(o -> GroupKeys.of(o.id()))
.select(group -> new TopicGroupTestDTOProxy()
.id().set(group.key1()) //
.idCount().set(group.groupTable().id().intCount()));
List<Draft2<String, Integer>> list = easyEntityQuery.queryable(BlogEntity.class)
.leftJoin(sql, (a, b) -> a.id().eq(b.id()))
.where((b1, t2) -> {
b1.id().isNotNull();
t2.id().eq("123");
}).select((b1, t2) -> Select.DRAFT.of(
b1.id(),
t2.idCount()
)).toList();
SELECT
t.`id` AS `value1`,
t3.`id_count` AS `value2`
FROM
`t_blog` t
LEFT JOIN
(
SELECT
t1.`id` AS `id`,
COUNT(t1.`id`) AS `id_count`
FROM
`t_topic` t1
WHERE
t1.`id` = '3'
GROUP BY
t1.`id`
) t3
ON t.`id` = t3.`id`
WHERE
t.`deleted` = false
AND t.`id` IS NOT NULL
AND t3.`id` = '123'Common Table Expression
EntityQueryable<TopicGroupTestDTOProxy, TopicGroupTestDTO> sql = easyEntityQuery
.queryable(Topic.class)
.where(o -> o.id().eq("3"))
.groupBy(o -> GroupKeys.of(o.id()))
.select(group -> new TopicGroupTestDTOProxy()
.id().set(group.key1()) //
.idCount().set(group.groupTable().id().intCount()))
.toCteAs();
List<Draft2<String, Integer>> list = easyEntityQuery.queryable(BlogEntity.class)
.leftJoin(sql, (a, b) -> a.id().eq(b.id()))
.where((b1, t2) -> {
b1.id().isNotNull();
t2.id().eq("123");
}).select((b1, t2) -> Select.DRAFT.of(
b1.id(),
t2.idCount()
)).toList();
WITH `with_TopicGroupTestDTO` AS (SELECT
t1.`id` AS `id`,
COUNT(t1.`id`) AS `id_count`
FROM
`t_topic` t1
WHERE
t1.`id` = '3'
GROUP BY
t1.`id`)
SELECT
t.`id` AS `value1`,
t3.`id_count` AS `value2`
FROM
`t_blog` t
LEFT JOIN
`with_TopicGroupTestDTO` t3
ON t.`id` = t3.`id`
WHERE
t.`deleted` = false
AND t.`id` IS NOT NULL
AND t3.`id` = '123'Join 2+ Tables
//Returns Queryable3, allowing subsequent operations on this query expression, and all operations can operate on three tables
easyEntitQuery.queryable(Topic.class)
//The first join uses two parameters: parameter 1 represents the first table Topic, parameter 2 represents the second table BlogEntity. The correspondence is the parameter order
.leftJoin(BlogEntity.class, (t, t1) -> t.id().eq(t1.id()))//t represents Topic table, t1 represents BlogEntity table. The correspondence is the parameter order
//The second join uses three parameters: parameter 1 represents the first table Topic, parameter 2 represents the second table BlogEntity, parameter 3 represents the third table SysUser. The correspondence is the parameter order
.leftJoin(SysUser.class, (t, t1, t2) -> t.id().eq(t2.id()))
.where(o -> o.id().eq("123"))//Single condition where parameter is the main table Topic
//Supports single parameter or all parameters. The number of all parameters is main table + number of join tables. During chain writing, you can use then to switch operating tables
.where((t, t1, t2) -> {
t.id().eq("123");
t1.title().like("456");
t2.createTime().eq(LocalDateTime.now());
});
//Also supports single table Queryable return, but subsequent operations can only operate on a single table and cannot operate on other join tables
easyEntitQuery.queryable(Topic.class)
//The first join uses two parameters: parameter 1 represents the first table Topic, parameter 2 represents the second table BlogEntity
.leftJoin(BlogEntity.class, (t, t1) -> t.id().eq(t1.id()))
//The second join uses three parameters: parameter 1 represents the first table Topic, parameter 2 represents the second table BlogEntity, parameter 3 represents the third table SysUser
.leftJoin(SysUser.class, (t, t1, t2) -> t.id().eq(t2.id()))
.where(o -> o.id().eq("123"))//Single condition where parameter is the main table Topic
//Supports single parameter or all parameters. The number of all parameters is main table + number of join tables. During chain writing, you can use then to switch operating tables
//If where parameters are too many and you don't want to write them, you can use whereMerge, selectMerge, orderByMerge similarly
.where((t, t1, t2) -> {
t.id().eq("123");
t1.title().like("456");
t2.createTime().eq(LocalDateTime.now());
});Query All Fields from a Certain Table
List<Map<String, Object>> list1 = easyEntityQuery.queryable(BlogEntity.class)
.leftJoin(Topic.class, (b, t2) -> b.id().eq(t2.id()))
.select((b1, t2) -> {
MapProxy result = new MapProxy();
result.selectAll(b1);
result.put("xx",t2.createTime());
return result;
})
.toList();
==> Preparing: SELECT t.`id`,t.`create_time`,t.`update_time`,t.`create_by`,t.`update_by`,t.`deleted`,t.`title`,t.`content`,t.`url`,t.`star`,t.`publish_time`,t.`score`,t.`status`,t.`order`,t.`is_top`,t.`top`,t1.`create_time` AS `xx` FROM `t_blog` t LEFT JOIN `t_topic` t1 ON t.`id` = t1.`id` WHERE t.`deleted` = ?
==> Parameters: false(Boolean)
<== Time Elapsed: 6(ms)
<== Total: 100Query All Fields Ignoring One
List<Map<String, Object>> list1 = easyEntityQuery.queryable(BlogEntity.class)
.leftJoin(Topic.class, (b, t2) -> b.id().eq(t2.id()))
.select((b1, t2) -> {
MapProxy result = new MapProxy();
result.selectAll(b1);
result.selectIgnores(b1.createTime());
result.put("xx",t2.createTime());
return result;
})
.toList();
==> Preparing: SELECT t.`id`,t.`update_time`,t.`create_by`,t.`update_by`,t.`deleted`,t.`title`,t.`content`,t.`url`,t.`star`,t.`publish_time`,t.`score`,t.`status`,t.`order`,t.`is_top`,t.`top`,t1.`create_time` AS `xx` FROM `t_blog` t LEFT JOIN `t_topic` t1 ON t.`id` = t1.`id` WHERE t.`deleted` = ?
==> Parameters: false(Boolean)Contributors
xuejiaming只是我