diff --git a/mybatis-flex-codegen/src/main/resources/templates/enjoy/serviceImpl.tpl b/mybatis-flex-codegen/src/main/resources/templates/enjoy/serviceImpl.tpl index edcb3693..c1669d7e 100644 --- a/mybatis-flex-codegen/src/main/resources/templates/enjoy/serviceImpl.tpl +++ b/mybatis-flex-codegen/src/main/resources/templates/enjoy/serviceImpl.tpl @@ -87,6 +87,30 @@ public class #(table.buildServiceImplClassName()) extends #(serviceImplConfig.bu return super.getOneAs(query, asType); } + @Override + @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") + public Object getObj(QueryWrapper query) { + return super.getObj(query); + } + + @Override + @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") + public R getObjAs(QueryWrapper query, Class asType) { + return super.getObjAs(query, asType); + } + + @Override + @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") + public List objList(QueryWrapper query) { + return super.objList(query); + } + + @Override + @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") + public List objListAs(QueryWrapper query, Class asType) { + return super.objListAs(query, asType); + } + @Override @Cacheable(key = "#root.methodName + ':' + #query.toSQL()") public List<#(entityClassName)> list(QueryWrapper query) { diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/service/IService.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/service/IService.java index 3504283e..64db3362 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/service/IService.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/service/IService.java @@ -46,8 +46,6 @@ public interface IService { int DEFAULT_BATCH_SIZE = 1000; - // ===== 保存(增)操作 ===== - /** *

