mysql異步查詢 java_基于 mysql 異步驅動的非阻塞 Mybatis

雖然 spring5 也推出了 WebFlux 這一套異步技術棧,這種極大提升吞吐的玩法在 node 里玩的風生水起,但 java 世界里異步依舊不是主流,Vertx 倒是做了不少對異步的支持,但是其對于數據訪問層的封裝依舊還是挺精簡的,傳統的 javaer 還是受不了這種沒有對象映射的工具庫,于是我嘗試將 Mybatis 移植到了異步驅動上,讓數據訪問層的工作變得更簡單一些。給個例子:

@Sql(User.class)

public interface CommonMapper {

@Select(columns = "id,age,username")

@OrderBy("id desc")

@Page

@ModelConditions({

@ModelCondition(field = "username", criterion = Criterions.EQUAL),

@ModelCondition(field = "maxAge", column = "age", criterion = Criterions.LESS),

@ModelCondition(field = "minAge", column = "age", criterion = Criterions.GREATER)

})

void query(UserSearch userSearch, DataHandler> handler);

}

上面是 mapper 接口定義,方法的最后一個參數因為異步的原因所以變成了一個回調,不同的是有很多注解來表達 sql,看到這些注解應該不難猜出 sql 語句吧。如果不喜歡你當然可以繼續使用 mapper.xml 的方式來寫 sql。

更多內容移步代碼庫吧~

AsyncDao

asyncDao是一款異步非阻塞模型下的數據訪問層工具。

MySQL only. 基于MySQL的異步驅動

借鑒了Mybatis的mapping 和 dynamicSQL的內容,Mybatiser可以無縫切換

注解表達SQL的能力

事務支持

SpringBoot支持

Mybatis like

使用上與Mybatis幾乎一致,由于異步非阻塞的關系,數據的返回都會通過回調DataHandler來完成,所以方法定義參數的最后一個一定是DataHandler類型。由于需要提取方法的參數名,于是需要加上編譯參數-parameters,請將它在IDE和maven里配置上。

public interface CommonDao {

void query(User user, DataHandler> handler);

void querySingle(User user, DataHandler handler);

void querySingleMap(User user, DataHandler handler);

void insert(User user,DataHandler handler);

void update(User user,DataHandler handler);

void delete(User user,DataHandler handler);

}

mapper.xml與Mybatis幾乎一致的寫法(覆蓋常見標簽,一些不常用標簽可能不支持,動態SQL建議使用注解SQL功能)

select * from T_User

AND username = #{user.username}

OR age > #{user.age}

order by id desc

insert into T_User

old_address,

created_at,

password,

now_address,

state,

age,

username,

updated_at,

#{user.oldAddress},

#{user.createdAt},

#{user.password},

#{user.nowAddress},

#{user.state},

#{user.age},

#{user.username},

#{user.updatedAt},

update T_User

password=#{user.password},

age=#{user.age},

where id = #{user.id}

注解SQL

在XML里寫SQL對于一些常見SQL實在是重復勞動,so這里允許你利用注解來表達SQL,該怎么做呢?

Table與Model關聯

@Table(name = "T_User")

