1. 程式人生 > 其它 >治理有精度,AI賦智加強城市精細化管理

治理有精度,AI賦智加強城市精細化管理

1.簡介

1.什麼是Mybatis-plus?

   MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而生。

  官網:https://mp.baomidou.com/

2.開發環境準備

1.配置資料庫環境,建立一張測試表

2.建立springboot專案,引入依賴

<!--mybatis plus 起步依賴-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>

3.編寫DataSource相關配置

spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456

4.編寫實體類

@Data
//指定表名
@TableName("user_info")
public class UserInfo implements Serializable {
//指定表的id
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
//指定表中的欄位名
@TableField("name")
private String name;
private Integer sex;
private Integer age;
private String address;
private String mobile;
private String email;
@TableField(exist = false)
private String test;
//邏輯刪除,1:刪除,0:未刪
@TableLogic(value = "0", delval = "1")
private Integer disabled;
}
1) @TableField("name") 指定對映關係。
  • 實體類的屬性名和資料庫的欄位名自動對映。
  • 自動對映條件:名稱一樣,或者資料庫欄位使用_分割,實體類屬性名使用駝峰名稱
  • 否則需要使用@TableField("name") 指定對映關係。
2)@TableField(exist = false) 忽略某個欄位的查詢和插入。
3) @TableId(type = IdType.AUTO)設定id生成策略:AUTO 資料庫自增。
  • AUTO 資料庫ID自增,依賴於資料庫。在插入操作生成SQL語句時,不會插入主鍵這一列
  • NONE 未設定主鍵型別。使用者輸入,為空則會根據主鍵的全域性策略自動生成
  • INPUT 需要手動設定主鍵,若不設定。插入操作生成SQL語句時,主鍵這一列的值會是null
  • ID_WORKER(Long) 當實體類的主鍵屬性為空時,才會自動填充
  • ID_WORKER_STR(String) 當實體類的主鍵屬性為空時,才會自動填充
  • UUID 當實體類的主鍵屬性為空時,才會自動填充,使用UUID
4)@TableLogic(value = "0", delval = "1")設定邏輯刪除欄位,並設定刪除與未刪的代表值
新增該註解之後:
  • 刪除轉變為更新,呼叫mp提供的刪除介面時,更新disable欄位0->1
  • 只對自動注入的SQL起效
  • 查詢時自動生成where disable=0查詢
  • 更新時自動生成where disable=0條件防止更新到已刪除資料
  • 自己寫的刪除介面依然為物理刪除
不新增此註解時:
  • mp提供的刪除介面預設為物理刪除

5.啟動類增加 @MapperScan 註解,指定dao包的位置

@SpringBootApplication
@MapperScan("com.jinrui.dao")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}

3.Mapper 介面

編寫dao

使用mp定義Mapper,需要讓Mapper介面繼承 BaseMapper介面。

@Mapper
public interface UserInfoDao extends BaseMapper<UserInfo> {
}

1.增加

// 插入一條記錄

int insert(T entity);

型別

引數名

描述

T entity 實體物件

2.刪除

// 根據 entity 條件,刪除記錄
int delete(Wrapper<T> wrapper);
// 刪除(根據ID 批量刪除)
int deleteBatchIds(Collection<? extends Serializable> idList);
// 根據 ID 刪除
int deleteById(Serializable id);
// 根據 columnMap 條件,刪除記錄
int deleteByMap(Map<String, Object> columnMap);

型別 引數名 描述
Wrapper<T> wrapper 實體物件封裝操作類(可以為 null)
Collection<? extends Serializable> idList 主鍵ID列表(不能為 null 以及 empty)
Serializable id 主鍵ID
Map<String, Object> columnMap 表字段 map 物件

3.修改

// 根據 whereWrapper 條件,更新記錄
int update(Wrapper<T> updateWrapper);
// 根據 ID 修改
int updateById(T entity);

