mysql动态sql是什么,mysql中动态sql的一次实际应用
一、前言
本次實(shí)際應(yīng)用中,使用到了如下幾個(gè)要點(diǎn):
mysql的動(dòng)態(tài)建表;
mysql的多表插入;
mysql的多表更新;
mysql的多表刪除;
二、使用場(chǎng)景
2.1 動(dòng)態(tài)建表
要求建立多個(gè)表,例如電壓、電流等表,這些表的字段是完全一樣的,只有表名不一樣,那么我們就可以把表名等字段放在基準(zhǔn)表中,然后從基準(zhǔn)表中獲得所有的表名字段,以list的形式傳入mybatis中,進(jìn)行循環(huán)動(dòng)態(tài)拼接創(chuàng)建。
void createTelemetryTable(List list);
復(fù)制代碼
CREATE TABLE if not exists `${item}` (
sys_id bigint NOT NULL,
mpnt_id bigint NOT NULL,
data_date DATE NOT NULL,
data_point int NOT NULL,
data_item_id bigint NOT NULL,
val DECIMAL(10,2) NOT NULL,
KEY `${item}_sys_id` (`sys_id`),
KEY `${item}_mpnt_id` (`mpnt_id`),
KEY `${item}_data_date` (`data_date`),
KEY `${item}_data_point` (`data_point`),
KEY `${item}_data_item_id` (`data_item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
復(fù)制代碼
部分截圖如下:
2.2 多表批量插入
應(yīng)用場(chǎng)景就是實(shí)際使用中,拿到一批數(shù)據(jù),然后這批數(shù)據(jù)對(duì)應(yīng)到多個(gè)不同表,那么最好的方式就是通過map映射,例如:Map>。那么這時(shí)候就需要自己來寫動(dòng)態(tài)sql了。
其中需要了解的兩個(gè)mybatis注解就是:@Insert 和@InsertProvider 都是用來在實(shí)體類的Mapper類中的注解保存方法的SQL語(yǔ)句。區(qū)別就是@Insert是直接配置sql語(yǔ)句,而@InsertProvider則是通過sql工廠類及對(duì)應(yīng)的方法生產(chǎn)sql語(yǔ)句,這種方法的好處就是可以寫出更為復(fù)雜的sql。
@InsertProvider的注解方式為:
@InsertProvider(type = BaseMapperEnhanceImpl.class,method = "insertCalBatchTable")
void insertBatch(@Param("tables") Map> ycTable);
復(fù)制代碼
說明:type指明sql工廠類,method是工廠類里對(duì)應(yīng)的方法。
多表批量插入的代碼如下:
/**
* 計(jì)算服務(wù)的批量插入:參數(shù)名稱必須傳 list ,例 @Param("list")
**/
public String insertCalBatchTable(Map map){
Map table = (Map) map.get("tables");
String sql = table.keySet().stream().map(i -> insertBatch((Collection) table.get(i),i)).collect(Collectors.joining());
return sql;
}
/**
* 計(jì)算服務(wù)批量插入
**/
private String insertBatch(Collection col,String table){
if(CollectionUtil.isEmpty(col)){
throw new RuntimeException("saveAll parameter size is zero or null");
}
Object t = null;
ArrayList list;
if(col instanceof List){
list = (ArrayList) col;
t = list.get(0);
}else{
throw new RuntimeException("Only list or set types are allowed");
}
Class cls = t.getClass();
Field[] fields = cls.getDeclaredFields();
StringBuffer sql = new StringBuffer();
sql.append("INSERT INTO `"+table+"` ");
sql.append("(");
for (Field field :fields) {
field.setAccessible(true);
TableField tableField = field.getAnnotation(TableField.class);
if(ObjectUtil.isNotNull(tableField)){
sql.append(tableField.value()+",");
}
}
sql.delete(sql.length()-1,sql.length());
sql.append(") VALUES ");
for (int i = 0; i < list.size(); i++) {
sql.append(list.get(i).toString());
if (i < list.size() - 1) {
sql.append(",");
}
}
sql.append(";");
return sql.toString();
}
復(fù)制代碼
說明:可以看下這個(gè)插入對(duì)象的實(shí)體類:需要在待插入的字段上加上@TableField注解,然后通過重寫toString來獲取sql的插入語(yǔ)句:然后sql會(huì)自動(dòng)把這些值給拼接上去。最后通過這個(gè)注解將這條動(dòng)態(tài)語(yǔ)句插入到數(shù)據(jù)庫(kù)中。
@Override
public String toString() {
return "("+this.getSysId()+","+this.getMpntId()+",'"+this.getDataDate()+"',"+this.getDataPoint()+","+ this.getDataItemId()+","+ this.getVal()+")";
}
復(fù)制代碼
2.3 多表批量更新
應(yīng)用場(chǎng)景與上同理,對(duì)多個(gè)表進(jìn)行批量更新。傳參形式依舊為如下:Map>。同理,在實(shí)體類中寫了個(gè)獲取update sql的方法:
@Data
@NoArgsConstructor
public class CalcDateCurve {
@TableField(value = "sys_id")
private long sysId;
@TableField(value = "mpnt_id")
private long mpntId;
@TableField(value = "data_date")
private Date dataDate;
@TableField(value = "data_point")
private Integer dataPoint;
@TableField(value = "data_item_id")
private long dataItemId;
@TableField(value = "val")
private BigDecimal val;
private String key;
@Override
public String toString() {
return "("+this.getSysId()+","+this.getMpntId()+",'"+this.getDataDate()+"',"+this.getDataPoint()+","+ this.getDataItemId()+","+ this.getVal()+")";
}
public String updateSql() {
return "val ="+this.getVal()+" where sys_id="+this.getSysId() +" and mpnt_id="+this.getMpntId() +" and data_date = '"+this.getDataDate()+"' and data_point="+this.getDataPoint()+" and data_item_id="+this.getDataItemId() ;
}
}
復(fù)制代碼
mapper 層:
@UpdateProvider(type = BaseMapperEnhanceImpl.class,method = "updateCalBatchTable")
void updateBatch(@Param("tables") Map> ycTable);
復(fù)制代碼
工廠類方法:
/**
* 計(jì)算服務(wù)的批量更新
**/
private String updateBatch(Collection col,String table) {
if(CollectionUtil.isEmpty(col)){
throw new RuntimeException("saveAll parameter size is zero or null");
}
Object t = null;
ArrayList list;
if(col instanceof List){
list = (ArrayList) col;
t = list.get(0);
}else{
throw new RuntimeException("Only list or set types are allowed");
}
Class cls = t.getClass();
Field[] fields = cls.getDeclaredFields();
StringBuffer sql = new StringBuffer();
for (int i = 0; i < list.size(); i++) {
try {
sql.append("UPDATE `"+table+"` SET ");
sql.append(list.get(i).getClass().getDeclaredMethod("updateSql").invoke(t));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
sql.append(";");
return sql.toString();
}
復(fù)制代碼
說明:這塊用到了反射該類來獲取該類的某個(gè)方法,也是自己在項(xiàng)目中第一次用到反射的東西。
2.4 批量刪除表
這個(gè)小玩意也記錄下來,手動(dòng)去清除表:查出所有語(yǔ)句遍歷執(zhí)行也是可以改進(jìn)的。
Select CONCAT( 'drop table ', table_name, ';' )
FROM information_schema.tables
Where table_name LIKE 'calc%';
復(fù)制代碼
總結(jié)
以上是生活随笔為你收集整理的mysql动态sql是什么,mysql中动态sql的一次实际应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二维有限元方程matlab,有限元法求解
- 下一篇: Mysql函数访问oracle,Orac