public class User {

@Id("id")

private Long id;

//建議全部用包裝類型,并注意mysql中字段類型與java類型的對應關系,mysql的int不會自動裝換到這里的long

private String username;

private Integer age;

@Column("now_address")

private String nowAddress;

@Column("created_at")

private LocalDateTime createdAt;

//asyncDao 里sql的時間類型都用joda,注意不是JDK8提供的那個,而是第三方包org.joda.time

@Ignore

private String remrk;

@Table記錄數據表的名字 @Id記錄主鍵信息 @Column映射了表字段和屬性的關系,如果表字段和類屬性同名,那么可以省略這個注解 @Ingore忽略這個類屬性,沒有哪個表字段與它關聯。

定義接口

@Sql(User.class)

public interface CommonDao {

@Select(columns = "id,age,username")

@OrderBy("id desc")

@Page

@ModelConditions({

@ModelCondition(field = "username", criterion = Criterions.EQUAL),

@ModelCondition(field = "maxAge", column = "age", criterion = Criterions.LESS),

@ModelCondition(field = "minAge", column = "age", criterion = Criterions.GREATER)

})

void query(UserSearch userSearch, DataHandler> handler);

@Select(columns = "age,username")

@OrderBy("id desc")

void queryParam(@Condition String username,

@Condition(criterion = Criterions.GREATER) Integer age,

@OffSet int offset,

@Limit int limit,

DataHandler> handler);

@Select(columns = "username,age", sqlMode = SqlMode.COMMON)

void queryList(@Condition(criterion = Criterions.IN, column = "id") int[] ids, DataHandler> handler);

@Insert(useGeneratedKeys = true, keyProperty = "id")

void insert(User user, DataHandler handler);

@Update

@ModelConditions(@ModelCondition(field = "id"))

void update(User user, DataHandler handler);

@Delete

@ModelConditions(@ModelCondition(field = "id"))

void delete(User user, DataHandler handler);

}

看到這些注解你應該能猜出來SQL長什么樣,接下來解釋一下這些注解

查詢

@Select(columns = "id,age,username")

@OrderBy("id desc")

@Page

@ModelConditions({

@ModelCondition(field = "username", criterion = Criterions.EQUAL),

@ModelCondition(field = "maxAge", column = "age", criterion = Criterions.LESS),

@ModelCondition(field = "minAge", column = "age", criterion = Criterions.GREATER)

})

void query(UserSearch userSearch, DataHandler> handler);

@Select

columns:默認 select *可以配置columns("username,age")選擇部分字段;

SqlMode:有兩個選擇,SqlMode.SELECTIVE 和 SqlMode.COMMON,區別是selective會檢查查詢條件的字段是否為null來實現動態的查詢,即值為null時不會成為查詢條件。并且@Select,@Count,@Update,@Delete都有selective這個屬性。

@Condition

criterion:查詢條件,=,,in等,具體見Criterions

column:與表字段的對應,若與字段名相同可不配置

attach:連接 and,or, 默認是and

test:SqlMode為selective下的判斷表達式,類似Mybatis里的test屬性,動態化查詢條件

@Limit,@OffSet為分頁字段。

方法的參數不加任何注解一樣會被當做查詢條件,如下面兩個函數效果是一樣的:

@Select()

void queryUser(Integer age,DataHandler> handler);

@Select()

void queryUser(@Condition(criterion = Criterions.EQUAL, column = "age") Integer age,DataHandler> handler);

查詢Model

上面的例子在查詢條件比較多時方法參數會比較多,我們可以把查詢條件封裝到一個類里,使用@ModelConditions來注解查詢條件,注意被@ModelConditions注解的方法只能有兩個參數,一個是查詢model,一個是DataHandler。

@Select

@Page

@ModelConditions({

@ModelCondition(field = "username", criterion = Criterions.EQUAL),

@ModelCondition(field = "minAge", column = "age", criterion = Criterions.GREATER),

@ModelCondition(field = "maxAge", column = "age", criterion = Criterions.LESS),

@ModelCondition(field = "ids", column = "id", criterion = Criterions.IN)

})

void queryUser5(UserSearch userSearch,DataHandler> handler);

@ModelCondition

field:必填,查詢條件中類對應的屬性

column:對應的表字段

test:動態SQL的判斷表達式

@Page只能用在ModelConditions下的查詢,并且方法參數的那個類應該有offset,limit這兩個屬性,或者 使用@Page(offsetField = "offset",limitField = "limit")指定具體字段

統計

@Count

void count(DataHandler handler);//返回Long類型

插入

@Insert(useGeneratedKeys = true, keyProperty = "id")//返回自增id

void insert(User user, DataHandler handler);

更新

@Update(columns = "username,age")//選擇更新某幾個列

void update(User user, DataHandler handler);//返回affectedRows

刪除

@Delete

int delete(@Condition(criterion = Criterions.GREATER, column = "age") int min,

@Condition(criterion = Criterions.LESS, column = "age") int max,

DataHandler handler);

@Delete

@ModelConditions(@ModelCondition(field = "id"))

void delete(User user, DataHandler handler);

使用

簡單的編程使用

AsyncConfig asyncConfig = new AsyncConfig();

PoolConfiguration configuration = new PoolConfiguration("username", "localhost", 3306, "password", "database-name");

asyncConfig.setPoolConfiguration(configuration);

asyncConfig.setMapperPackages("com.tg.async.mapper");//mapper接口

asyncConfig.setXmlLocations("mapper/");//xml目錄,classpath的相對路徑,不支持絕對路徑

AsyncDaoFactory asyncDaoFactory = AsyncDaoFactory.build(asyncConfig);

CommonDao commonDao = asyncDaoFactory.getMapper(CommonDao.class);

UserSearch userSearch = new UserSearch();

userSearch.setUsername("ha");

userSearch.setMaxAge(28);

userSearch.setMinAge(8);

userSearch.setLimit(5);

CountDownLatch latch = new CountDownLatch(1);

commonDao.query(user, users -> {

System.out.println(users);

latch.countDown();

});

latch.await();

事務

Mybatis和Spring體系里有一個非常好用的@Translactional注解,我們知道事務本質就是依賴connection的rollback等操作,那么一個事務下多個SQL就要共用這一個connection,如何共享呢?傳統的阻塞體系下ThreadLocal就成了實現這一點的完美解決方案。那么在異步世界里,要實現mybatis-spring一樣的上層Api來完成事務操作是一件非常困難的事,難點就在于Api太上層,以至于無法實現connection共享。于是這里自能退而求其次,使用編程式的方式來使用事務,抽象出一個Translaction,具體的mapper通過translaction.getMapper()來獲取,這樣通過同一個Translaction得到的Mapper都將共用一個connection。

CountDownLatch latch = new CountDownLatch(1);

AsyncConfig asyncConfig = new AsyncConfig();

PoolConfiguration configuration = new PoolConfiguration("username", "localhost", 3306, "password", "database-name");

asyncConfig.setPoolConfiguration(configuration);

asyncConfig.setMapperPackages("com.tg.async.mapper");

asyncConfig.setXmlLocations("mapper/");

asyncDaoFactory = AsyncDaoFactory.build(asyncConfig);

asyncDaoFactory.startTranslation(res -> {

Translaction translaction = res.result();

System.out.println(translaction);

CommonDao commonDao = translaction.getMapper(CommonDao.class);

User user = new User();

user.setUsername("insert");

user.setPassword("1234");

user.setAge(28);

commonDao.insert(user, id -> {

System.out.println(id);

translaction.rollback(Void -> {

latch.countDown();

});

});

});

latch.await();

SpringBoot

雖然Spring5推出了WebFlux,但異步體系在Spring里依舊不是主流。在異步化改造的過程中,大部分人也往往會保留Spring的IOC,而將其他交給Vertx,所以asyncDao對于Spring的支持就是將Mapper注入IOC容器。

quick start

YAML配置文件:

async:

dao:

mapperLocations: /mapper #xml目錄,classpath的相對路徑,不支持絕對路徑

basePackages: com.tg.mapper #mapper所在包

username: username

host: localhost

port: 3306

password: pass

database: database-name

maxTotal: 12

maxIdle: 12

minIdle: 1

maxWaitMillis: 10000

添加@Mapper來實現注入

@Mapper

@Sql(User.class)

public interface CommonDao {

@Select(columns = "id,age,username")

@OrderBy("id desc")

@Page(offsetField = "offset", limitField = "limit")

@ModelConditions({

@ModelCondition(field = "username", criterion = Criterions.EQUAL),

@ModelCondition(field = "maxAge", column = "age", criterion = Criterions.LESS),

@ModelCondition(field = "minAge", column = "age", criterion = Criterions.GREATER)

})

void query(UserSearch userSearch, DataHandler> handler);

}

通過@EnableAsyncDao來開啟支持,簡單示例:

@SpringBootApplication

@EnableAsyncDao

public class DemoApplication {

public static void main(String[] args){

ApplicationContext applicationContext = SpringApplication.run(DemoApplication.class);

CommonDao commonDao = applicationContext.getBean(CommonDao.class);

UserSearch userSearch = new UserSearch();

userSearch.setUsername("ha");

userSearch.setMaxAge(28);

userSearch.setMinAge(8);

userSearch.setLimit(5);

commonDao.query(userSearch, users -> {

System.out.println("result: " + users);

});

}

}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/534004.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/534004.shtml
英文地址,請注明出處:http://en.pswp.cn/news/534004.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

跨域獲取后臺數據undefined_同源策略amp;JSONP跨域

同源策略&JSONP跨域同源策略 對于同源的定義,MDN給出了這樣的解釋:如果兩個頁面的協議,端口(如果有指定)和主機都相同,則兩個頁面具有相同的源。如何確定兩個頁面是否同源,只要比較兩個頁面…

python 除數不能為零的報錯有哪些_【社區精選40】Python錯誤處理及代碼調試方法(文末贈書中獎名單)...

本文整理自愛數據學院中的問答更多精彩問答,進入下方社區網站查看http://www.lovedata.cn/invitation社區精選話題 第40期Python錯誤處理及代碼調試方法一次寫完代碼程序并能夠正常運行的概率很小很小,總會有各種各樣的錯誤bug需要處理。有的報錯簡單&a…

利用python批量查詢企業信息_python實現批量獲取指定文件夾下的所有文件的廠商信息...

本文實例講述了python實現批量獲取指定文件夾下的所有文件的廠商信息的方法。分享給大家供大家參考。具體如下:功能代碼如下:import os, string, shutil,reimport pefileimport codecs, sysimport wximport struct#輸出中打印Unicode字符#sys.stdout co…

mac mysql prefpane_【MySQL數據庫開發之一】Mac下配置安裝數據庫-MySQL

本站文章均為那么從今天開始陸續會更新數據庫和Hibernate框架的博文,也是Himi學習的歷程記錄,希望大家能共同討論和研究;OK,本篇簡單介紹安裝吧,首先到MySQL官方網站:如上圖:點擊DOWNLOAD &…

系統新模塊增加需要哪些步驟_想要吸引人流,兒童樂園需要增加哪些新設備呢...

兒童樂園是現今最火爆的一個投資項目,因為它的主要消費群體是孩子,而現在的家長們對孩子們的寵愛,基本都會答應讓孩子們去兒童樂園里面玩耍。但是兒童樂園的投資經營者也會遇見一些小問題,例如兒童樂園添加設備要怎么選擇呢&#…

php mysql 圖像_php-向/從MySQL數據庫插入/查看圖像

我在DB中插入圖像時遇到問題.該表具有以下結構:> id-> INT(3)->自動增量>名稱-> VARCHAR(30)> extension-> VARCHAR(10)[可能太短]> img-> MEDIUMBLOB插入圖像的PHP代碼為:if($_FILES[file][error]0){$result is_uploaded_f…

照片打印預覽正常打印空白_小米發布口袋照片打印機,可無墨打印3寸背膠照片...

9月11日消息,小米推出一款小米口袋照片打印機。與之前的小米米家照片打印機相比,這款新品更加小巧便攜,體積接近充電寶大小,凈重僅181g,便于隨身攜帶。小米口袋照片打印機采用ZINK無墨技術打印,即使用嵌入紙…

c中獲取python控制臺輸出_在真實的tim中用C捕獲控制臺python打印

我正在嘗試從C創建一個python進程,并從python腳本獲取打印結果。在這就是我的C代碼:namespace ConsoleApp1{public class CreateProcess{public String PythonPath { get; set; }public String FilePath { get; set; }public String Arguments { get; se…

python三大編程語言_程序員最需要的三種編程語言

隨著科學技術的進步和新技術的進步,編程語言的種類越來越多,變化是程序員需要跟蹤和學習許多語言 然而,有太多的語言無法一一掌握 在目前的形式中,最需要掌握的三種編程語言是 現在判斷還不晚 坦白說,找工作很容易 它可…

MySQL優化調優有沒有做過_MySQL 調優/優化的 100 個建議

MySQL是一個強大的開源數據庫。隨著MySQL上的應用越來越多,MySQL逐漸遇到了瓶頸。這里提供 101 條優化 MySQL 的建議。有些技巧適合特定的安裝環境,但是思路是相通的。我已經將它們分成了幾類以幫助你理解。MySQL監控MySQL服務器硬件和OS(操作系統)調優&…

python語句print(type([1、2、3、4))_Python 學習第一天

一、學習內容1.print:表示輸出print (“hello world”)單行注釋:#多行注釋:“““ ”””2.運算符注意:才表示等于,!表示不等于3.位運算符~按位取反:~104.變量和賦值teacher“老馬的…

mysql核心參數_MySQL技術體系之核心參數

本文主要基于MySQL 5.7版本的數據庫環境,總結my.cnf文件中核心參數的配置使用,讓更多的人對MySQL技術體系有更全面、更專業的深度了解。一、客戶端核心參數1、port端口號,默認33062、socketSocket文件地址,默認以.sock為文件名稱后…

svd降維 python案例_SVD(奇異值分解)Python實現

注: 在《SVD(異值分解)小結 》中分享了SVD原理,但其中只是利用了numpy.linalg.svd函數應用了它,并沒有提到如何自己編寫代碼實現它,在這里,我再分享一下如何自已寫一個SVD函數。但是這里會利用到SVD的原理,…

salt 啟動mysql_saltsack自動化配置day03:服務部署mysql部署

一、MySQL集群需求分享1、抽象:功能模塊把基礎的寫成通用服務部署也要抽象出來模塊redis內存有的多,有的少,可以config set在線更改redis 安裝、配置、啟動mysql 安裝、配置(my.cnf可以統一 目錄默認配置可以統一)master: server_id 1111slav…

jtag引腳定義_從逆向分析的角度學習硬件調試技巧JTAG,SSD和固件提取

我想從逆向的角度做了深入了解JTAG,JTAG是許多嵌入式CPU使用的硬件級別調試機制,我希望通過這篇文章從逆向工程師的角度解釋如何使用JTAG,并在此過程中提供一些實際示例。0x01 研究目標通過這篇文章,我希望做到以下幾點&#xff1…

python virtualenv conda_在vscode中啟動conda虛擬環境的思路詳解

問題:cudatoolkit cudnn 通過conda 虛擬環境安裝,先前已經使用virtualenv安裝tf,需要在conda虛擬環境中啟動外部python虛擬環境思路:conda prompt即將 [虛擬環境位置] 以參數形式傳入 [activate.bat]VSOCDE中的設置添加以下語句{&…

python如何導入圖片imread_OpenCV 使用imread()函數讀取圖片的六種正確姿勢

經常看到有人在網上詢問關于imread()函數讀取圖片失敗的問題。今天心血來潮,經過實驗,總結出imread()調用的四種正確姿勢。通常我要獲取一張圖片的絕對路徑是這樣做的:在圖片上右鍵——屬性——安全——對象名稱。然后復制對象名稱就得到了圖…

python2.7與3.7腳本轉換_python 2.7 - python 3.7 升級記錄

更換的模塊python 3.7 模塊名python 2.7 模塊名python 3.7 包python 2.7包pymysqlMySQLdbPyMySQLMySQL-pythonpdfminerpdfminerpdfminer.sixpdfminerurllib.parseurlparse自帶自帶htmlHTMLParser自帶HTMLparser語法變化1. print 修改為 print()2. except Exception, e 修改為 e…

遠程過程調用失敗_Java開發大型互聯網RPC遠程調用服務實現之問題處理方案

引言RPC(Remote Procedure Call Protocol)——遠程過程調用協議,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議。RPC協議假定某些傳輸協議的存在,如TCP或UDP,為通信程序之間攜帶信息數據。在OSI網絡…

chrome 新的session 設置_為什么還是由這么多人搞不懂Cookie、Session、Token?

作者:不學無數的程序員鏈接:https://urlify.cn/Yfm6Vr# Cookie洛:大爺,樓上322住的是馬冬梅家吧? 大爺:馬都什么? 夏洛:馬冬梅。 7大爺:什么都沒啊? 夏洛…