型別 引數名 描述
T entity 實體物件 (set 條件值,可為 null)
Wrapper<T> updateWrapper 實體物件封裝操作類(可以為 null,裡面的 entity 用於生成 where 語句)

4.查詢

// 根據 ID 查詢
T selectById(Serializable id);
// 根據 entity 條件,查詢一條記錄
T selectOne(Wrapper<T> queryWrapper);

// 查詢(根據ID 批量查詢)
List<T> selectBatchIds(Collection<? extends Serializable> idList);
// 根據 entity 條件,查詢全部記錄
List<T> selectList(Wrapper<T> queryWrapper);
// 查詢(根據 columnMap 條件)
List<T> selectByMap(Map<String, Object> columnMap);
// 根據 Wrapper 條件,查詢全部記錄,只展示查詢的欄位,不展示為null的欄位
List<Map<String, Object>> selectMaps(Wrapper<T> queryWrapper);
// 根據 Wrapper 條件,查詢全部記錄。注意: 只返回第一個欄位的值
List<Object> selectObjs(Wrapper<T> queryWrapper);

// 根據 entity 條件,查詢全部記錄(並翻頁)
IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper);
// 根據 Wrapper 條件,查詢全部記錄(並翻頁)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, Wrapper<T> queryWrapper);
// 根據 Wrapper 條件,查詢總記錄數
Integer selectCount(Wrapper<T> queryWrapper);

型別 引數名 描述
Serializable id 主鍵ID
Wrapper<T> queryWrapper 實體物件封裝操作類(可以為 null)
Collection<? extends Serializable> idList 主鍵ID列表(不能為 null 以及 empty)
Map<String, Object> columnMap 表字段 map 物件
IPage<T> page 分頁查詢條件(可以為 RowBounds.DEFAULT)

條件構造器

AbstractWrapper是QueryWrapper和 UpdateWrapper的父類,用於生成 sql 的 where 條件

AbstractWrapper:
like(R column, Object val)
like(boolean condition, R column, Object val)
  • LIKE '%值%'

  • 例: like("name", "王")--->name like '%王%
eq(R column, Object val)
eq(boolean condition, R column, Object val)
  • 等於 =

  • 例: eq("name", "老王")--->name = '老王'

likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
  • LIKE '%值'

  • 例: likeLeft("name", "王")--->name like '%王'

likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
  • LIKE '值%'
  • 例: likeRight("name", "王")--->name like '王%'
gt(R column, Object val)
gt(boolean condition, R column, Object val)
  • 大於 >
  • 例: gt("age", 18)--->age > 18
ge(R column, Object val)
ge(boolean condition, R column, Object val)
  • 大於等於 >=

  • 例: ge("age", 18)--->age >= 18

lt(R column, Object val)
lt(boolean condition, R column, Object val)
  • 小於 <
  • 例: lt("age", 18)--->age < 18
le(R column, Object val)
le(boolean condition, R column, Object val)
  • 小於等於 <=
  • 例: le("age", 18)--->age <= 18
isNull(R column)
isNull(boolean condition, R column)
  • 欄位 IS NULL
  • 例: isNull("name")--->name is null
isNotNull(R column)
isNotNull(boolean condition, R column)
  • 欄位 IS NOT NULL
  • 例: isNotNull("name")--->name is not null
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
  • 欄位 IN (value.get(0), value.get(1), ...)
  • 例: in("age",{1,2,3})--->age in (1,2,3)
orderBy(boolean condition, boolean isAsc, R... columns)
  • 排序:ORDER BY 欄位, ...
  • 例: orderBy(true, true, "id", "name")--->order by id ASC,name ASC
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
  • BETWEEN 值1 AND 值2
  • 例: between("age", 18, 30)--->age between 18 and 30
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
  • NOT BETWEEN 值1 AND 值2
  • 例: notBetween("age", 18, 30)--->age not between 18 and 30
groupBy(R... columns)
groupBy(boolean condition, R... columns)
  • 分組:GROUP BY 欄位, ...
  • 例: groupBy("id", "name")--->group by id,name
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
  • HAVING ( sql語句 )
  • 例: having("sum(age) > 10")--->having sum(age) > 10
  • 例: having("sum(age) > {0}", 11)--->having sum(age) > 11
