本文目录导读:

我来为您提供一个完整的Java即席查询(Ad-hoc Query)案例,包含动态SQL构建、参数处理和结果解析。
项目结构
src/main/java/com/example/adhoc/
├── model/
│ ├── QueryRequest.java
│ └── QueryCondition.java
├── service/
│ └── AdhocQueryService.java
├── controller/
│ └── QueryController.java
└── util/
└── QueryBuilder.java
请求模型类
QueryRequest.java
package com.example.adhoc.model;
import java.util.List;
public class QueryRequest {
private String tableName;
private List<String> selectFields;
private List<QueryCondition> conditions;
private String orderBy;
private String orderDirection;
private Integer pageNum;
private Integer pageSize;
// Getters and Setters
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public List<String> getSelectFields() {
return selectFields;
}
public void setSelectFields(List<String> selectFields) {
this.selectFields = selectFields;
}
public List<QueryCondition> getConditions() {
return conditions;
}
public void setConditions(List<QueryCondition> conditions) {
this.conditions = conditions;
}
public String getOrderBy() {
return orderBy;
}
public void setOrderBy(String orderBy) {
this.orderBy = orderBy;
}
public String getOrderDirection() {
return orderDirection;
}
public void setOrderDirection(String orderDirection) {
this.orderDirection = orderDirection;
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
}
QueryCondition.java
package com.example.adhoc.model;
public class QueryCondition {
private String field;
private String operator;
private Object value;
private String logicOperator; // AND, OR
// Getters and Setters
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getLogicOperator() {
return logicOperator;
}
public void setLogicOperator(String logicOperator) {
this.logicOperator = logicOperator;
}
}
SQL构建工具类
QueryBuilder.java
package com.example.adhoc.util;
import com.example.adhoc.model.QueryCondition;
import com.example.adhoc.model.QueryRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class QueryBuilder {
/**
* 构建动态查询SQL
*/
public static QueryResult buildQuery(QueryRequest request) {
StringBuilder sql = new StringBuilder();
List<Object> params = new ArrayList<>();
// 构建SELECT部分
sql.append("SELECT ");
if (request.getSelectFields() != null && !request.getSelectFields().isEmpty()) {
sql.append(String.join(", ", request.getSelectFields()));
} else {
sql.append("*");
}
// 构建FROM部分
sql.append(" FROM ");
sql.append(validateTableName(request.getTableName()));
// 构建WHERE部分
if (request.getConditions() != null && !request.getConditions().isEmpty()) {
sql.append(" WHERE ");
buildConditions(sql, params, request.getConditions());
}
// 构建ORDER BY部分
if (request.getOrderBy() != null && !request.getOrderBy().isEmpty()) {
sql.append(" ORDER BY ").append(validateFieldName(request.getOrderBy()));
if (request.getOrderDirection() != null &&
request.getOrderDirection().equalsIgnoreCase("DESC")) {
sql.append(" DESC");
} else {
sql.append(" ASC");
}
}
// 构建分页部分
if (request.getPageNum() != null && request.getPageSize() != null) {
int offset = (request.getPageNum() - 1) * request.getPageSize();
sql.append(" LIMIT ? OFFSET ?");
params.add(request.getPageSize());
params.add(offset);
}
return new QueryResult(sql.toString(), params);
}
/**
* 构建条件部分
*/
private static void buildConditions(StringBuilder sql, List<Object> params,
List<QueryCondition> conditions) {
for (int i = 0; i < conditions.size(); i++) {
QueryCondition condition = conditions.get(i);
if (i > 0 && condition.getLogicOperator() != null) {
sql.append(" ").append(condition.getLogicOperator()).append(" ");
}
String field = validateFieldName(condition.getField());
switch (condition.getOperator().toLowerCase()) {
case "equals":
case "=":
sql.append(field).append(" = ?");
params.add(condition.getValue());
break;
case "not_equals":
case "!=":
sql.append(field).append(" != ?");
params.add(condition.getValue());
break;
case "greater_than":
case ">":
sql.append(field).append(" > ?");
params.add(condition.getValue());
break;
case "less_than":
case "<":
sql.append(field).append(" < ?");
params.add(condition.getValue());
break;
case "greater_equal":
case ">=":
sql.append(field).append(" >= ?");
params.add(condition.getValue());
break;
case "less_equal":
case "<=":
sql.append(field).append(" <= ?");
params.add(condition.getValue());
break;
case "like":
sql.append(field).append(" LIKE ?");
params.add("%" + condition.getValue() + "%");
break;
case "in":
List<?> inValues = (List<?>) condition.getValue();
String placeholders = inValues.stream()
.map(v -> {
params.add(v);
return "?";
})
.collect(Collectors.joining(", "));
sql.append(field).append(" IN (").append(placeholders).append(")");
break;
case "between":
List<?> rangeValues = (List<?>) condition.getValue();
sql.append(field).append(" BETWEEN ? AND ?");
params.add(rangeValues.get(0));
params.add(rangeValues.get(1));
break;
case "is_null":
sql.append(field).append(" IS NULL");
break;
case "is_not_null":
sql.append(field).append(" IS NOT NULL");
break;
default:
throw new IllegalArgumentException("Unsupported operator: " + condition.getOperator());
}
}
}
/**
* 验证表名防止SQL注入
*/
private static String validateTableName(String tableName) {
if (!tableName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$")) {
throw new IllegalArgumentException("Invalid table name: " + tableName);
}
return tableName;
}
/**
* 验证字段名防止SQL注入
*/
private static String validateFieldName(String fieldName) {
if (!fieldName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$")) {
throw new IllegalArgumentException("Invalid field name: " + fieldName);
}
return fieldName;
}
/**
* 查询结果内部类
*/
public static class QueryResult {
private String sql;
private List<Object> params;
public QueryResult(String sql, List<Object> params) {
this.sql = sql;
this.params = params;
}
public String getSql() {
return sql;
}
public List<Object> getParams() {
return params;
}
}
}
服务层实现
AdhocQueryService.java
package com.example.adhoc.service;
import com.example.adhoc.model.QueryRequest;
import com.example.adhoc.util.QueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public class AdhocQueryService {
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 执行即席查询
*/
public List<Map<String, Object>> executeQuery(QueryRequest request) {
// 构建SQL和参数
QueryBuilder.QueryResult queryResult = QueryBuilder.buildQuery(request);
// 记录查询日志(可选)
logQuery(queryResult.getSql(), queryResult.getParams());
// 执行查询
List<Map<String, Object>> result = jdbcTemplate.queryForList(
queryResult.getSql(),
queryResult.getParams().toArray()
);
return result;
}
/**
* 获取查询记录数
*/
public long countQuery(QueryRequest request) {
QueryBuilder.QueryResult queryResult = QueryBuilder.buildQuery(request);
String countSql = queryResult.getSql().replaceFirst(
"SELECT .* FROM",
"SELECT COUNT(*) FROM"
);
// 移除ORDER BY和LIMIT部分
countSql = countSql.replaceAll("ORDER BY .*", "");
countSql = countSql.replaceAll("LIMIT .*", "");
Long count = jdbcTemplate.queryForObject(
countSql,
queryResult.getParams().toArray(),
Long.class
);
return count != null ? count : 0L;
}
/**
* 记录查询日志
*/
private void logQuery(String sql, List<Object> params) {
System.out.println("Executing query: " + sql);
System.out.println("With parameters: " + params);
}
}
控制器实现
QueryController.java
package com.example.adhoc.controller;
import com.example.adhoc.model.QueryRequest;
import com.example.adhoc.service.AdhocQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/adhoc")
public class QueryController {
@Autowired
private AdhocQueryService adhocQueryService;
/**
* 执行即席查询
*/
@PostMapping("/query")
public ResponseEntity<Map<String, Object>> executeQuery(@RequestBody QueryRequest request) {
try {
// 执行查询
List<Map<String, Object>> data = adhocQueryService.executeQuery(request);
// 获取总记录数
long total = adhocQueryService.countQuery(request);
// 构建响应
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("data", data);
response.put("total", total);
response.put("pageNum", request.getPageNum());
response.put("pageSize", request.getPageSize());
return ResponseEntity.ok(response);
} catch (Exception e) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("success", false);
errorResponse.put("message", "Query execution failed: " + e.getMessage());
return ResponseEntity.badRequest().body(errorResponse);
}
}
/**
* 获取元数据信息
*/
@GetMapping("/metadata/{tableName}")
public ResponseEntity<Map<String, Object>> getTableMetadata(@PathVariable String tableName) {
// 这里可以返回表的元数据信息,如字段列表、类型等
Map<String, Object> metadata = new HashMap<>();
metadata.put("tableName", tableName);
return ResponseEntity.ok(metadata);
}
}
使用示例
测试代码
package com.example.adhoc;
import com.example.adhoc.model.QueryCondition;
import com.example.adhoc.model.QueryRequest;
import com.example.adhoc.util.QueryBuilder;
import java.util.ArrayList;
import java.util.List;
public class AdhocQueryExample {
public static void main(String[] args) {
// 创建查询请求
QueryRequest request = new QueryRequest();
request.setTableName("employees");
// 设置查询字段
List<String> fields = new ArrayList<>();
fields.add("id");
fields.add("name");
fields.add("department");
fields.add("salary");
request.setSelectFields(fields);
// 设置查询条件
List<QueryCondition> conditions = new ArrayList<>();
QueryCondition cond1 = new QueryCondition();
cond1.setField("department");
cond1.setOperator("equals");
cond1.setValue("IT");
cond1.setLogicOperator("AND");
QueryCondition cond2 = new QueryCondition();
cond2.setField("salary");
cond2.setOperator("greater_than");
cond2.setValue(50000);
cond2.setLogicOperator("AND");
conditions.add(cond1);
conditions.add(cond2);
request.setConditions(conditions);
// 设置排序
request.setOrderBy("salary");
request.setOrderDirection("DESC");
// 设置分页
request.setPageNum(1);
request.setPageSize(10);
// 构建查询
QueryBuilder.QueryResult result = QueryBuilder.buildQuery(request);
System.out.println("Generated SQL: " + result.getSql());
System.out.println("Parameters: " + result.getParams());
}
}
JSON请求示例
发送的JSON请求
{
"tableName": "employees",
"selectFields": ["id", "name", "department", "salary", "hire_date"],
"conditions": [
{
"field": "department",
"operator": "in",
"value": ["IT", "HR", "Finance"],
"logicOperator": "AND"
},
{
"field": "salary",
"operator": "between",
"value": [30000, 100000],
"logicOperator": "AND"
},
{
"field": "status",
"operator": "equals",
"value": "ACTIVE",
"logicOperator": "AND"
}
],
"orderBy": "salary",
"orderDirection": "DESC",
"pageNum": 1,
"pageSize": 20
}
关键特性
- 动态SQL构建:根据请求参数动态生成SQL语句
- SQL注入防护:通过字段名和表名校验防止注入
- 参数化查询:使用PreparedStatement参数,避免SQL注入
- 多种运算符支持:=, !=, >, <, >=, <=, LIKE, IN, BETWEEN, IS NULL等
- 分页支持:内置分页功能
- 排序支持:支持多字段排序
- 逻辑运算符:支持AND/OR组合条件
这个即席查询系统可以灵活地处理各种查询需求,同时保证了安全性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播