获取对应实体类(Entity)的基础映射类(BaseMapper)。 * @@ -55,27 +53,18 @@ public interface IService { */ BaseMapper getMapper(); + // ===== 保存(增)操作 ===== + /** *

保存实体类对象数据。 * * @param entity 实体类对象 * @return {@code true} 保存成功,{@code false} 保存失败。 - * @apiNote 默认调用的是 {@link BaseMapper#insertSelective(Object)} 方法,忽略 - * {@code null} 字段的数据,使数据库配置的默认值生效。 + * @apiNote 默认调用的是 {@link BaseMapper#insertSelective(Object)} 方法,忽略实体类 + * {@code null} 属性的数据,使数据库配置的默认值生效。 */ default boolean save(T entity) { - return SqlUtil.toBool(getMapper().insertSelective(entity)); - } - - /** - *

保存或者更新实体类对象数据。 - * - * @param entity 实体类对象 - * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败。 - * @apiNote 如果实体类对象主键有值,则更新数据,若没有值,则保存数据。 - */ - default boolean saveOrUpdate(T entity) { - return SqlUtil.toBool(getMapper().insertOrUpdate(entity, true)); + return SqlUtil.toBool(getMapper().insert(entity, true)); } /** @@ -83,6 +72,8 @@ public interface IService { * * @param entities 实体类对象 * @return {@code true} 保存成功,{@code false} 保存失败。 + * @apiNote 默认调用的是 {@link BaseMapper#insertSelective(Object)} 方法,忽略实体类 + * {@code null} 属性的数据,使数据库配置的默认值生效。 */ default boolean saveBatch(Collection entities) { return saveBatch(entities, DEFAULT_BATCH_SIZE); @@ -94,10 +85,12 @@ public interface IService { * @param entities 实体类对象 * @param batchSize 每次保存切分的数量 * @return {@code true} 保存成功,{@code false} 保存失败。 + * @apiNote 默认调用的是 {@link BaseMapper#insertSelective(Object)} 方法,忽略实体类 + * {@code null} 属性的数据,使数据库配置的默认值生效。 */ default boolean saveBatch(Collection entities, int batchSize) { Class> usefulClass = (Class>) ClassUtil.getUsefulClass(getMapper().getClass()); - return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::insert)); + return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::insertSelective)); } /** @@ -105,7 +98,10 @@ public interface IService { * * @param entities 实体类对象 * @return {@code true} 保存成功,{@code false} 保存失败。 + * @deprecated 为保持 Service 层 API 一致性,默认方法都是忽略实体类 {@code null} 属性的数据。 + * 另外,该方法将在 1.6.0 版本被移除。 */ + @Deprecated default boolean saveBatchSelective(Collection entities) { return saveBatchSelective(entities, DEFAULT_BATCH_SIZE); } @@ -116,12 +112,53 @@ public interface IService { * @param entities 实体类对象 * @param batchSize 每次保存切分的数量 * @return {@code true} 保存成功,{@code false} 保存失败。 + * @deprecated 为保持 Service 层 API 一致性,默认方法都是忽略实体类 {@code null} 属性的数据。 + * 另外,该方法将在 1.6.0 版本被移除。 */ + @Deprecated default boolean saveBatchSelective(Collection entities, int batchSize) { Class> usefulClass = (Class>) ClassUtil.getUsefulClass(getMapper().getClass()); return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::insertSelective)); } + /** + *

保存或者更新实体类对象数据。 + * + * @param entity 实体类对象 + * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败。 + * @apiNote 如果实体类对象主键有值,则更新数据,若没有值,则保存数据,无论新增还是更新都会忽略实体类 + * {@code null} 属性的数据。 + */ + default boolean saveOrUpdate(T entity) { + return SqlUtil.toBool(getMapper().insertOrUpdate(entity, true)); + } + + /** + *

保存或者更新实体类对象数据。 + * + * @param entities 实体类对象 + * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败。 + * @apiNote 如果实体类对象主键有值,则更新数据,若没有值,则保存数据,无论新增还是更新都会忽略实体类 + * {@code null} 属性的数据。 + */ + default boolean saveOrUpdateBatch(Collection entities) { + return saveOrUpdateBatch(entities, DEFAULT_BATCH_SIZE); + } + + /** + *

保存或者更新实体类对象数据。 + * + * @param entities 实体类对象 + * @param batchSize 每次操作切分的数量 + * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败。 + * @apiNote 如果实体类对象主键有值,则更新数据,若没有值,则保存数据,无论新增还是更新都会忽略实体类 + * {@code null} 属性的数据。 + */ + default boolean saveOrUpdateBatch(Collection entities, int batchSize) { + Class> usefulClass = (Class>) ClassUtil.getUsefulClass(getMapper().getClass()); + return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::insertOrUpdateSelective)); + } + // ===== 删除(删)操作 ===== /** @@ -167,8 +204,6 @@ public interface IService { return SqlUtil.toBool(getMapper().deleteBatchByIds(ids)); } - // ===== 更新(改)操作 ===== - /** *

根据 {@link Map} 构建查询条件删除数据。 * @@ -183,6 +218,8 @@ public interface IService { return remove(query().where(query)); } + // ===== 更新(改)操作 ===== + /** *

根据数据主键更新数据。 * @@ -211,6 +248,7 @@ public interface IService { * @param entity 实体类对象 * @param query 查询条件 * @return {@code true} 更新成功,{@code false} 更新失败。 + * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 */ default boolean update(T entity, Map query) { return update(entity, query().where(query)); @@ -222,6 +260,7 @@ public interface IService { * @param entity 实体类对象 * @param query 查询条件 * @return {@code true} 更新成功,{@code false} 更新失败。 + * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 */ default boolean update(T entity, QueryWrapper query) { return SqlUtil.toBool(getMapper().updateByQuery(entity, query)); @@ -233,6 +272,7 @@ public interface IService { * @param entity 实体类对象 * @param condition 查询条件 * @return {@code true} 更新成功,{@code false} 更新失败。 + * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 */ default boolean update(T entity, QueryCondition condition) { return update(entity, query().where(condition)); @@ -243,6 +283,7 @@ public interface IService { * * @param entities 实体类对象集合 * @return boolean {@code true} 更新成功,{@code false} 更新失败。 + * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 */ default boolean updateBatch(Collection entities) { return updateBatch(entities, DEFAULT_BATCH_SIZE); @@ -254,13 +295,13 @@ public interface IService { * @param entities 实体类对象集合 * @param batchSize 每批次更新数量 * @return {@code true} 更新成功,{@code false} 更新失败。 + * @apiNote 若实体类属性数据为 {@code null},该属性不会新到数据库。 */ default boolean updateBatch(Collection entities, int batchSize) { Class> usefulClass = (Class>) ClassUtil.getUsefulClass(getMapper().getClass()); return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::update)); } - // ===== 查询(查)操作 ===== /** @@ -349,6 +390,70 @@ public interface IService { return Optional.ofNullable(getOne(condition)); } + /** + *

查询结果集中第一列,且第一条数据。 + * + * @param query 查询条件 + * @return 数据值 + */ + default Object getObj(QueryWrapper query) { + return getMapper().selectObjectByQuery(query); + } + + /** + *

查询结果集中第一列,且第一条数据,并封装为 {@link Optional} 返回。 + * + * @param query 查询条件 + * @return 数据值 + */ + default Optional getObjOpt(QueryWrapper query) { + return Optional.ofNullable(getObj(query)); + } + + /** + *

查询结果集中第一列,且第一条数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。 + * + * @param query 查询条件 + * @param asType 接收的数据类型 + * @return 数据值 + */ + default R getObjAs(QueryWrapper query, Class asType) { + return getMapper().selectObjectByQueryAs(query, asType); + } + + /** + *

查询结果集中第一列,且第一条数据,并转换为指定类型,比如 {@code Long}, {@code String} + * 等,封装为 {@link Optional} 返回。 + * + * @param query 查询条件 + * @param asType 接收的数据类型 + * @return 数据值 + */ + default Optional getObjAsOpt(QueryWrapper query, Class asType) { + return Optional.ofNullable(getObjAs(query, asType)); + } + + /** + *

查询结果集中第一列所有数据。 + * + * @param query 查询条件 + * @return 数据列表 + */ + default List objList(QueryWrapper query) { + return getMapper().selectObjectListByQuery(query); + } + + /** + *

查询结果集中第一列所有数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。 + * + * @param query 查询条件 + * @param asType 接收的数据类型 + * @return 数据列表 + */ + default List objListAs(QueryWrapper query, Class asType) { + return getMapper().selectObjectListByQueryAs(query, asType); + } + /** *

查询所有数据。 * @@ -428,7 +533,7 @@ public interface IService { * @return {@code true} 数据存在,{@code false} 数据不存在。 */ default boolean exists(QueryCondition condition) { - return CollectionUtil.isNotEmpty(getMapper().selectListByCondition(condition,1L)); + return CollectionUtil.isNotEmpty(getMapper().selectListByCondition(condition, 1L)); } /** diff --git a/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/FunctionSqlTest.java b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/FunctionSqlTest.java index 790fed6c..c6186c46 100644 --- a/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/FunctionSqlTest.java +++ b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/FunctionSqlTest.java @@ -52,4 +52,27 @@ public class FunctionSqlTest { System.out.println(sql); } + @Test + public void test03() { + String sql = QueryWrapper.create() + .select() + .from(ACCOUNT) + .where(upper(ACCOUNT.USER_NAME).likeRaw(raw("UPPER('ws')"))) + .toSQL(); + + System.out.println(sql); + } + + @Test + public void test04() { + String sql = QueryWrapper.create() + .select() + .from(ACCOUNT) +// .where("FIND_IN_SET(?, `id`)", 100) + .where(findInSet(number(100), ACCOUNT.ID).eq(true)) + .toSQL(); + + System.out.println(sql); + } + } diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleTester.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleTester.java index f195dd04..aeae9ef0 100644 --- a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleTester.java +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/ArticleTester.java @@ -77,10 +77,7 @@ public class ArticleTester { articles.add(article); } - Db.executeBatch(articles, ArticleMapper.class, (mapper, article) -> { - System.out.println("article: " + article); - mapper.insertSelective(article); - }); + Db.executeBatch(articles, ArticleMapper.class, ArticleMapper::insertOrUpdateSelective); articleMapper.selectAll().forEach(System.out::println); }