or()
or(boolean condition)
  • 拼接 OR
  • 主動呼叫or表示緊接著下一個方法不是用and連線!(不呼叫or則預設為使用and連線)
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
  • 該方法可用於資料庫函式 動態入參的params對應前面的{index}部分.這樣是不會有sql注入風險的,反之會有!
  • apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

QueryWrapper:
select(String... sqlSelect)
  • 設定查詢欄位
  • 例: select("id", "name", "age")->select id,name,age
UpdateWrapper:
set(String column, Object val)
set(boolean condition, String column, Object val)
  • SQL SET 欄位
  • 例: set("name", "wang")
  • 例: set("name", "")--->資料庫欄位值變為空字串
  • 例: set("name", null)--->資料庫欄位值變為null
setSql(String sql)
  • 設定 SET 部分 SQL
  • 例: setSql("name = 'wang'")

4.Service介面

說明:

通用 Service CRUD 封裝IService 介面,進一步封裝 CRUD 採用 get 查詢、單行 remove 刪除、 list 查詢集合、 page 分頁, 字首命名方式區分 Mapper 層避免混淆。

需要繼承Service類

public interface UserInfoService extends IService<UserInfo> {}

建議如果存在自定義通用 Service 方法,請建立自己的 BaseService 繼承 Mybatis-Plus 提供的基類

public interface UserInfoService extends BaseService<UserInfo> {}
public interface BaseService extends IService<UserInfo> {}

 

介面介紹:

#Save

// 插入一條記錄(選擇欄位,策略插入)

boolean save(T entity);

// 插入(批量)

boolean saveBatch(Collection<T> entityList);

型別

引數名

描述

T entity 實體物件
Collection<T> entityList 實體物件集合

SaveOrUpdate

// 主鍵id存在更新記錄,否則插入一條記錄

boolean saveOrUpdate(T entity);

// 批量修改插入

boolean saveOrUpdateBatch(Collection<T> entityList);

// 批量修改插入

boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

型別 引數名 描述
T entity 實體物件
Collection<T> entityList 實體物件集合
int batchSize 插入批次數量

#Remove

// 根據 entity 條件,刪除記錄
boolean remove(Wrapper<T> queryWrapper);
// 根據 ID 刪除
boolean removeById(Serializable id);
// 根據 columnMap 條件,刪除記錄
boolean removeByMap(Map<String, Object> columnMap);
// 刪除(根據ID 批量刪除)
boolean removeByIds(Collection<? extends Serializable> idList);

型別 引數名 描述
Wrapper<T> queryWrapper 實體包裝類 QueryWrapper
Serializable id 主鍵ID
Map<String, Object> columnMap 表字段 map 物件
Collection<? extends Serializable> idList 主鍵ID列表

#Update

// 根據 updateWrapper條件,更新記錄
boolean update(T updateEntity, Wrapper<T> updateWrapper);
// 根據 ID 選擇修改
boolean updateById(T entity);
// 根據ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根據ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

型別 引數名 描述
Wrapper<T> updateWrapper 實體物件封裝操作類 UpdateWrapper
T entity 實體物件
Collection<T> entityList 實體物件集合
int batchSize 更新批次數量

#Get

// 根據 ID 查詢
T getById(Serializable id);
// 根據 Wrapper,查詢一條記錄。結果集,如果是多個會丟擲異常
T getOne(Wrapper<T> queryWrapper);
// 根據 Wrapper,查詢一條記錄
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根據 Wrapper,查詢一條記錄
Map<String, Object> getMap(Wrapper<T> queryWrapper);

型別 引數名 描述
Serializable id 主鍵ID
Wrapper<T> queryWrapper 實體物件封裝操作類 QueryWrapper
boolean throwEx 有多個 result 是否丟擲異常
T entity 實體物件

#List

