日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql异步查询 java_基于 mysql 异步驱动的非阻塞 Mybatis

發布時間:2025/3/8 数据库 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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);

});

}

}

總結

以上是生活随笔為你收集整理的mysql异步查询 java_基于 mysql 异步驱动的非阻塞 Mybatis的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。