# entityqueryable
**Repository Path**: ccait/entityqueryable
## Basic Information
- **Project Name**: entityqueryable
- **Description**: EntityQueryable是Java开如平台下轻量级ORM, 支持多数据库映射操作的开源ORM库, 兼容mybatis配置,支持联表查询、异步批量插入、更新、删除,内置阿里的Druid数据库连接池支持数据库mysql/mariadb/sqlserver/sqlite/oracle/postgresql,以及集成了rxjava2-jdbc(默认不开启),可以支持响应式的异步非阻塞IO操作数据;
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 1
- **Created**: 2022-06-30
- **Last Updated**: 2025-11-21
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[](https://www.jetbrains.com/idea/)
**EntityQueryable 是一个轻量级的 ORM 库**
(EntityQueryable is a Micro ORM library)
请作者喝饮料
EntityQueryable 是面向 Java 平台的轻量级 ORM:以 fluent API 构建 SQL,利用方法返回类型在编译期约束链式调用顺序(如 `form → where → and/or → group → select`),无需 AST 解析即可确保语义合法;同时兼容 MyBatis 风格 XML 作为复杂查询的补充,两种方式共用同一 `QueryableAction` 执行管线。内置多数据源映射、联表查询、异步批量写、Druid 连接池与可选 RxJava2-JDBC(默认关闭),覆盖 mysql/mariadb/sqlserver/sqlite/oracle/postgresql 等主流数据库,并提供 SQL/PreparedSql 预览、可插拔诊断追踪、元数据探查、动态数据源与热切换支持,既可走链式 DSL,也能按需回退到原生 SQL 与 XML Mapper,交付体验从调试到运维都保持轻盈可控。
### **如何开始**
How to start?
#### **1.先下载数据库驱动并创建 `db-config.xml`**
Download database driver first, then build a "db-config.xml"
```xml
```
#### **或者在 `/conf/application.yml` 中添加配置**
Or add config to /conf/application.yml
```yaml
# entityQueryable config
entity:
datasource:
activated: test #activated datasource
#configFile: db-config.xml #db-config path
environments:
test:
default: true
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=CTT
username: root
password: 123456
```
**诊断日志开关 / Diagnostics toggle**
```yaml
entity:
query:
diagnostics:
enabled: true # 设置为 false 可完全关闭 QueryDiagnostics 采集
```
若不配置该项,默认开启;当设置为 `false` 时,`QueryDiagnostics.start(...)` 将返回 no-op trace,不再记录 SQL、耗时或缓存命中统计。
> Default is `true`; set to `false` to fully disable query diagnostics so no UUID/timing/counter updates are produced.
#### **2.通过 Maven 引入依赖**
Add the jar package by Maven
```xml
4.0.0
entity-orm
entity.queryable
1.0.0-SNAPSHOT
gitee
https://gitee.com/linlurui/entityqueryable/raw/v1.0
always
true
always
true
ignore
entity-orm
entity.queryable
1.0.0-SNAPSHOT
```
#### **3.让实体继承 `entity.query.Queryable` 基类**
Inherit base class "entity.query.Queryable" in your entity
```java
package cn.entity;
import java.util.Date;
import entity.query.Queryable;
import entity.query.annotation.AutoIncrement;
import entity.query.annotation.DBConfig;
import entity.query.annotation.Fieldname;
import entity.query.annotation.PrimaryKey;
import entity.query.annotation.Tablename;
@DBConfig(id="mysql")
@Tablename(value="user")
public class User extends Queryable {
public User() {
super();
}
@PrimaryKey
@AutoIncrement
private int id;
public int getId()
{
return id;
}
public void setId(int value)
{
id = value;
}
private String name;
public String getName()
{
return name;
}
...
@Fieldname(value="create_on")
private Date createOn;
public Date getCreateOn()
{
return createOn;
}
public void setCreateOn(Date value)
{
createOn = value;
}
}
```
### 核心 API 速查
| 使用场景 | 关键方法 | 说明 |
| --- | --- | --- |
| 基础 CRUD | `insert` / `update` / `update(String... exp)` / `delete` | 实体方法自动按注解映射字段,`update(String...)` 允许手写 set 语句 |
| 条件查询 | `where` / `and` / `or` / `select` / `orderby` / `groupby` | 与 MyBatis 语法一致,支持 `#{field}` 占位符 |
| 执行控制 | `query` / `query(Class)` / `query(skip, top)` / `first` / `top` / `exist` / `count` | 同步查询、分页、单条与布尔判断 |
| 组合查询 | `join` / `on` / `union` / `from(select, alias)` / `as` | 支持联表、子查询、UNION 与表别名 |
| 静态链 | `Queryable.from(User.class, "u")` | 直接通过实体 class 构建查询,无需 new |
| SQL预览 | `toString(CommandMode)` / `toString(mode, DBType)` / `getPreparedSql` / `toPreparedSql` | 输出最终 SQL 或 PreparedSql(含参数) |
| 响应式 | `asyncQuery` / `asyncFirst` / `asyncCount` / `asyncInsert` 等 | 基于 RxJava2,返回 `Flowable` / `Maybe` / `Single` |
| 批量操作 | `batchInsert` / `batchUpdate` / `batchDelete` | 复用同一 parser 批量执行 |
| 原生 SQL | `QueryableAction.executeSql(...)` | 支持默认数据源、指定数据源 ID 或自定义 `DataSource` |
| XML SQL | `QueryableAction.executeSqlFromXml(...)` | 读取配置目录下的 XML Mapper,兼容常见 MyBatis 标签但无需引入 MyBatis |
| 元数据 | `getTables` / `getColumns` / `getPrimaryKey` / `selectNow` | 查询库表、字段及数据库时间 |
###### 下面章节会逐一对应每个方法族的典型写法,可直接复制调试。
### **如何使用 EntityQueryable 访问数据库**
How to use EntityQueryable to access database
##### **1.如何插入数据**
How to insert data
```java
@RequestMapping(value="/eqinsert", method=RequestMethod.GET)
public ModelAndView add() {
User user = new User();
user.setName("linlurui");
user.setAccount("linlurui");
user.setPassword("******");
user.setMobile("13000000007");
user.setCreateOn(new Date());
user.insert();
return new ModelAndView("hello", "message", "Insert data by entity queryable");
}
```
#### **2.如何更新数据**
How to update data?
```java
@RequestMapping(value="/equpdate", method=RequestMethod.GET)
public ModelAndView edit() {
User user = new User();
user.setAccount("linlurui");
user.setName("linlurui");
user.setMobile("13300000000");
user.where("account=#{account}").update("name=#{name}, mobile=#{mobile}");
return new ModelAndView("hello", "message", "Update data by entity queryable");
}
```
#### **3.如何删除数据**
How to delete data
```java
@RequestMapping(value="/eqdelete", method=RequestMethod.GET)
public ModelAndView remove() {
User user = new User();
user.setAccount("linlurui");
user.where("account=#{account}").delete();
return new ModelAndView("hello", "message", "Delete data by entity queryable");
}
```
#### **4.如何查询数据**
How to query data
```java
@RequestMapping(value="/eqselect", method=RequestMethod.GET)
public ModelAndView query() {
User user = new User();
user.setName("linlurui");
List list = user
.where("name=#{name}")
.where(Condition.OR, "account=#{name}")
.orderby("id")
.query();
return new ModelAndView("data", "list", list);
}
```
#### **5.如何进行联表查询**
How to join table
```java
@RequestMapping(value="/eqjoin", method=RequestMethod.GET)
public ModelAndView joinQuery() {
User user = new User();
Auth auth = new Auth();
user.setName("linlurui");
List list = user
.where("account=#{name}")
.join(JoinMode.Inner, auth, "a")
.on("[user].[id]=[a].[user_id]")
.query();
return new ModelAndView("data", "list", list);
}
```
#### **6.如何进行 UNION 合并**
How to union data
```java
@RequestMapping(value="/equnion", method=RequestMethod.GET)
public ModelAndView unionQuery() {
User user = new User();
Auth auth = new Auth();
user.setName("linlurui");
List list = user
.where("name=#{name}")
.select("[id] AS [user_id]")
.union(auth.select("[user_id]"))
.query();
return new ModelAndView("data2", "list", list);
}
```
#### **7.如何返回自定义结果**
How to return custom result
```java
@RequestMapping(value="/eqmyresult", method=RequestMethod.GET)
public ModelAndView myresult() {
User user = new User();
user.setName("linlurui");
List list = user
.where("1=1")
.select("COUNT(Id) AS count, SUM(Id) AS sum, MAX(Id) AS max")
.query(MyResult.class);
return new ModelAndView("data3", "list", list);
}
```
#### **8.如何查询首条数据**
How to query first
```java
@RequestMapping(value="/eqfirst", method=RequestMethod.GET)
public ModelAndView first() {
User user = new User();
user.setName("linlurui");
List list = new ArrayList();
User entity = user
.where("name=#{name}")
.or("account=#{name}")
.orderby("id")
.first();
list.add(entity);
return new ModelAndView("data", "list", list);
}
```
#### **9.如何查询前 N 条数据**
How to query top data
```java
@RequestMapping(value="/eqtop", method=RequestMethod.GET)
public ModelAndView top() {
User user = new User();
user.setName("linlurui");
List list = user
.where("name=#{name}")
.or("account=#{name}")
.orderby("id")
.top(5);
return new ModelAndView("data", "list", list);
}
```
#### **10.如何判断记录是否存在**
How to check exist
```java
@RequestMapping(value="/eqexist", method=RequestMethod.GET)
public ModelAndView exist() {
User user = new User();
user.setName("linlurui");
List list = new ArrayList();
Boolean exist = user
.where("name=#{name}")
.where(Condition.OR, "account=#{name}")
.exist();
list.add(exist);
return new ModelAndView("dataexist", "list", list);
}
```
#### **11.如何统计数量**
How to count data
```java
@RequestMapping(value="/eqcount", method=RequestMethod.GET)
public ModelAndView count() {
User user = new User();
user.setName("linlurui");
List list = new ArrayList();
Number count = user
.where("name=#{name}")
.where(Condition.OR, "account=#{name}")
.count();
list.add(count);
return new ModelAndView("datacount", "list", list);
}
```
#### **12.如何分页查询**
How to query by page
```java
@RequestMapping(value="/eqpage", method=RequestMethod.GET)
public ModelAndView page() {
int pageIndex = 1;
int pageSize = 20;
User user = new User();
user.setName("linlurui");
List list = user
.where("name=#{name}")
.where(Condition.OR, "account=#{name}")
.query(pageIndex * pageSize - pageSize, pageSize);
return new ModelAndView("data", "list", list);
}
```
#### **13.如何直接从实体查询**
select from entity
```java
@RequestMapping(value="/eqfrom", method=RequestMethod.GET)
public ModelAndView from() {
User user = new User();
user.setName("linlurui");
Select s = user
.where("name=#{name}")
.where(Condition.OR, "account=#{name}")
.select("account,name");
List list = user.from(s, "a").where("name='linlurui'").query();
return new ModelAndView("data", "list", list);
}
```
#### **14.如何使用静态查询链**
Static query chain (new)
```java
// 1. 普通查询
List list = Queryable.from(User.class, "user")
.where("id=#{id}", 2)
.and("parent_id>0")
.or("parent_id=#{parentId}", -1)
.orderby("id DESC")
.query();
// 2. 查询首条
User first = Queryable.from(User.class, "user")
.where("id=#{id}", 2)
.and("parent_id>0")
.first();
// 3. 只生成 SQL
String mysqlSql = Queryable.from(User.class, "user")
.where("id=#{id}", 2)
.select("id", "name")
.toString(CommandMode.Select);
```
> 静态链式调用内部会自动实例化实体并为 `#{field}` 占位符注入值, 可直接复用 `query/first/exist/top/count` 等所有查询能力。
#### **15.如何执行原生 SQL**
How to run raw SQL (executeSql)
```java
// 1. 使用默认/实体推断数据源
List users = QueryableAction.executeSql(
"SELECT * FROM user WHERE id > ?",
User.class,
100
);
// 2. 指定数据源 ID
List shUsers = QueryableAction.executeSql(
"shard_mysql",
"SELECT * FROM user WHERE region = ?",
User.class,
"sh"
);
// 3. 自定义 DataSource(例如多租户动态构建)
DataSource tenantDs = buildTenantDataSource();
List