// 查詢所有
List<T> list();
// 查詢列表
List<T> list(Wrapper<T> queryWrapper);
// 查詢(根據ID 批量查詢)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查詢(根據 columnMap 條件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查詢所有列表,不顯示為null的欄位
List<Map<String, Object>> listMaps();
// 根據條件查詢所有列表,不顯示為null的欄位
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查詢全部記錄,只顯示第一個欄位
List<Object> listObjs();
// 根據 Wrapper 條件,查詢全部記錄
List<Object> listObjs(Wrapper<T> queryWrapper);

型別 引數名 描述
Wrapper<T> queryWrapper 實體物件封裝操作類 QueryWrapper
Collection<? extends Serializable> idList 主鍵ID列表
Map<?String, Object> columnMap 表字段 map 物件

#Count

// 查詢總記錄數
int count();
// 根據 Wrapper 條件,查詢總記錄數
int count(Wrapper<T> queryWrapper);

 

型別

引數名

描述

Wrapper<T> queryWrapper 實體物件封裝操作類 QueryWrapper

5.分頁外掛

寫mybatis-plus配置類,用來配置使用的資料庫

@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor= new PaginationInterceptor();
paginationInterceptor.setDialectType("mysql");
return paginationInterceptor;
}
}

寫service,可以呼叫mp中service層提供的分頁介面和Ipage外掛進行分頁。

// 無條件分頁查詢
IPage<T> page(IPage<T> page);
// 條件分頁查詢
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 無條件分頁查詢,不顯示null欄位
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 條件分頁查詢,不顯示null欄位
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

型別 引數名 描述
IPage<T> page 翻頁物件
Wrapper<T> queryWrapper 實體物件封裝操作類 QueryWrapper

編碼:

@Override
public List<UserInfo> selectPage(Integer page, Integer limit) {
IPage ipage = this.page(new Page(page,limit),null);
return ipage.getRecords();
}

測試

 

 

所執行的sql

6.SQL分析

在MybatisPlusConfig當中新增配置程式碼,此配置可以顯示SQ語句和執行時間

@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
Properties properties=new Properties();
//開啟sql格式化
properties.setProperty("format", "true");
performanceInterceptor.setProperties(properties);
return performanceInterceptor;
}

測試

7.程式碼生成器

1.新增依賴

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>

2.新增模板依賴

MyBatis-Plus 支援 Velocity(預設)、Freemarker、Beetl,專案中使用的是Freemarker,我們以Freemarker為例。

<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>

3.編寫配置類

設定存放路徑,作者

GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
System.out.println(projectPath);
gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("itheima");
gc.setOpen(false);

資料來源配置

DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql:///test");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);

包配置

PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("模組名"));
pc.setParent("com.jinrui");
mpg.setPackageInfo(pc);

其他配置

// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定義輸出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定義配置會被優先輸出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定義輸出檔名 , 如果你 Entity 設定了前後綴、此處注意 xml 的名稱會跟著發生變化!!
return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
// 下劃線駝峰命名轉換
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// 開啟lombok
strategy.setEntityLombokModel(true);
// 開啟RestController
strategy.setRestControllerStyle(true);
// 公共父類
// 寫於父類中的公共欄位
// strategy.setSuperEntityColumns("id");
strategy.setInclude(scanner("表名,多個英文逗號分割").split(","));
//@RequestMapping中駝峰轉字串
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();

7.測試

執行main方法,輸入模組名和表名:

成功生成程式碼

8.Demo

 

9.fir專案

1.fir-db

1.實體類添加註解,以MetricData為例,用於資料庫表與實體類、欄位與屬性對應

