icann 域名注册网站,sem竞价推广公司,在国外用什么地图导航,wordpress配置七牛cdn虽然 spring5 也推出了 WebFlux 这一套异步技术栈#xff0c;这种极大提升吞吐的玩法在 node 里玩的风生水起#xff0c;但 java 世界里异步依旧不是主流#xff0c;Vertx 倒是做了不少对异步的支持#xff0c;但是其对于数据访问层的封装依旧还是挺精简的#xff0c;传统…虽然 spring5 也推出了 WebFlux 这一套异步技术栈这种极大提升吞吐的玩法在 node 里玩的风生水起但 java 世界里异步依旧不是主流Vertx 倒是做了不少对异步的支持但是其对于数据访问层的封装依旧还是挺精简的传统的 javaer 还是受不了这种没有对象映射的工具库于是我尝试将 Mybatis 移植到了异步驱动上让数据访问层的工作变得更简单一些。给个例子Sql(User.class)public interface CommonMapper {Select(columns id,age,username)OrderBy(id desc)PageModelConditions({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。更多内容移步代码库吧~AsyncDaoasyncDao是一款异步非阻塞模型下的数据访问层工具。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_UserAND username #{user.username}OR age #{user.age}order by id descinsert into T_Userold_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_Userpassword#{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不会自动装换到这里的longprivate String username;private Integer age;Column(now_address)private String nowAddress;Column(created_at)private LocalDateTime createdAt;//asyncDao 里sql的时间类型都用joda注意不是JDK8提供的那个而是第三方包org.joda.timeIgnoreprivate String remrk;Table记录数据表的名字 Id记录主键信息 Column映射了表字段和属性的关系如果表字段和类属性同名那么可以省略这个注解 Ingore忽略这个类属性没有哪个表字段与它关联。定义接口Sql(User.class)public interface CommonDao {Select(columns id,age,username)OrderBy(id desc)PageModelConditions({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);UpdateModelConditions(ModelCondition(field id))void update(User user, DataHandler handler);DeleteModelConditions(ModelCondition(field id))void delete(User user, DataHandler handler);}看到这些注解你应该能猜出来SQL长什么样接下来解释一下这些注解查询Select(columns id,age,username)OrderBy(id desc)PageModelConditions({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);Selectcolumns:默认 select *可以配置columns(username,age)选择部分字段SqlMode:有两个选择SqlMode.SELECTIVE 和 SqlMode.COMMON区别是selective会检查查询条件的字段是否为null来实现动态的查询即值为null时不会成为查询条件。并且SelectCountUpdateDelete都有selective这个属性。Conditioncriterion查询条件,,in等具体见Criterionscolumn与表字段的对应若与字段名相同可不配置attach连接 and,or 默认是andtestSqlMode为selective下的判断表达式类似Mybatis里的test属性动态化查询条件LimitOffSet为分页字段。方法的参数不加任何注解一样会被当做查询条件如下面两个函数效果是一样的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。SelectPageModelConditions({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);ModelConditionfield:必填查询条件中类对应的属性column对应的表字段test动态SQL的判断表达式Page只能用在ModelConditions下的查询并且方法参数的那个类应该有offsetlimit这两个属性或者 使用Page(offsetField offset,limitField limit)指定具体字段统计Countvoid count(DataHandler handler);//返回Long类型插入Insert(useGeneratedKeys true, keyProperty id)//返回自增idvoid insert(User user, DataHandler handler);更新Update(columns username,age)//选择更新某几个列void update(User user, DataHandler handler);//返回affectedRows删除Deleteint delete(Condition(criterion Criterions.GREATER, column age) int min,Condition(criterion Criterions.LESS, column age) int max,DataHandler handler);DeleteModelConditions(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 startYAML配置文件async:dao:mapperLocations: /mapper #xml目录,classpath的相对路径,不支持绝对路径basePackages: com.tg.mapper #mapper所在包username: usernamehost: localhostport: 3306password: passdatabase: database-namemaxTotal: 12maxIdle: 12minIdle: 1maxWaitMillis: 10000添加Mapper来实现注入MapperSql(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来开启支持简单示例SpringBootApplicationEnableAsyncDaopublic 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);});}}