001/*
002 *  Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016
017package com.mybatisflex.core.activerecord;
018
019import com.mybatisflex.core.BaseMapper;
020import com.mybatisflex.core.activerecord.query.FieldsQuery;
021import com.mybatisflex.core.activerecord.query.QueryModel;
022import com.mybatisflex.core.activerecord.query.RelationsQuery;
023import com.mybatisflex.core.query.MapperQueryChain;
024import com.mybatisflex.core.query.QueryWrapper;
025import com.mybatisflex.core.query.RelationsBuilder;
026import com.mybatisflex.core.relation.RelationManager;
027import com.mybatisflex.core.util.LambdaGetter;
028import com.mybatisflex.core.util.LambdaUtil;
029import com.mybatisflex.core.util.SqlUtil;
030
031import java.io.Serializable;
032import java.util.Arrays;
033import java.util.Optional;
034
035/**
036 * Active Record 模型。
037 *
038 * @param <T> 实体类类型
039 * @author 王帅
040 * @since 2023-07-24
041 */
042@SuppressWarnings({"unused", "unchecked"})
043public abstract class Model<T extends Model<T>>
044    extends QueryModel<T>
045    implements MapperModel<T>, MapperQueryChain<T>, Serializable {
046
047    /**
048     * 根据实体类构建的条件删除数据。
049     *
050     * @return {@code true} 删除成功,{@code false} 删除失败
051     */
052    public boolean remove() {
053        return SqlUtil.toBool(baseMapper().deleteByQuery(queryWrapper()));
054    }
055
056    /**
057     * 根据实体类构建的条件删除数据,结果使用 {@link Optional} 返回源对象回调,删除成功返回
058     * {@code Optional.of(this)},删除失败返回 {@code Optional.empty()}。
059     *
060     * @return {@link Optional} 链式调用
061     */
062    public Optional<T> removeOpt() {
063        return remove() ? Optional.of((T) this) : Optional.empty();
064    }
065
066    /**
067     * 根据实体类构建的条件更新数据(自动忽略 {@code null} 值)。
068     *
069     * @return {@code true} 更新成功,{@code false} 更新失败
070     */
071    public boolean update() {
072        return update(true);
073    }
074
075    /**
076     * 根据实体类构建的条件更新数据(自动忽略 {@code null} 值),结果使用 {@link Optional}
077     * 返回源对象回调,更新成功返回 {@code Optional.of(this)},更新失败返回
078     * {@code Optional.empty()}。
079     *
080     * @return {@link Optional} 链式调用
081     */
082    public Optional<T> updateOpt() {
083        return updateOpt(true);
084    }
085
086    /**
087     * 根据实体类构建的条件更新数据,并设置是否忽略 {@code null} 值。
088     *
089     * @param ignoreNulls 是否忽略 {@code null} 值
090     * @return {@code true} 更新成功,{@code false} 更新失败
091     */
092    public boolean update(boolean ignoreNulls) {
093        return SqlUtil.toBool(baseMapper().updateByQuery((T) this, ignoreNulls, queryWrapper()));
094    }
095
096    /**
097     * 根据实体类构建的条件更新数据,并设置是否忽略 {@code null} 值,结果使用 {@link Optional}
098     * 返回源对象回调,更新成功返回 {@code Optional.of(this)},更新失败返回
099     * {@code Optional.empty()}。
100     *
101     * @param ignoreNulls 是否忽略 {@code null} 值
102     * @return {@link Optional} 链式调用
103     */
104    public Optional<T> updateOpt(boolean ignoreNulls) {
105        return update(ignoreNulls) ? Optional.of((T) this) : Optional.empty();
106    }
107
108    @Override
109    public BaseMapper<T> baseMapper() {
110        return MapperModel.super.baseMapper();
111    }
112
113    @Override
114    public QueryWrapper toQueryWrapper() {
115        return queryWrapper();
116    }
117
118    @Override
119    public FieldsQuery<T> withFields() {
120        return new FieldsQuery<>(this);
121    }
122
123    @Override
124    public RelationsQuery<T> withRelations() {
125        return new RelationsQuery<>(this);
126    }
127
128    @Override
129    public RelationsBuilder<T> withRelations(LambdaGetter<T>... columns) {
130        if(columns != null && columns.length > 0) {
131            String[] array = Arrays.stream(columns)
132                .map(LambdaUtil::getFieldName)
133                .toArray(String[]::new);
134            RelationManager.addQueryRelations(array);
135        }
136        return new RelationsBuilder<>(this);
137    }
138
139}