From abfd7d8bca40d2f71ea6a8c24db0fdaad67bf1c6 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:33:28 +0800 Subject: [PATCH 01/19] feat: CPI add addWhereQueryCondition method. --- .../src/main/java/com/mybatisflex/core/query/CPI.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/CPI.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/CPI.java index a5a45278..7875bb95 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/CPI.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/query/CPI.java @@ -125,6 +125,10 @@ public class CPI { return queryWrapper.getWhereQueryCondition(); } + public static void addWhereQueryCondition(QueryWrapper queryWrapper, QueryCondition queryCondition, SqlConnector connector) { + queryWrapper.addWhereQueryCondition(queryCondition, connector); + } + public static List getGroupByColumns(QueryWrapper queryWrapper) { return queryWrapper.getGroupByColumns(); } From b65175e1facc60df1c21c97e504afe6f1374427a Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:36:11 +0800 Subject: [PATCH 02/19] =?UTF-8?q?feat:=20Active=20Record=20=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=8C=85=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/activerecord/package-info.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/package-info.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/package-info.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/package-info.java new file mode 100644 index 00000000..e1cd4ffb --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Active Record 功能。 + */ +package com.mybatisflex.core.activerecord; From ef06e19857b1ca3558d6cc5a5a5bdac2da51ccda Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:36:37 +0800 Subject: [PATCH 03/19] feat: add MapperModel. --- .../core/activerecord/MapperModel.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java new file mode 100644 index 00000000..78b3cab4 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mybatisflex.core.activerecord; + +import com.mybatisflex.core.BaseMapper; +import com.mybatisflex.core.mybatis.Mappers; +import com.mybatisflex.core.table.TableInfo; +import com.mybatisflex.core.table.TableInfoFactory; +import com.mybatisflex.core.util.SqlUtil; + +import java.util.Optional; + +/** + * @param 实体类类型 + * @author 王帅 + * @since 2023-07-23 + */ +@SuppressWarnings({"unused", "unchecked"}) +public interface MapperModel { + + default BaseMapper baseMapper() { + return Mappers.ofEntityClass((Class) getClass()); + } + + default Object[] getPkValues() { + TableInfo tableInfo = TableInfoFactory.ofEntityClass(getClass()); + return tableInfo.buildPkSqlArgs(this); + } + + default boolean save() { + return save(true); + } + + default boolean save(boolean ignoreNulls) { + return SqlUtil.toBool(baseMapper().insert((T) this, ignoreNulls)); + } + + default boolean saveOrUpdate() { + return saveOrUpdate(true); + } + + default boolean saveOrUpdate(boolean ignoreNulls) { + return SqlUtil.toBool(baseMapper().insertOrUpdate((T) this, ignoreNulls)); + } + + default boolean removeById() { + return SqlUtil.toBool(baseMapper().deleteById(getPkValues())); + } + + default boolean updateById() { + return updateById(true); + } + + default boolean updateById(boolean ignoreNulls) { + return SqlUtil.toBool(baseMapper().update((T) this, ignoreNulls)); + } + + default T oneById() { + return baseMapper().selectOneById(getPkValues()); + } + + default Optional oneByIdOpt() { + return Optional.ofNullable(oneById()); + } + +} From c036a869da4c37ec37277715e99abea7663d3fb0 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:37:13 +0800 Subject: [PATCH 04/19] =?UTF-8?q?feat:=20=E6=9F=A5=E8=AF=A2=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E6=89=A9=E5=B1=95=E5=8C=85=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/activerecord/query/package-info.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/package-info.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/package-info.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/package-info.java new file mode 100644 index 00000000..ca0a2d88 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 条件查询功能。 + */ +package com.mybatisflex.core.activerecord.query; From a91987c4d3947b3f1cdc15cb223d0ba567d8cde6 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:37:33 +0800 Subject: [PATCH 05/19] feat: add WhereBuilder. --- .../core/activerecord/query/WhereBuilder.java | 351 ++++++++++++++++++ 1 file changed, 351 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/WhereBuilder.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/WhereBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/WhereBuilder.java new file mode 100644 index 00000000..d9693c5b --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/WhereBuilder.java @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mybatisflex.core.activerecord.query; + +import com.mybatisflex.core.query.CPI; +import com.mybatisflex.core.query.QueryColumn; +import com.mybatisflex.core.query.SqlConnector; +import com.mybatisflex.core.util.LambdaGetter; +import com.mybatisflex.core.util.LambdaUtil; + +import java.util.Collection; +import java.util.function.Predicate; + +/** + * @param + * @author 王帅 + * @since 2023-07-24 + */ +public class WhereBuilder> { + + private final R queryModel; + private final QueryColumn queryColumn; + private final SqlConnector connector; + + public WhereBuilder(R queryModel, QueryColumn queryColumn, SqlConnector connector) { + this.queryModel = queryModel; + this.queryColumn = queryColumn; + this.connector = connector; + } + + public R eq(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.eq(value), connector); + } + return queryModel; + } + + public R eq(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.eq(value, when), connector); + } + return queryModel; + } + + public R eq(LambdaGetter value) { + return eq(LambdaUtil.getQueryColumn(value)); + } + + public R eq(LambdaGetter value, Predicate when) { + return eq(LambdaUtil.getQueryColumn(value), when); + } + + public R ne(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.ne(value), connector); + } + return queryModel; + } + + public R ne(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.ne(value, when), connector); + } + return queryModel; + } + + public R ne(LambdaGetter value) { + return ne(LambdaUtil.getQueryColumn(value)); + } + + public R ne(LambdaGetter value, Predicate when) { + return ne(LambdaUtil.getQueryColumn(value), when); + } + + public R like(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.like(value), connector); + } + return queryModel; + } + + public R like(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.like(value, when), connector); + } + return queryModel; + } + + public R likeLeft(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.likeLeft(value), connector); + } + return queryModel; + } + + public R likeLeft(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.likeLeft(value, when), connector); + } + return queryModel; + } + + public R likeRight(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.likeRight(value), connector); + } + return queryModel; + } + + public R likeRight(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.likeRight(value, when), connector); + } + return queryModel; + } + + public R gt(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.gt(value), connector); + } + return queryModel; + } + + public R gt(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.gt(value, when), connector); + } + return queryModel; + } + + public R gt(LambdaGetter value) { + return gt(LambdaUtil.getQueryColumn(value)); + } + + public R gt(LambdaGetter value, Predicate when) { + return gt(LambdaUtil.getQueryColumn(value), when); + } + + public R ge(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.ge(value), connector); + } + return queryModel; + } + + public R ge(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.ge(value, when), connector); + } + return queryModel; + } + + public R ge(LambdaGetter value) { + return ge(LambdaUtil.getQueryColumn(value)); + } + + public R ge(LambdaGetter value, Predicate when) { + return ge(LambdaUtil.getQueryColumn(value), when); + } + + public R lt(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.lt(value), connector); + } + return queryModel; + } + + public R lt(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.lt(value, when), connector); + } + return queryModel; + } + + public R lt(LambdaGetter value) { + return lt(LambdaUtil.getQueryColumn(value)); + } + + public R lt(LambdaGetter value, Predicate when) { + return lt(LambdaUtil.getQueryColumn(value), when); + } + + public R le(Object value) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.le(value), connector); + } + return queryModel; + } + + public R le(Object value, Predicate when) { + if (value != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.le(value, when), connector); + } + return queryModel; + } + + public R le(LambdaGetter value) { + return le(LambdaUtil.getQueryColumn(value)); + } + + public R le(LambdaGetter value, Predicate when) { + return le(LambdaUtil.getQueryColumn(value), when); + } + + public R isNull() { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.isNull(), connector); + return queryModel; + } + + public R isNull(Predicate when) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.isNull(when), connector); + return queryModel; + } + + public R isNotNull() { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.isNotNull(), connector); + return queryModel; + } + + public R isNotNull(Predicate when) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.isNotNull(when), connector); + return queryModel; + } + + public R in(Object... arrays) { + if (arrays != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.in(arrays), connector); + } + return queryModel; + } + + public R in(Object[] arrays, Predicate when) { + //忽略 QueryWrapper.in("name", null) 的情况 + if (arrays != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.in(arrays, when), connector); + } + return queryModel; + } + + public R in(R queryModel) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.in(queryModel), connector); + } + return this.queryModel; + } + + public R in(R queryModel, Predicate when) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.in(queryModel, when), connector); + } + return this.queryModel; + } + + public R in(Collection collection) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.in(collection), connector); + } + return queryModel; + } + + public R in(Collection collection, Predicate when) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.in(collection, when), connector); + } + return queryModel; + } + + public R notIn(Object... arrays) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.notIn(arrays), connector); + } + return queryModel; + } + + public R notIn(Object[] arrays, Predicate when) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.notIn(arrays, when), connector); + } + return queryModel; + } + + public R notIn(Collection collection) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.notIn(collection), connector); + } + return queryModel; + } + + public R notIn(Collection collection, Predicate when) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.notIn(collection, when), connector); + } + return queryModel; + } + + public R notIn(R queryModel) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.notIn(queryModel), connector); + } + return this.queryModel; + } + + public R notIn(R queryModel, Predicate when) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.notIn(queryModel, when), connector); + } + return this.queryModel; + } + + public R between(Object start, Object end) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.between(start, end), connector); + } + return queryModel; + } + + public R between(Object start, Object end, Predicate when) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.between(start, end, when), connector); + } + return queryModel; + } + + public R notBetween(Object start, Object end) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.notBetween(start, end), connector); + } + return queryModel; + } + + public R notBetween(Object start, Object end, Predicate when) { + if (queryModel != null) { + CPI.addWhereQueryCondition(queryModel.getQueryWrapper(), queryColumn.notBetween(start, end, when), connector); + } + return queryModel; + } + +} From 7df2e13832d680532ee5e6c675c96c601cb93498 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:37:47 +0800 Subject: [PATCH 06/19] feat: add OrderByBuilder. --- .../activerecord/query/OrderByBuilder.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/OrderByBuilder.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/OrderByBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/OrderByBuilder.java new file mode 100644 index 00000000..32cb301b --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/OrderByBuilder.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mybatisflex.core.activerecord.query; + + +import com.mybatisflex.core.query.QueryColumn; +import com.mybatisflex.core.util.LambdaGetter; +import com.mybatisflex.core.util.LambdaUtil; + +/** + * 排序字段构建器 + * + * @author michael + */ +public class OrderByBuilder> { + + private final R queryModel; + private final QueryColumn queryColumn; + + public OrderByBuilder(R queryModel, LambdaGetter getter) { + this.queryModel = queryModel; + this.queryColumn = LambdaUtil.getQueryColumn(getter); + } + + public R asc() { + return queryModel.orderBy(queryColumn.asc()); + } + + public R desc() { + return queryModel.orderBy(queryColumn.desc()); + } + +} From 8832da5cafa33e42953981d6191217bf46e3f8d1 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:40:27 +0800 Subject: [PATCH 07/19] feat: add QueryModel. --- .../core/activerecord/query/QueryModel.java | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java new file mode 100644 index 00000000..e1a45b48 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mybatisflex.core.activerecord.query; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.core.query.*; +import com.mybatisflex.core.util.LambdaGetter; +import com.mybatisflex.core.util.LambdaUtil; + +/** + * @author 王帅 + * @since 2023-07-24 + */ +@SuppressWarnings({"unused", "unchecked"}) +public abstract class QueryModel> { + + @Column(ignore = true) + private QueryWrapper queryWrapper; + + protected QueryWrapper getQueryWrapper() { + if (queryWrapper == null) { + queryWrapper = QueryWrapper.create(this); + } + return queryWrapper; + } + + public T select() { + return (T) this; + } + + public T select(String... columns) { + getQueryWrapper().select(columns); + return (T) this; + } + + public T select(QueryColumn... queryColumns) { + getQueryWrapper().select(queryColumns); + return (T) this; + } + + public T select(LambdaGetter... columns) { + getQueryWrapper().select(columns); + return (T) this; + } + + public T select(QueryColumn[]... queryColumns) { + getQueryWrapper().select(queryColumns); + return (T) this; + } + + public T where(QueryCondition queryCondition) { + getQueryWrapper().where(queryCondition); + return (T) this; + } + + public T where(String sql) { + getQueryWrapper().where(sql); + return (T) this; + } + + public T where(String sql, Object... params) { + getQueryWrapper().where(sql, params); + return (T) this; + } + + public WhereBuilder where(LambdaGetter column) { + return new WhereBuilder<>((T) this, LambdaUtil.getQueryColumn(column), SqlConnector.AND); + } + + public T and(QueryCondition queryCondition) { + getQueryWrapper().and(queryCondition); + return (T) this; + } + + public T and(String sql) { + getQueryWrapper().and(sql); + return (T) this; + } + + public T and(String sql, Object... params) { + getQueryWrapper().and(sql, params); + return (T) this; + } + + public WhereBuilder and(LambdaGetter column) { + return new WhereBuilder<>((T) this, LambdaUtil.getQueryColumn(column), SqlConnector.AND); + } + + public T or(QueryCondition queryCondition) { + getQueryWrapper().or(queryCondition); + return (T) this; + } + + public T or(String sql) { + getQueryWrapper().or(sql); + return (T) this; + } + + public T or(String sql, Object... params) { + getQueryWrapper().or(sql, params); + return (T) this; + } + + public WhereBuilder or(LambdaGetter column) { + return new WhereBuilder<>((T) this, LambdaUtil.getQueryColumn(column), SqlConnector.OR); + } + + public T groupBy(String... names) { + getQueryWrapper().groupBy(names); + return (T) this; + } + + public T groupBy(QueryColumn... columns) { + getQueryWrapper().groupBy(columns); + return (T) this; + } + + public T groupBy(LambdaGetter... columns) { + getQueryWrapper().groupBy(columns); + return (T) this; + } + + public T having(QueryCondition queryCondition) { + getQueryWrapper().having(queryCondition); + return (T) this; + } + + public T orderBy(QueryOrderBy... orderBys) { + getQueryWrapper().orderBy(orderBys); + return (T) this; + } + + public T orderBy(String... orderBys) { + getQueryWrapper().orderBy(orderBys); + return (T) this; + } + + public OrderByBuilder orderBy(LambdaGetter column) { + return new OrderByBuilder<>((T) this, column); + } + + public T limit(Integer rows) { + getQueryWrapper().limit(rows); + return (T) this; + } + + public T offset(Integer offset) { + getQueryWrapper().offset(offset); + return (T) this; + } + + public T limit(Integer offset, Integer rows) { + getQueryWrapper().limit(offset, rows); + return (T) this; + } + +} From 1f0e70528facbf850d96f87be112e2b17e9a84e9 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:40:38 +0800 Subject: [PATCH 08/19] feat: add Model. --- .../mybatisflex/core/activerecord/Model.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java new file mode 100644 index 00000000..e9e46eca --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.mybatisflex.core.activerecord; + +import com.mybatisflex.core.activerecord.query.QueryModel; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.util.SqlUtil; + +import java.util.List; +import java.util.Optional; + +/** + * @param 实体类类型 + * @author 王帅 + * @since 2023-07-24 + */ +@SuppressWarnings({"unused", "unchecked"}) +public abstract class Model> + extends QueryModel + implements MapperModel { + + public boolean remove() { + return SqlUtil.toBool(baseMapper().deleteByQuery(getQueryWrapper())); + } + + public boolean update() { + return update(true); + } + + public boolean update(boolean ignoreNulls) { + return SqlUtil.toBool(baseMapper().updateByQuery((T) this, ignoreNulls, getQueryWrapper())); + } + + public long count() { + return baseMapper().selectCountByQuery(getQueryWrapper()); + } + + public boolean exists() { + return SqlUtil.toBool(count()); + } + + public T one() { + return baseMapper().selectOneByQuery(getQueryWrapper()); + } + + public Optional oneOpt() { + return Optional.ofNullable(one()); + } + + public List list() { + return baseMapper().selectListByQuery(getQueryWrapper()); + } + + public Page page(Page page) { + return baseMapper().paginate(page, getQueryWrapper()); + } + +} From ff5d19099773c21707a36cb300042794404af52c Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:44:52 +0800 Subject: [PATCH 09/19] =?UTF-8?q?refactor:=20Active=20Record=20=E9=93=BE?= =?UTF-8?q?=E5=BC=8F=E6=A8=A1=E5=9E=8B=E7=B1=BB=E6=9E=84=E5=BB=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/mybatisflex/test/model/Good.java | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/Good.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/Good.java index 87d9def7..e95742c9 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/Good.java +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/main/java/com/mybatisflex/test/model/Good.java @@ -17,7 +17,9 @@ package com.mybatisflex.test.model; import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; import com.mybatisflex.annotation.Table; +import com.mybatisflex.core.activerecord.Model; import java.util.Objects; @@ -28,35 +30,42 @@ import java.util.Objects; * @since 2023-06-07 */ @Table("tb_good") -public class Good { +public class Good extends Model { - @Id + @Id(keyType = KeyType.Auto) private Integer goodId; private String name; - private double price; + private Double price; + + public static Good create() { + return new Good(); + } public Integer getGoodId() { return goodId; } - public void setGoodId(Integer goodId) { + public Good setGoodId(Integer goodId) { this.goodId = goodId; + return this; } public String getName() { return name; } - public void setName(String name) { + public Good setName(String name) { this.name = name; + return this; } - public double getPrice() { + public Double getPrice() { return price; } - public void setPrice(double price) { + public Good setPrice(Double price) { this.price = price; + return this; } @Override @@ -79,23 +88,20 @@ public class Good { Good good = (Good) o; - if (Double.compare(good.price, price) != 0) { - return false; - } if (!Objects.equals(goodId, good.goodId)) { return false; } - return Objects.equals(name, good.name); + if (!Objects.equals(name, good.name)) { + return false; + } + return Objects.equals(price, good.price); } @Override public int hashCode() { - int result; - long temp; - result = goodId != null ? goodId.hashCode() : 0; + int result = goodId != null ? goodId.hashCode() : 0; result = 31 * result + (name != null ? name.hashCode() : 0); - temp = Double.doubleToLongBits(price); - result = 31 * result + (int) (temp ^ (temp >>> 32)); + result = 31 * result + (price != null ? price.hashCode() : 0); return result; } From 94ba44a1a43a6144f1300cd186f2197c77ffc1c4 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 11:45:24 +0800 Subject: [PATCH 10/19] =?UTF-8?q?test:=20Active=20Record=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/mapper/ActiveRecordTest.java | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/ActiveRecordTest.java b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/ActiveRecordTest.java index 17bd1675..61d45f33 100644 --- a/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/ActiveRecordTest.java +++ b/mybatis-flex-test/mybatis-flex-spring-boot-test/src/test/java/com/mybatisflex/test/mapper/ActiveRecordTest.java @@ -19,9 +19,12 @@ package com.mybatisflex.test.mapper; import com.mybatisflex.core.mybatis.Mappers; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.test.model.Good; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import static com.mybatisflex.test.model.table.GoodTableDef.GOOD; + /** * @author 王帅 * @since 2023-07-23 @@ -31,12 +34,75 @@ class ActiveRecordTest { @Test void testMapper() { - Good good = new Good(); - good.setPrice(28); + Good good = Good.create(); - GoodMapper goodMapper = Mappers.ofMapperClass(GoodMapper.class); + good.setPrice(28.0); + + GoodMapper goodMapper = (GoodMapper) Mappers.ofEntityClass(Good.class); goodMapper.selectListByQuery(QueryWrapper.create(good)); } + @Test + void testInsert() { + boolean saved = Good.create() + .setPrice(28.0) + .setName("摆渡人") + .save(); + + Assertions.assertTrue(saved); + } + + @Test + void testUpdate() { + Good.create() + .setGoodId(11) + .setPrice(38.0) + .updateById(); + } + + @Test + void testDelete() { + boolean removed = Good.create() + .setGoodId(1) + .removeById(); + + Assertions.assertTrue(removed); + } + + @Test + void testSelectById() { + Good good = Good.create() + .setGoodId(11) + .oneById(); + + System.out.println(good); + } + + @Test + void testSelectOne() { + Good good1 = Good.create() + .setName("摆渡人") + .one(); + + Good good2 = Good.create() + .where(GOOD.NAME.eq("摆渡人")) + .one(); + + Good good3 = Good.create() + .where(Good::getName).eq("摆渡人") + .one(); + + Assertions.assertEquals(good1, good2); + Assertions.assertEquals(good1, good3); + } + + @Test + void testSelectList() { + Good.create() + .where(GOOD.PRICE.ge(28.0)) + .list() + .forEach(System.out::println); + } + } From 3a9dbf5d681841e7bbd2272d262acf318437d6da Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 12:06:44 +0800 Subject: [PATCH 11/19] style: add MapperModel javadoc. --- .../core/activerecord/MapperModel.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java index 78b3cab4..c0a6f465 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java @@ -25,6 +25,11 @@ import com.mybatisflex.core.util.SqlUtil; import java.util.Optional; /** + *

使用 {@link BaseMapper} 进行 CRUD 操作的实体类的抽象接口。 + * + *

使用接口是为了方便拓展,该接口提供了简单的根据 主键 操作数据的方法, + * 实现类可以进行其他方法的扩展。 + * * @param 实体类类型 * @author 王帅 * @since 2023-07-23 @@ -32,47 +37,117 @@ import java.util.Optional; @SuppressWarnings({"unused", "unchecked"}) public interface MapperModel { + /** + *

获取实体类对应的 {@link BaseMapper} 接口。 + * + *

可以拓展该方法提高效率,例如: + *

{@code
+     * return AccountMapper.class;
+     * }
+ * + * @return {@link BaseMapper} 接口 + */ default BaseMapper baseMapper() { return Mappers.ofEntityClass((Class) getClass()); } + /** + *

获取实体类主键数据。 + * + *

可以拓展该方法提高效率,例如: + *

{@code
+     * return new Object[]{id};
+     * }
+ * + * @return 主键数据数组 + */ default Object[] getPkValues() { TableInfo tableInfo = TableInfoFactory.ofEntityClass(getClass()); return tableInfo.buildPkSqlArgs(this); } + /** + * 保存数据(自动忽略 {@code null} 值)。 + * + * @return {@code true} 保存成功,{@code false} 保存失败 + */ default boolean save() { return save(true); } + /** + * 保存数据,并设置是否忽略 {@code null} 值。 + * + * @param ignoreNulls 是否忽略 {@code null} 值 + * @return {@code true} 保存成功,{@code false} 保存失败 + */ default boolean save(boolean ignoreNulls) { return SqlUtil.toBool(baseMapper().insert((T) this, ignoreNulls)); } + /** + * 保存或者更新数据,如果实体类主键没有值,则 保存 数据;如果实体类主键有值,则 + * 更新 数据(全部自动忽略 {@code null} 值)。 + * + * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败 + */ default boolean saveOrUpdate() { return saveOrUpdate(true); } + /** + * 保存或者更新数据,如果实体类主键没有值,则 保存 数据;如果实体类主键有值,则 + * 更新 数据,并设置是否忽略 {@code null} 值。 + * + * @param ignoreNulls 是否忽略 {@code null} 值 + * @return {@code true} 保存或更新成功,{@code false} 保存或更新失败 + */ default boolean saveOrUpdate(boolean ignoreNulls) { return SqlUtil.toBool(baseMapper().insertOrUpdate((T) this, ignoreNulls)); } + /** + * 根据实体类主键删除数据。 + * + * @return {@code true} 删除成功,{@code false} 删除失败 + */ default boolean removeById() { return SqlUtil.toBool(baseMapper().deleteById(getPkValues())); } + /** + * 根据实体类主键更新数据(自动忽略 {@code null} 值)。 + * + * @return {@code true} 更新成功,{@code false} 更新失败 + */ default boolean updateById() { return updateById(true); } + /** + * 根据实体类主键更新数据,并设置是否忽略 {@code null} 值。 + * + * @param ignoreNulls 是否忽略 {@code null} 值 + * @return {@code true} 更新成功,{@code false} 更新失败 + */ default boolean updateById(boolean ignoreNulls) { return SqlUtil.toBool(baseMapper().update((T) this, ignoreNulls)); } + /** + * 根据实体类主键获取一条数据。 + * + * @return 数据 + */ default T oneById() { return baseMapper().selectOneById(getPkValues()); } + /** + * 根据实体类主键获取一条数据,并封装为 {@link Optional} 返回。 + * + * @return 数据 + */ default Optional oneByIdOpt() { return Optional.ofNullable(oneById()); } From cd8ce808d2a25890e52181e4916956113dafda02 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 12:30:15 +0800 Subject: [PATCH 12/19] style: add OrderByBuilder javadoc. --- .../mybatisflex/core/activerecord/query/OrderByBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/OrderByBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/OrderByBuilder.java index 32cb301b..7287001a 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/OrderByBuilder.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/OrderByBuilder.java @@ -21,9 +21,10 @@ import com.mybatisflex.core.util.LambdaGetter; import com.mybatisflex.core.util.LambdaUtil; /** - * 排序字段构建器 + * Lambda 排序构建器。 * - * @author michael + * @author 王帅 + * @since 2023-07-25 */ public class OrderByBuilder> { From 34e6685ae89a9e3b7e0c7dc7b25dab27eb778e46 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 12:30:26 +0800 Subject: [PATCH 13/19] style: add WhereBuilder javadoc. --- .../com/mybatisflex/core/activerecord/query/WhereBuilder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/WhereBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/WhereBuilder.java index d9693c5b..285429d6 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/WhereBuilder.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/WhereBuilder.java @@ -25,7 +25,8 @@ import java.util.Collection; import java.util.function.Predicate; /** - * @param + * Lambda 条件构建器。 + * * @author 王帅 * @since 2023-07-24 */ From 26efb7cb664e60d990eb44fb8b8831b5f06dfb72 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 12:30:35 +0800 Subject: [PATCH 14/19] style: add QueryModel javadoc. --- .../mybatisflex/core/activerecord/query/QueryModel.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java index e1a45b48..29fd527e 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java @@ -22,6 +22,13 @@ import com.mybatisflex.core.util.LambdaGetter; import com.mybatisflex.core.util.LambdaUtil; /** + *

实体类条件查询构建模型。 + * + *

该类内部维护了一个 {@link QueryWrapper} 属性,用来构建查询条件。 + * 通过实体类属性构建的查询条件都是值等于,该扩展用于非等于值构建,及一些其他方法。 + * 如果不想通过实体类直接构建查询条件,可以不继承该类。 + * + * @param 实体类类型 * @author 王帅 * @since 2023-07-24 */ From 9e82a0ac12ff5f8319673f3864e7782eb69c803a Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 12:30:43 +0800 Subject: [PATCH 15/19] style: add Model javadoc. --- .../mybatisflex/core/activerecord/Model.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java index e9e46eca..2887bbc2 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java @@ -24,6 +24,8 @@ import java.util.List; import java.util.Optional; /** + * Active Record 模型。 + * * @param 实体类类型 * @author 王帅 * @since 2023-07-24 @@ -33,38 +35,85 @@ public abstract class Model> extends QueryModel implements MapperModel { + /** + * 根据实体类构建的条件删除数据。 + * + * @return {@code true} 删除成功,{@code false} 删除失败 + */ public boolean remove() { return SqlUtil.toBool(baseMapper().deleteByQuery(getQueryWrapper())); } + /** + * 根据实体类构建的条件更新数据(自动忽略 {@code null} 值)。 + * + * @return {@code true} 更新成功,{@code false} 更新失败 + */ public boolean update() { return update(true); } + /** + * 根据实体类构建的条件更新数据,并设置是否忽略 {@code null} 值。 + * + * @param ignoreNulls 是否忽略 {@code null} 值 + * @return {@code true} 更新成功,{@code false} 更新失败 + */ public boolean update(boolean ignoreNulls) { return SqlUtil.toBool(baseMapper().updateByQuery((T) this, ignoreNulls, getQueryWrapper())); } + /** + * 根据实体类构建的条件查询数据数量。 + * + * @return 数据数量 + */ public long count() { return baseMapper().selectCountByQuery(getQueryWrapper()); } + /** + * 根据实体类构建的条件判断数据是否存在。 + * + * @return {@code true} 数据存在,{@code false} 数据不存在 + */ public boolean exists() { return SqlUtil.toBool(count()); } + /** + * 根据实体类构建的条件获取一条数据。 + * + * @return 数据 + */ public T one() { return baseMapper().selectOneByQuery(getQueryWrapper()); } + /** + * 根据实体类构建的条件获取一条数据,并封装为 {@link Optional} 返回。 + * + * @return 数据 + */ public Optional oneOpt() { return Optional.ofNullable(one()); } + /** + * 根据实体类构建的条件获取多条数据。 + * + * @return 数据列表 + */ public List list() { return baseMapper().selectListByQuery(getQueryWrapper()); } + /** + * 根据实体类构建的条件获取分页数据。 + * + * @param page 分页对象 + * @return 分页数据 + */ public Page page(Page page) { return baseMapper().paginate(page, getQueryWrapper()); } From 9633a2866efe44c88244b4816aa65ce912027f21 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 12:31:27 +0800 Subject: [PATCH 16/19] =?UTF-8?q?refactor:=20=E6=95=B0=E6=8D=AE=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=92=8C=E6=9F=A5=E8=AF=A2=E9=9C=80=E8=A6=81=E5=88=86?= =?UTF-8?q?=E7=A6=BB=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mybatisflex/core/activerecord/query/QueryModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java index 29fd527e..ece914c4 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/query/QueryModel.java @@ -40,7 +40,7 @@ public abstract class QueryModel> { protected QueryWrapper getQueryWrapper() { if (queryWrapper == null) { - queryWrapper = QueryWrapper.create(this); + queryWrapper = QueryWrapper.create(); } return queryWrapper; } From 5555a286f86285be4984e1e67c60909a5016a2f8 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 12:32:11 +0800 Subject: [PATCH 17/19] =?UTF-8?q?fix:=20=E6=9F=A5=E8=AF=A2=E4=B8=80?= =?UTF-8?q?=E6=9D=A1=E6=95=B0=E6=8D=AE=E6=95=B0=E6=8D=AE=E9=99=90=E5=88=B6?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/mybatisflex/core/activerecord/Model.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java index 2887bbc2..d0d17efb 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java @@ -87,7 +87,7 @@ public abstract class Model> * @return 数据 */ public T one() { - return baseMapper().selectOneByQuery(getQueryWrapper()); + return baseMapper().selectOneByQuery(getQueryWrapper().limit(1)); } /** From 98696adeededab1b06b474181ff307b6e01609fc Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 13:32:08 +0800 Subject: [PATCH 18/19] =?UTF-8?q?fix:=20Javadoc=20=E6=8F=8F=E8=BF=B0?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mybatisflex/core/activerecord/MapperModel.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java index c0a6f465..1b4e7431 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/MapperModel.java @@ -38,12 +38,7 @@ import java.util.Optional; public interface MapperModel { /** - *

获取实体类对应的 {@link BaseMapper} 接口。 - * - *

可以拓展该方法提高效率,例如: - *

{@code
-     * return AccountMapper.class;
-     * }
+ * 获取实体类对应的 {@link BaseMapper} 接口。 * * @return {@link BaseMapper} 接口 */ From 8c91f9554c27097b3096b2d14980b8155193aa05 Mon Sep 17 00:00:00 2001 From: Suomm <1474983351@qq.com> Date: Tue, 25 Jul 2023 13:34:51 +0800 Subject: [PATCH 19/19] =?UTF-8?q?doc:=20Active=20Record=20=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vitepress/config.ts | 1 + docs/zh/base/active-record.md | 141 ++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 docs/zh/base/active-record.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 7bb627d8..b0277067 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -63,6 +63,7 @@ export default defineConfig({ {text: 'QueryWrapper', link: '/zh/base/querywrapper'}, {text: 'QueryWrapperChain', link: '/zh/base/query-wrapper-chain'}, {text: 'Db + Row', link: '/zh/base/db-row'}, + {text: 'Active Record', link: '/zh/base/active-record'}, {text: 'IService', link: '/zh/base/service'}, {text: 'SpringBoot 配置文件', link: '/zh/base/configuration'}, {text: 'MyBatisFlexCustomizer', link: '/zh/base/mybatis-flex-customizer'}, diff --git a/docs/zh/base/active-record.md b/docs/zh/base/active-record.md new file mode 100644 index 00000000..d8148ba7 --- /dev/null +++ b/docs/zh/base/active-record.md @@ -0,0 +1,141 @@ +# Active Record + +[Active Record 模式](http://www.martinfowler.com/eaaCatalog/activeRecord.html)出自 Martin Fowler +写的《[企业应用架构模式](https://book.douban.com/subject/4826290/)》书中。在 Active Record +模式中,对象中既有持久存储的数据,也有针对数据的操作。Active Record 模式把数据存取逻辑作为对象的一部分,处理对象的用户知道如何把数据写入数据库,还知道如何从数据库中读出数据。 + +在 MyBatis-Flex 中实现 Active Record +功能十分简单,只需继承 [Model](https://gitee.com/mybatis-flex/mybatis-flex/blob/main/mybatis-flex-core/src/main/java/com/mybatisflex/core/activerecord/Model.java) +即可。 + +::: tip 注意事项 + +- 使用 Active Record 功能时,项目中必须注入对应实体类的 BaseMapper 对象! +- 如果不想手动创建 Mapper 接口,可以使用 [APT](../others/apt.md#配置文件和选项) 辅助生成。 + ::: + +## 使用示例 + +在以下示例当中,使用了 [Lombok](https://www.projectlombok.org/) 对实体类进行了增强,以便我们全链式调用: + +1. `@Table` 标记了实体类对应的数据表。 +2. `@Data` 为我们生成了 setter/getter、toString、equals、hashCode 等方法, + 其中 `staticConstructor = "create"` 为我们创建了一个 `create()` 静态方法用于链式调用。 +3. `@Accessors(chain = true)` 为我们开启了 `return this;` 这样既可以被序列化,又可以链式调用。 + +```java + +@Table("tb_account") +@Accessors(chain = true) +@Data(staticConstructor = "create") +public class Account extends Model { + + @Id(keyType = KeyType.Auto) + private Long id; + private String userName; + private Integer age; + private Date birthday; + +} +``` + +这样我们就可以流畅的使用 Active Record 功能了: + +```java +@RestController +@RequestMapping("/account") +public class AccountController { + + @PostMapping("save") + public boolean save(@RequestBody Account account) { + return account.save(); + } + +} +``` + +## 保存数据 + +`Model` 提供了 `save` 方法来保存数据,调用该方法前需要将保存数据填充: + +```java +Account.create() + .setUserName("张三") + .setAge(18) + .setBirthday(new Date()) + .save(); +``` + +## 删除数据 + +`Model` 提供了 `remove` 方法来删除数据: + +- 根据主键删除 + +```java +Account.create() + .setId(1L) + .removeById(); +``` + +- 根据条件删除 + +```java +Account.create() + .where(Account::getId).eq(1L) + .remove(); +``` + +## 更新数据 + +`Model` 提供了 `update` 方法来更新数据,调用该方法前需要将更新数据填充: + +- 根据主键更新 + +```java +Account.create() + .setId(1L) + .setAge(100) + .updateById(); +``` + +- 根据条件更新 + +```java +Account.create() + .setAge(100) + .where(Account::getId).eq(1L) + .update(); +``` + +## 查询数据 + +### 查询一条数据 + +`Model` 提供了 `one` 方法来查询一条数据: + +```java +Account.create() + .where(Account::getId).eq(1L) + .one(); +``` + +### 查询多条数据 + +`Model` 提供了 `list` 方法来查询多条数据: + +```java +Account.create() + .where(Account::getAge).ge(18) + .list(); +``` + +### 查询分页数据 + +`Model` 提供了 `page` 方法来查询分页数据: + +```java +Account.create() + .where(Account::getAge).ge(18) + .page(Page.of(1,10)); +```