Java mysql語句動態執行、分頁和獲取總數
Java mysql語句動態執行、分頁和獲取總數
目錄
1,動態執行
使用mybatis
SheetService:
@Resource private SheetSourceMapper sheetSourceMapper; String sqlParam = "select * from account" List<Map<String,Object>> result = excuteSoureSql(sqlParam); public List<Map<String,Object>> excuteSoureSql(String sqlParam){ return sheetSourceMapper.executeSql(sqlParam); }
ReportSourceMapper:
List<Map<String, Object>> executeSql(@Param("sqlParameter") String sqlParameter);
Xml:
<select id="executeSql" resultType="map">
${sqlParameter}
</select>
這邊注意 Mapper @Param("sqlParameter") 引數名的說明
2,分頁
1,Mysql的分頁:
從零開始:
比如: branch 有四條資料:
SELECT * FROM branch LIMIT 0, 5 ;
SELECT * FROM branch LIMIT 1, 5 ;
這時候就只有3條。 確認是從零開始計算的
方式一:
SELECT * FROM account LIMIT 0, 6 ;
LIMIT 0, 6: 0 變成開始的數字, 6表示限定的條數
方式二:offset
SELECT * FROM account LIMIT 6 OFFSET 0 ;
LIMIT 6 OFFSET 0 : 6表示限定的條數, offset 偏移量,0 表示開始的數字
這個更好理解,限制返回多少條,偏移多少,即從第xx開始
通用的規律:
假設pageSize表示每頁要顯示的條數,pageNumber表示頁碼。
設定pageNumber從數字1開始,比如限定的size為10:
第一頁: page: 1, size: 10; 即: 0-9
第二頁: page: 2, size: 10; 即: 10-19
第三頁: page: 3, size: 10; 即: 20-39
方式一:
SELECT * FROM account LIMIT (pageNumber-1)*pageSize,pageSize;
方式二:
SELECT * FROM account LIMIT pageSize OFFSET (pageNumber-1)*pageSize;
如果pageNumber是從0開始,就不用減1了。看具體情況而定
3,綜合的例子:
需求:
請求引數
typeId
page 當前頁數,為空不分頁
size 每頁大小,為空不分頁
param:{} 動態查詢引數
要求:
根據typeId動態獲取要查詢的值進行動態匹配後,再執行sql
比如: SELECT * FROM employee where f_name=$param.name anddept_id=$global.DEPT_ID
實現:
先宣告引數和返回值:
引數:SheetQuery
public class SheetQuery {
private Long classId;
private Integer page;
private Integer size;
private Map<String,Object> param = new HashMap<>();
public Long getClassId() {
return classId;
}
public void setClassId(Long classId) {
this.classId = classId;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public Map<String, Object> getParam() {
return param;
}
public void setParam(Map<String, Object> param) {
this.param = param;
}
}
返回值:SheetResult
public class SheetResult {
private Long total;
private Object data;
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
正則替換類:RegUtils
public class RegUtils {
public static String getReplaceStr(String content, Map<String, Object> param)
{
String pattern = "\\$[a-zA-Z_]*\\.([a-zA-Z_]*)";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(content);
StringBuffer sb = new StringBuffer();
while (m.find())
{
String key = m.group(1);
String value = MapUtils.getString(param, key);
m.appendReplacement(sb, value == null ? "" : ("\"").concat(value).concat("\""));
}
m.appendTail(sb);
return sb.toString();
}
}
服務:SheetService
@Service
public class SheetService {
@Resource
private SheetSourceMapper sheetSourceMapper;
public SheetResult getSheetResult(SheetQuery sheetQuery){
//替換表示式的引數
// 根據typeId動態獲取,這邊就直接賦值
String sqlExpr = "SELECT * FROM employee where f_name=$param.name and dept_id=$global.DEPT_ID";
String sqlStr = RegUtils.getReplaceStr(sqlExpr, sheetQuery.getParam());
String sqlParam = sqlStr.concat(appendSqlParam(sheetQuery));
SheetResult sheetResult = new SheetResult();
List<Map<String,Object>> result = excuteSoureSql(sqlParam);
sheetResult.setTotal(getSqlTotal(sqlStr));
sheetResult.setData(result);
return sheetResult;
}
// 獲取總數
private long getSqlTotal(String sqlStr){
// 處理from可能是小寫的情況
String splitStr = "FROM";
if(!sqlStr.contains(splitStr)){
splitStr = "from";
}
String[] wheres = sqlStr.split(splitStr);
String sqlParam = "select count(*) as total from ".concat(wheres[1]);
List<Map<String,Object>> result = excuteSoureSql(sqlParam);
Map<String, Object> totalMap = ListUtils.emptyIfNull(result).stream().findFirst().orElse(new HashMap<>());
return MapUtils.getLongValue(totalMap,"total");
}
// 拼接分頁的查詢內容
private String appendSqlParam(SheetQuery sheetQuery){
Integer pageNumber = sheetQuery.getPage();
Integer pageSize = sheetQuery.getSize();
String limitStr = "";
// 如果size 為空就直接分頁
if (!Objects.isNull(pageSize)) {
// pageNumber從1開始
if(Objects.isNull(pageNumber) || pageNumber.equals(NumberUtils.INTEGER_ZERO)){
pageNumber = NumberUtils.INTEGER_ONE;
}
limitStr = " limit "+ ((pageNumber-1)*pageSize) + ", "+ pageSize;
}
return limitStr;
}
public List<Map<String,Object>> excuteSoureSql(String sqlParam){
return sheetSourceMapper.executeSql(sqlParam);
}
}
Mapper和xml
Mapper:
public interface SheetSourceMapper {
List<Map<String, Object>> executeSql(@Param("sqlParameter") String sqlParameter);
}
xml:
<select id="executeSql" resultType="map">
${sqlParameter}
</select>
測試:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SheetApplicationTests {
@Autowired
private SheetService sheetService;
@Test
public void testSheetResult() {
SheetQuery sheetQuery = new SheetQuery();
int page = 0;
int size = 10;
Map<String,Object> param = new HashMap<>();
param.put("name","Robert");
param.put("DEPT_ID",1);
sheetQuery.setPage(page);
sheetQuery.setSize(size);
sheetQuery.setParam(param);
sheetService.getSheetResult(sheetQuery);
}
}
備註: 這個是在springboot專案測試的,啟動的時候例項化service
可以從 建立spring專案 直接建一個springboot專案,再引入對應的包就行
總結:
在獲取總數的時候,也想過用一次查詢的時候,網上查了下使用:SELECT found_rows() AS recordCounts; 但是這種方式,我試驗的時候並沒有獲取到全部,就放棄了。
Mysql分頁的時候,注意從0開始。其它嘛,根據需求去寫。