java/kotlin high performance lightweight solution for jdbc query,support oltp and olap query,一款java下面支持强类型、轻量级、高性能的ORM,致力于解决jdbc查询,拥有对象模型筛选、隐式子查询、隐式join
Implicit Join - Automatically implements join queries for OneToOne and ManyToOne relationships, supporting filtering, sorting, and result fetching
Implicit Subquery - Automatically handles subqueries for OneToMany and ManyToMany relationships, supporting filtering, sorting, and aggregate function results
Implicit Grouping - Optimizes and merges multiple subqueries into grouped queries for OneToMany and ManyToMany relationships, supporting filtering, sorting, and aggregate functions
Implicit Partition Grouping - Enables first/Nth element operations for OneToMany and ManyToMany relationships, supporting filtering, sorting, and aggregate function results
Implicit CASE WHEN Expression - property.aggregate.filter() syntax, e.g., o.age().sum().filter(()->o.name().like(“123”))
First, let’s look at a complete single-table query example involving filtering, aggregation, aggregate filtering, projection, and sorting.
List<Draft3<String, Integer, LocalDateTime>> myBlog = easyEntityQuery.queryable(BlogEntity.class)
.where(b -> {
b.content().like("my blog");
})
.groupBy(b -> GroupKeys.of(b.title()))
.having(group -> {
group.groupTable().star().sum().lt(10);
})
// The select statement will wrap previous expressions as an inline view (t1 table)
// If no subsequent chained operations exist, it will expand directly
.select(group -> Select.DRAFT.of(
group.key1(), // value1
group.groupTable().star().sum().asAnyType(Integer.class), // value2
group.groupTable().createTime().max() // value3
))
// If no orderBy is added, no inline view (t1 table) SQL will be generated
// Because orderBy operates on the previous select results
.orderBy(group -> group.value3().desc())
.limit(2, 2) // Apply result pagination
.toList();
-- 第1条sql数据
SELECT
t1.`value1` AS `value1`,
t1.`value2` AS `value2`,
t1.`value3` AS `value3`
FROM
(SELECT
t.`title` AS `value1`,
SUM(t.`star`) AS `value2`,
MAX(t.`create_time`) AS `value3`
FROM
`t_blog` t
WHERE
t.`deleted` = false
AND t.`content` LIKE '%my blog%'
GROUP BY
t.`title`
HAVING
SUM(t.`star`) < 10) t1
ORDER BY
t1.`value3` DESC LIMIT 2,2
Db Support
数据库名称
包名
springboot配置
solon配置
MySQL
sql-mysql
mysql
mysql
Oracle
sql-oracle
oracle
oracle
PostgreSQL
sql-pgsql
pgsql
pgsql
SqlServer
sql-mssql
mssql
mssql
SqlServer RowNumber
sql-mssql
mssql_row_number
mssql_row_number
H2
sql-h2
h2
h2
SQLite
sql-sqlite
sqlite
sqlite
ClickHouse
sql-clickhouse
clickhouse
clickhouse
达梦dameng
sql-dameng
dameng
dameng
人大金仓KingbaseES
sql-kingbase-es
kingbase_es
kingbase_es
高斯
sql-gauss-db
gauss-db
gauss-db
duckdb
sql-duckdb
duckdb
duckdb
DB2
sql-db2
db2
db2
Dependency
entity use @EntityProxy or @EntityFileProxy annotation then build project apt will auto generate java code for proxy
easy-query 🚀 is a high-performance, lightweight, and versatile Java/Kotlin object query ORM framework that supports database sharding and read-write separation.
Overview
easy-query is a dependency-free JAVA/Kotlin ORM framework, extremely lightweight, with high performance. It supports single table queries, multi-table queries, union, subqueries, pagination, dynamic table names, VO object query returns, logical deletion, global interception, database column encryption (supporting high-performance LIKE queries), data tracking for differential updates, optimistic locking, multi-tenancy, automatic database sharding, automatic table sharding, read-write separation, and supports full-featured external extension customization of the framework, with strong-typed expressions.
List<Draft3<String, Integer, LocalDateTime>> myBlog = easyEntityQuery.queryable(BlogEntity.class)
.where(b -> {
b.content().like("my blog");
//other conditions
//b.id().eq("123");
})
.groupBy(b -> GroupKeys.of(b.title()))
.having(group -> {
group.groupTable().star().sum().lt(10);
})
// The select clause will wrap the select and previous expressions into a nested view (t1 table).
// If there are no subsequent chained operations, it will expand directly; otherwise, it will be represented as a nested view (t1 table).
.select(group -> Select.DRAFT.of(
group.key1(),//value1
group.groupTable().star().sum().asAnyType(Integer.class),//value2
group.groupTable().createTime().max()//value3
))
// If orderBy is not added, no nested view (t1 table) SQL will be generated
// because orderBy operates on the results of the preceding select
.orderBy(group -> group.value3().desc())
// Apply result limit restrictions
limit(2,2)
.toList();
SELECT
t1.`value1` AS `value1`,
t1.`value2` AS `value2`,
t1.`value3` AS `value3`
FROM
(SELECT
t.`title` AS `value1`,
SUM(t.`star`) AS `value2`,
MAX(t.`create_time`) AS `value3`
FROM
`t_blog` t
WHERE
t.`deleted` = false
AND t.`content` LIKE '%my blog%'
GROUP BY
t.`title`
HAVING
SUM(t.`star`) < 10) t1
ORDER BY
t1.`value3` DESC LIMIT 2,2
Installation
Here is the usage guide for spring-boot environment and console mode.
<properties><easy-query.version>last-version</easy-query.version></properties><dependency><groupId>com.easy-query</groupId><artifactId>sql-api-proxy</artifactId><version>${easy-query.version}</version></dependency><!-- required data base dialect --><dependency><groupId>com.easy-query</groupId><artifactId>sql-mysql</artifactId><version>${easy-query.version}</version></dependency>
==> 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` = ? AND t.`title` = ? LIMIT 1
==> Parameters: false(Boolean),3(String),4(String)
<== Time Elapsed: 2(ms)
<== Total: 1
==> Preparing: SELECT COUNT(*) FROM (SELECT t1.`id` AS `id`,SUM(t1.`score`) AS `score` FROM `t_topic` t INNER JOIN `t_blog` t1 ON t1.`deleted` = ? AND t.`id` = t1.`id` WHERE t1.`title` IS NOT NULL GROUP BY t1.`id`) t2
==> Parameters: false(Boolean)
<== Time Elapsed: 4(ms)
<== Total: 1
==> Preparing: SELECT t1.`id` AS `id`,SUM(t1.`score`) AS `score` FROM `t_topic` t INNER JOIN `t_blog` t1 ON t1.`deleted` = ? AND t.`id` = t1.`id` WHERE t1.`title` IS NOT NULL GROUP BY t1.`id` LIMIT 20
==> Parameters: false(Boolean)
<== Time Elapsed: 2(ms)
<== Total: 20
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 `aa_bb_cc` t WHERE t.`deleted` = ? AND t.`id` = ?
Insert
Topic topic = new Topic();
topic.setId(String.valueOf(0));
topic.setStars(100);
topic.setTitle("标题0");
topic.setCreateTime(LocalDateTime.now().plusDays(i));
long rows = easyEntityQuery.insertable(topic).executeRows();
==> Preparing: SELECT t1.`id`,t1.`stars`,t1.`title`,t1.`create_time` FROM (SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic` t UNION SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic` t UNION SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic` t) t1 WHERE t1.`id` = ?
==> Parameters: 123321(String)
<== Time Elapsed: 19(ms)
<== Total: 0
==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic` t WHERE t.`id` IN (SELECT t1.`id` FROM `t_blog` t1 WHERE t1.`deleted` = ? AND t1.`id` = ?)
==> Parameters: false(Boolean),1(String)
<== Time Elapsed: 6(ms)
<== Total: 1
==> Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic` t WHERE EXISTS (SELECT 1 FROM `t_blog` t1 WHERE t1.`deleted` = ? AND t1.`id` = ? AND t1.`id` = t.`id`)
==> Parameters: false(Boolean),1(String)
<== Time Elapsed: 2(ms)
<== Total: 1
LocalDateTime beginTime = LocalDateTime.of(2021, 1, 1, 1, 1);
LocalDateTime endTime = LocalDateTime.of(2021, 5, 2, 1, 1);
Duration between = Duration.between(beginTime, endTime);
long days = between.toDays();
List<TopicShardingTime> list = easyQuery.queryable(TopicShardingTime.class)
.where(o->o.rangeClosed(TopicShardingTime::getCreateTime,beginTime,endTime))
.orderByAsc(o -> o.column(TopicShardingTime::getCreateTime))
.toList();
==> SHARDING_EXECUTOR_2, name:ds2020, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_time_202101` t WHERE t.`create_time` >= ? AND t.`create_time` <= ? ORDER BY t.`create_time` ASC
==> SHARDING_EXECUTOR_3, name:ds2020, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_time_202102` t WHERE t.`create_time` >= ? AND t.`create_time` <= ? ORDER BY t.`create_time` ASC
==> SHARDING_EXECUTOR_2, name:ds2020, Parameters: 2021-01-01T01:01(LocalDateTime),2021-05-02T01:01(LocalDateTime)
==> SHARDING_EXECUTOR_3, name:ds2020, Parameters: 2021-01-01T01:01(LocalDateTime),2021-05-02T01:01(LocalDateTime)
<== SHARDING_EXECUTOR_3, name:ds2020, Time Elapsed: 3(ms)
<== SHARDING_EXECUTOR_2, name:ds2020, Time Elapsed: 3(ms)
==> SHARDING_EXECUTOR_2, name:ds2020, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_time_202103` t WHERE t.`create_time` >= ? AND t.`create_time` <= ? ORDER BY t.`create_time` ASC
==> SHARDING_EXECUTOR_3, name:ds2020, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_time_202104` t WHERE t.`create_time` >= ? AND t.`create_time` <= ? ORDER BY t.`create_time` ASC
==> SHARDING_EXECUTOR_2, name:ds2020, Parameters: 2021-01-01T01:01(LocalDateTime),2021-05-02T01:01(LocalDateTime)
==> SHARDING_EXECUTOR_3, name:ds2020, Parameters: 2021-01-01T01:01(LocalDateTime),2021-05-02T01:01(LocalDateTime)
<== SHARDING_EXECUTOR_3, name:ds2020, Time Elapsed: 2(ms)
<== SHARDING_EXECUTOR_2, name:ds2020, Time Elapsed: 2(ms)
==> main, name:ds2020, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_time_202105` t WHERE t.`create_time` >= ? AND t.`create_time` <= ? ORDER BY t.`create_time` ASC
==> main, name:ds2020, Parameters: 2021-01-01T01:01(LocalDateTime),2021-05-02T01:01(LocalDateTime)
<== main, name:ds2020, Time Elapsed: 2(ms)
<== Total: 122
==> SHARDING_EXECUTOR_23, name:ds2022, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_ds` t ORDER BY t.`create_time` ASC LIMIT 33
==> SHARDING_EXECUTOR_11, name:ds2021, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_ds` t ORDER BY t.`create_time` ASC LIMIT 33
==> SHARDING_EXECUTOR_2, name:ds2020, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_ds` t ORDER BY t.`create_time` ASC LIMIT 33
==> SHARDING_EXECUTOR_4, name:ds2023, Preparing: SELECT t.`id`,t.`stars`,t.`title`,t.`create_time` FROM `t_topic_sharding_ds` t ORDER BY t.`create_time` ASC LIMIT 33
<== SHARDING_EXECUTOR_4, name:ds2023, Time Elapsed: 4(ms)
<== SHARDING_EXECUTOR_23, name:ds2022, Time Elapsed: 4(ms)
<== SHARDING_EXECUTOR_2, name:ds2020, Time Elapsed: 4(ms)
<== SHARDING_EXECUTOR_11, name:ds2021, Time Elapsed: 6(ms)
<== Total: 33
评论