PlusBaseMapperX.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. package mybatisex.core.mapper;
  2. import java.beans.PropertyDescriptor;
  3. import java.lang.reflect.Method;
  4. import java.util.Collection;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Objects;
  9. import java.util.function.Function;
  10. import java.util.stream.Collectors;
  11. import org.apache.ibatis.annotations.Param;
  12. import org.apache.ibatis.logging.Log;
  13. import org.apache.ibatis.logging.LogFactory;
  14. import org.apache.ibatis.reflection.property.PropertyNamer;
  15. import com.baomidou.mybatisplus.core.conditions.Wrapper;
  16. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  17. import com.baomidou.mybatisplus.core.metadata.IPage;
  18. import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
  19. import com.baomidou.mybatisplus.core.toolkit.Assert;
  20. import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
  21. import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
  22. import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
  23. import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta;
  24. import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
  25. import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
  26. import com.github.yulichang.interfaces.MPJBaseJoin;
  27. import com.github.yulichang.wrapper.MPJLambdaWrapper;
  28. import mybatisex.common.pojo.PageParam;
  29. import mybatisex.common.pojo.PageResult;
  30. import mybatisex.common.pojo.SortablePageParam;
  31. import mybatisex.common.pojo.SortingField;
  32. import mybatisex.core.util.MyBatisUtils;
  33. /**
  34. * 对实体类的操作
  35. *
  36. * @param <T>
  37. */
  38. public interface PlusBaseMapperX<T> extends BaseMapperX<T> {
  39. static final Log logger = LogFactory.getLog(PlusBaseMapperX.class);
  40. /**
  41. * 博客地址:https://blog.csdn.net/qq_19266669/article/details/114369195
  42. * 查看AbstractLambdaWrapper通过方法得到字段名称
  43. *
  44. * @param column
  45. * @return
  46. */
  47. default String columnToString(SFunction<T, ?> column) {
  48. return columnToString(column, true);
  49. }
  50. default String columnToString(SFunction<T, ?> column, boolean onlyColumn) {
  51. ColumnCache cache = getColumnCache(column);
  52. return onlyColumn ? cache.getColumn() : cache.getColumnSelect();
  53. }
  54. /**
  55. * 获取 SerializedLambda 对应的列信息,从 lambda 表达式中推测实体类
  56. * <p>
  57. * 如果获取不到列信息,那么本次条件组装将会失败
  58. *
  59. * @return 列
  60. * @throws com.baomidou.mybatisplus.core.exceptions.MybatisPlusException 获取不到列信息时抛出异常
  61. */
  62. default ColumnCache getColumnCache(SFunction<T, ?> column) {
  63. LambdaMeta meta = LambdaUtils.extract(column);
  64. String fieldName = PropertyNamer.methodToProperty(meta.getImplMethodName());
  65. Class<?> instantiatedClass = meta.getInstantiatedClass();
  66. Map<String, ColumnCache> columnMap = tryInitCache(instantiatedClass);
  67. return getColumnCache(fieldName, instantiatedClass, columnMap);
  68. }
  69. default ColumnCache getColumnCache(String fieldName, Class<?> lambdaClass, Map<String, ColumnCache> columnMap) {
  70. ColumnCache columnCache = columnMap.get(LambdaUtils.formatKey(fieldName));
  71. Assert.notNull(columnCache, "can not find lambda cache for this property [%s] of entity [%s]", fieldName,
  72. lambdaClass.getName());
  73. return columnCache;
  74. }
  75. @SuppressWarnings("unchecked")
  76. default Class<T> getEntityClass() {
  77. return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), PlusBaseMapperX.class, 0);
  78. }
  79. @SuppressWarnings("unchecked")
  80. default Class<T> currentMapperClass() {
  81. return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), PlusBaseMapperX.class, 0);
  82. }
  83. default Map<String, ColumnCache> tryInitCache(Class<?> lambdaClass) {
  84. final Class<T> entityClass = getEntityClass();
  85. if (entityClass != null) {
  86. lambdaClass = entityClass;
  87. }
  88. Map<String, ColumnCache> columnMap = LambdaUtils.getColumnMap(lambdaClass);
  89. return columnMap;
  90. }
  91. /**
  92. * 根据 entity 条件,删除记录
  93. *
  94. * @param queryWrapper 实体包装类
  95. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  96. */
  97. default boolean delete(T t) {
  98. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t);
  99. return SqlHelper.retBool(delete(queryWrapper));
  100. }
  101. /**
  102. * 根据 whereEntity 条件,更新记录
  103. *
  104. * @param entity 实体对象
  105. * @param updateWrapper 实体对象封装操作类
  106. * {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
  107. * @throws SecurityException
  108. * @throws NoSuchFieldException
  109. */
  110. default boolean update(T entity, SFunction<T, ?> column, Object value) {
  111. UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
  112. String conditions = columnToString(column);
  113. var tableInfo = TableInfoHelper.getTableInfo(entity.getClass());
  114. if (tableInfo != null) {
  115. String keyProperty = tableInfo.getKeyProperty();
  116. Object keyVal = keyProperty != null ? tableInfo.getPropertyValue(entity, keyProperty) : null;
  117. if (keyVal != null) {
  118. updateWrapper.eq(tableInfo.getKeyColumn(), keyVal).set(conditions, value);
  119. return SqlHelper.retBool(update(entity, updateWrapper));
  120. }
  121. }
  122. updateWrapper.eq(conditions, value);
  123. return SqlHelper.retBool(update(entity, updateWrapper));
  124. }
  125. /**
  126. * 根据 whereEntity 条件,更新记录
  127. *
  128. * @param entity 实体对象
  129. * @param updateWrapper 实体对象封装操作类
  130. * {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
  131. * @throws SecurityException
  132. * @throws NoSuchFieldException
  133. */
  134. default boolean update(T entity, Map<String, Object> columns) {
  135. UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
  136. var tableInfo = TableInfoHelper.getTableInfo(entity.getClass());
  137. if (tableInfo != null) {
  138. String keyProperty = tableInfo.getKeyProperty();
  139. Object keyVal = keyProperty != null ? tableInfo.getPropertyValue(entity, keyProperty) : null;
  140. if (keyVal != null) {
  141. updateWrapper.eq(tableInfo.getKeyColumn(), keyVal);
  142. columns.forEach(updateWrapper::set);
  143. return SqlHelper.retBool(update(entity, updateWrapper));
  144. }
  145. }
  146. for (String key : columns.keySet()) {
  147. updateWrapper.eq(key, columns.get(key));
  148. }
  149. return SqlHelper.retBool(update(entity, updateWrapper));
  150. }
  151. /**
  152. * 将
  153. *
  154. * @param entity
  155. * @param columns
  156. * @return
  157. */
  158. @SuppressWarnings("unchecked")
  159. default boolean update(T entity, SFunction<T, ?>... columns) {
  160. // 这里是反射,通过反射来得到
  161. try {
  162. Map<String, Object> columnVal = new HashMap<>();
  163. for (SFunction<T, ?> column : columns) {
  164. String columnName = columnToString(column);
  165. String fieldName = getFieldName(column);
  166. Class<?> clazz = entity.getClass();
  167. PropertyDescriptor p = new PropertyDescriptor(fieldName, clazz);
  168. Method readMethod = p.getReadMethod();
  169. // 得到跟新的值
  170. Object value = readMethod.invoke(entity);
  171. // 把查询条件的值设置为null
  172. Method writeMethod = p.getWriteMethod();
  173. // 将相等的值设置为控制
  174. Object obj = null;
  175. writeMethod.invoke(entity, obj);
  176. columnVal.put(columnName, value);
  177. }
  178. return update(entity, columnVal);
  179. } catch (Exception e) {
  180. logger.error("update class" + entity.getClass() + " exception :" + e.getMessage());
  181. return false;
  182. }
  183. }
  184. default String getFieldName(SFunction<T, ?> column) {
  185. LambdaMeta meta = LambdaUtils.extract(column);
  186. String fieldName = PropertyNamer.methodToProperty(meta.getImplMethodName());
  187. return fieldName;
  188. }
  189. default boolean update(T entity, SFunction<T, ?> column, Collection<?> coll) {
  190. UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
  191. // 这里使用反射得到字段,
  192. String conditions = columnToString(column);
  193. updateWrapper.in(conditions, coll);
  194. return SqlHelper.retBool(update(entity, updateWrapper));
  195. }
  196. default boolean update(T entity, String column, Object value) {
  197. UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
  198. var tableInfo = TableInfoHelper.getTableInfo(entity.getClass());
  199. if (tableInfo != null) {
  200. String keyProperty = tableInfo.getKeyProperty();
  201. Object keyVal = keyProperty != null ? tableInfo.getPropertyValue(entity, keyProperty) : null;
  202. if (keyVal != null) {
  203. updateWrapper.eq(tableInfo.getKeyColumn(), keyVal).set(column, value);
  204. return SqlHelper.retBool(update(entity, updateWrapper));
  205. }
  206. }
  207. updateWrapper.eq(column, value);
  208. return SqlHelper.retBool(update(entity, updateWrapper));
  209. }
  210. default boolean update(T entity, String conditions, Object... values) {
  211. UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
  212. updateWrapper.in(conditions, values);
  213. return SqlHelper.retBool(update(entity, updateWrapper));
  214. }
  215. /**
  216. * 根据 Wrapper,查询一条记录 <br/>
  217. * <p>
  218. * 结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
  219. * </p>
  220. *
  221. * @param queryWrapper 实体对象封装操作类
  222. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  223. */
  224. default T selectOne(T t) {
  225. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t);
  226. return selectOne(queryWrapper, true);
  227. }
  228. /**
  229. * 根据 Wrapper 条件,查询总记录数
  230. *
  231. * @param queryWrapper 实体对象封装操作类
  232. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  233. */
  234. default long selectCount(T t) {
  235. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t);
  236. return SqlHelper.retCount(selectCount(queryWrapper));
  237. }
  238. /**
  239. * 查询列表
  240. *
  241. * @param queryWrapper 实体对象封装操作类
  242. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  243. */
  244. default List<T> selectList(T t) {
  245. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t);
  246. return selectList(queryWrapper);
  247. }
  248. /**
  249. * 查询对象
  250. *
  251. * @param queryWrapper 实体对象封装操作类
  252. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  253. */
  254. default Map<String, Object> getMap(T t) {
  255. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t);
  256. List<Map<String, Object>> selectMaps = selectMaps(queryWrapper);
  257. if (selectMaps != null && selectMaps.size() > 0) {
  258. return selectMaps.get(0);
  259. }
  260. return new HashMap<>();
  261. }
  262. /**
  263. * 查询列表
  264. *
  265. * @param queryWrapper 实体对象封装操作类
  266. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  267. */
  268. default List<Map<String, Object>> selectMaps(T t) {
  269. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t);
  270. return selectMaps(queryWrapper);
  271. }
  272. /**
  273. * 根据 Wrapper 条件,查询全部记录
  274. *
  275. * @param queryWrapper 实体对象封装操作类
  276. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  277. */
  278. default List<Object> listObjs(T t) {
  279. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t);
  280. return selectObjs(queryWrapper, Function.identity());
  281. }
  282. /**
  283. * 根据 Wrapper 条件,查询全部记录
  284. *
  285. * @param queryWrapper 实体对象封装操作类
  286. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  287. * @param mapper 转换函数
  288. */
  289. default <V> List<V> selectObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
  290. return selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
  291. }
  292. /**
  293. * 翻页查询
  294. *
  295. * @param page 翻页对象
  296. * @param queryWrapper 实体对象封装操作类
  297. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  298. */
  299. default <E extends IPage<T>> E selectPage(E page, T t, QueryMap... map) {
  300. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t, map);
  301. try {
  302. return selectPage(page, queryWrapper);
  303. } catch (Exception e) {
  304. e.printStackTrace();
  305. }
  306. return null;
  307. }
  308. /**
  309. * 翻页查询
  310. *
  311. * @param page 翻页对象
  312. * @param queryWrapper 实体对象封装操作类
  313. * {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  314. */
  315. default <E extends IPage<T>> E selectPage(E page, T t) {
  316. Wrapper<T> queryWrapper = QueryWrapperUtil.convertQuery(t);
  317. try {
  318. return selectPage(page, queryWrapper);
  319. } catch (Exception e) {
  320. e.printStackTrace();
  321. }
  322. return null;
  323. }
  324. // select join
  325. /**
  326. * 查询对象 连表查询返回记录集合
  327. *
  328. * @param wrapper joinWrapper
  329. * @param clazz resultType
  330. * @param objs 查询条件
  331. */
  332. /**
  333. * 根据 Wrapper 条件,查询总记录数
  334. *
  335. * @param wrapper joinWrapper
  336. */
  337. default Long selectJoinCount(MPJLambdaWrapper<T> wrapper, Object... param) {
  338. wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
  339. return this.selectJoinCount(wrapper);
  340. }
  341. /**
  342. * 连表查询返回一条记录
  343. *
  344. * @param wrapper joinWrapper
  345. * @param clazz resultType
  346. */
  347. default <DTO> DTO selectJoinOne(Class<DTO> clazz, MPJLambdaWrapper<T> wrapper, Object... param) {
  348. wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
  349. return this.selectJoinOne(clazz, wrapper);
  350. }
  351. /**
  352. * 连表查询返回Map
  353. *
  354. * @param wrapper joinWrapper
  355. */
  356. default Map<String, Object> selectJoinMap(MPJLambdaWrapper<T> wrapper, Object... param) {
  357. wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
  358. return this.selectJoinMap(wrapper);
  359. }
  360. /**
  361. * 连表查询返回记录集合
  362. *
  363. * @param wrapper joinWrapper
  364. * @param clazz resultType
  365. */
  366. default <DTO> List<DTO> selectJoinList(Class<DTO> clazz, MPJLambdaWrapper<T> wrapper, Object... param) {
  367. wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
  368. return this.selectJoinList(clazz, wrapper);
  369. }
  370. /**
  371. * 连表查询返回Map集合
  372. *
  373. * @param wrapper joinWrapper
  374. */
  375. default List<Map<String, Object>> selectJoinMaps(MPJLambdaWrapper<T> wrapper, Object... param) {
  376. wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
  377. return this.selectJoinMaps(wrapper);
  378. }
  379. /**
  380. * 连表查询返回记录集合并分页
  381. *
  382. * @param wrapper joinWrapper
  383. * @param clazz resultType
  384. * @param <DTO> 分页返回对象
  385. */
  386. default <DTO, P extends IPage<DTO>> P selectJoinPage(P page, Class<DTO> clazz, MPJLambdaWrapper<T> wrapper,
  387. Object... param) {
  388. wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
  389. return this.selectJoinPage(page, clazz, wrapper);
  390. }
  391. /**
  392. * 连表查询返回Map集合并分页
  393. *
  394. * @param wrapper joinWrapper
  395. */
  396. default <P extends IPage<Map<String, Object>>> P selectJoinMapsPage(P page, MPJLambdaWrapper<T> wrapper,
  397. Object... param) {
  398. wrapper = QueryLambdaUtil.convertQuery(wrapper, param);
  399. return this.selectJoinMapsPage(page, wrapper);
  400. }
  401. default PageResult<T> selectPage(SortablePageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
  402. return selectPage(pageParam, pageParam.getSortingFields(), queryWrapper);
  403. }
  404. default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
  405. return selectPage(pageParam, null, queryWrapper);
  406. }
  407. default PageResult<T> selectPage(PageParam pageParam, Collection<SortingField> sortingFields,
  408. @Param("ew") Wrapper<T> queryWrapper) {
  409. // 特殊:不分页,直接查询全部
  410. if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) {
  411. List<T> list = selectList(queryWrapper);
  412. return new PageResult<>(list, (long) list.size());
  413. }
  414. // MyBatis Plus 查询
  415. IPage<T> mpPage = MyBatisUtils.buildPage(pageParam, sortingFields);
  416. selectPage(mpPage, queryWrapper);
  417. // 转换返回
  418. return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
  419. }
  420. // ========== 统计方法(基于 Lambda) ==========
  421. /**
  422. * 获取字段最大值(Lambda)
  423. */
  424. default Object selectMax(SFunction<T, ?> column) {
  425. String columnName = columnToString(column);
  426. return selectObjs(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>().select("MAX(" + columnName + ")")).stream().findFirst().orElse(null);
  427. }
  428. /**
  429. * 获取字段最小值(Lambda)
  430. */
  431. default Object selectMin(SFunction<T, ?> column) {
  432. String columnName = columnToString(column);
  433. return selectObjs(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>().select("MIN(" + columnName + ")")).stream().findFirst().orElse(null);
  434. }
  435. /**
  436. * 获取字段总和(Lambda)
  437. */
  438. default Object selectSum(SFunction<T, ?> column) {
  439. String columnName = columnToString(column);
  440. return selectObjs(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>().select("SUM(" + columnName + ")")).stream().findFirst().orElse(null);
  441. }
  442. /**
  443. * 获取字段平均值(Lambda)
  444. */
  445. default Object selectAvg(SFunction<T, ?> column) {
  446. String columnName = columnToString(column);
  447. return selectObjs(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>().select("AVG(" + columnName + ")")).stream().findFirst().orElse(null);
  448. }
  449. default <D> PageResult<D> selectJoinPage(PageParam pageParam, Class<D> clazz, MPJLambdaWrapper<T> lambdaWrapper) {
  450. // 特殊:不分页,直接查询全部
  451. if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageNo())) {
  452. List<D> list = selectJoinList(clazz, lambdaWrapper);
  453. return new PageResult<>(list, (long) list.size());
  454. }
  455. // MyBatis Plus Join 查询
  456. IPage<D> mpPage = MyBatisUtils.buildPage(pageParam);
  457. mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper);
  458. // 转换返回
  459. return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
  460. }
  461. default <DTO> PageResult<DTO> selectJoinPage(PageParam pageParam, Class<DTO> resultTypeClass,
  462. MPJBaseJoin<T> joinQueryWrapper) {
  463. IPage<DTO> mpPage = MyBatisUtils.buildPage(pageParam);
  464. selectJoinPage(mpPage, resultTypeClass, joinQueryWrapper);
  465. // 转换返回
  466. return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
  467. }
  468. }