@TableName("metric_data")
public class MetricData implements Serializable {
private static long serialVersionUID = -2449909017343874495L;
@TableId(value = "mdid", type = IdType.AUTO)
private Long id;
@TableField("metricid")
private String metricId;
@TableField("time")
private Long time;
@TableField("data")
private Double data;
@TableField("addtime")
private Date addtime;
@TableField("reporttime")
private Long reportTime;
@TableField(exist = false)
private Metric metric;
@TableLogic(value = "0", delval = "1")
@TableField("disabled")
private Integer disabled;

2.Mapper層繼承BaseMapper,可以呼叫mp提供的API

public interface MetricDataRepository extends BaseRepository<MetricData, Long>{}
public interface BaseRepository<T, ID extends Serializable> extends BaseMapper<T>()

3.Service層繼承Iservice,可以呼叫mp提供的API

public interface MetricDataService extends BaseService<MetricData>{}
public interface BaseService<T> extends IService<T>{}

4.使用了自定義通用Service類,定義了一些常用的方法,方便複用

public interface BaseService<T> extends IService<T>
{
AdminUser getCurrentAdmin();
User getCurrentUser();
SearchResult findBySearchRequest( SearchRequest searchRequest);
List<T> findAll();
T findById( Serializable id);
boolean deleteById( Serializable p0);
boolean isDisabled();
}

5.MybatisPlusConfig中寫了一些配置,用於配置分頁外掛和SQL分析外掛

@Configuration
public class MybatisPlusConfig {
/**
* mybatis-plus分頁外掛
* @return
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor= new PaginationInterceptor();
paginationInterceptor.setDialectType("mysql");
return paginationInterceptor;
}
/**
*sql執行效率外掛
* @return
*/
@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
Properties properties=new Properties();
//開啟sql格式化
properties.setProperty("format", "true");
performanceInterceptor.setProperties(properties);
return performanceInterceptor;
}
}

6.條件查詢的構造方式

Controller層,attribute(欄位)、operator(操作)、values(值)封裝到Condition中,col(欄位)、direction(方向)封裝到Ordering中,然後把這些資料封裝到SearchRequest中。

Service層,呼叫BaseService中的findBySearchRequest方法進行分頁查詢,迭代構造條件,最後返回SearchResult。

 

 

 

例:Controller層:封裝Condition、Ordering、page、limit到SearchRequest,以searchRequest為引數呼叫service中的search()。

這裡面封裝資料的SearchRequest,程式碼如下圖所示。

Service層:呼叫BaseService類中的findBySearchRequest方法用於分頁查詢。

返回結果SearchResult,程式碼如圖所示。

BaseService中findBySearchRequest方法,主要用於分頁,呼叫contructWrapper方法構造條件。

BaseService中contructWrapper方法用於迭代構造查詢條件,呼叫addCondition方法。

addCondition方法:主要用於匹配操作名稱和構造條件。

private QueryWrapper addCondition(String attribute, String operator, List<Object> valuesList, QueryWrapper queryWrapper) {
Object value = null;
if (CollectionUtils.isNotEmpty(valuesList)) {
value = valuesList.get(0);
}
switch (OperatorEnum.matchValue(operator)) {
case LIKE: {
queryWrapper.like(attribute, value);
break;
}
case LIKE_BEGIN: {
queryWrapper.likeRight(attribute, value);
break;
}
case LIKE_END: {
queryWrapper.likeLeft(attribute, value);
break;
}
case GT: {
queryWrapper.gt(attribute, value);
break;
}
case GTE: {
queryWrapper.ge(attribute, value);
break;
}
case EQ: {
queryWrapper.eq(attribute, value);
break;
}
case LT: {
queryWrapper.lt(attribute, value);
break;
}
case LTE: {
queryWrapper.le(attribute, value);
break;
}
case ISNULL: {
queryWrapper.isNull(attribute);
break;
}
case ISNOTNULL: {
queryWrapper.isNotNull(attribute);
break;
}
case IN: {
queryWrapper.in(attribute, valuesList);
break;
}
case NE: {
queryWrapper.ne(attribute, value);
break;
}
default: {
throw new SearchException(ServiceExceptionCodeEnum.BADARGUMENT_PARAM.getCode(), "查詢操作符不符合");
}
}
return queryWrapper;
}

列舉類,用於選擇對應的查詢條件。