001/*
002 *  Copyright (c) 2022-2025, 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.query;
018
019import com.mybatisflex.core.BaseMapper;
020import com.mybatisflex.core.paginate.Page;
021import com.mybatisflex.core.relation.RelationManager;
022import com.mybatisflex.core.util.LambdaGetter;
023import com.mybatisflex.core.util.LambdaUtil;
024import com.mybatisflex.core.util.SqlUtil;
025
026import java.util.Arrays;
027import java.util.List;
028import java.util.Optional;
029
030/**
031 * <p>链式 {@link BaseMapper} 查询。
032 *
033 * <p>要求实现类除了包含有 {@link BaseMapper} 接口的引用外,还必须具有 {@link QueryWrapper}
034 * 的查询条件构建功能。在使用时:
035 * <ul>
036 *     <li>通过 {@link #baseMapper()} 获取该实现类对应的 {@link BaseMapper} 引用。
037 *     <li>通过 {@link #toQueryWrapper()} 将该实现类转换为 {@link QueryWrapper} 对象。
038 * </ul>
039 *
040 * @param <T> 实体类类型
041 * @author 王帅
042 * @since 2023-08-08
043 */
044public interface MapperQueryChain<T> extends ChainQuery<T> {
045
046    /**
047     * 该实现类对应的 {@link BaseMapper} 对象。
048     *
049     * @return {@link BaseMapper}
050     */
051    BaseMapper<T> baseMapper();
052
053    /**
054     * 将该实现类转换为 {@link QueryWrapper} 对象。
055     *
056     * @return {@link QueryWrapper}
057     */
058    QueryWrapper toQueryWrapper();
059
060    /**
061     * 查询数据数量。
062     *
063     * @return 数据数量
064     */
065    default long count() {
066        return baseMapper().selectCountByQuery(toQueryWrapper());
067    }
068
069    /**
070     * 判断数据是否存在。
071     *
072     * @return {@code true} 数据存在,{@code false} 数据不存在
073     */
074    default boolean exists() {
075        return SqlUtil.toBool(count());
076    }
077
078    /**
079     * {@inheritDoc}
080     */
081    @Override
082    default T one() {
083        return baseMapper().selectOneByQuery(toQueryWrapper());
084    }
085
086    /**
087     * {@inheritDoc}
088     */
089    @Override
090    default <R> R oneAs(Class<R> asType) {
091        return baseMapper().selectOneByQueryAs(toQueryWrapper(), asType);
092    }
093
094    /**
095     * 获取第一列,且第一条数据。
096     *
097     * @return 第一列数据
098     */
099    default Object obj() {
100        return baseMapper().selectObjectByQuery(toQueryWrapper());
101    }
102
103    /**
104     * 获取第一列,且第一条数据并转换为指定类型,比如 {@code Long}, {@code String} 等。
105     *
106     * @param asType 接收数据类型
107     * @param <R>    接收数据类型
108     * @return 第一列数据
109     */
110    default <R> R objAs(Class<R> asType) {
111        return baseMapper().selectObjectByQueryAs(toQueryWrapper(), asType);
112    }
113
114    /**
115     * 获取第一列,且第一条数据,并封装为 {@link Optional} 返回。
116     *
117     * @return 第一列数据
118     */
119    default Optional<Object> objOpt() {
120        return Optional.ofNullable(obj());
121    }
122
123    /**
124     * 获取第一列,且第一条数据并转换为指定类型,比如 {@code Long}, {@code String}
125     * 等,封装为 {@link Optional} 返回。
126     *
127     * @param asType 接收数据类型
128     * @param <R>    接收数据类型
129     * @return 第一列数据
130     */
131    default <R> Optional<R> objAsOpt(Class<R> asType) {
132        return Optional.ofNullable(objAs(asType));
133    }
134
135    /**
136     * 获取第一列的所有数据。
137     *
138     * @return 第一列数据
139     */
140    default List<Object> objList() {
141        return baseMapper().selectObjectListByQuery(toQueryWrapper());
142    }
143
144    /**
145     * 获取第一列的所有数据,并转换为指定类型,比如 {@code Long}, {@code String} 等。
146     *
147     * @param asType 接收数据类型
148     * @param <R>    接收数据类型
149     * @return 第一列数据
150     */
151    default <R> List<R> objListAs(Class<R> asType) {
152        return baseMapper().selectObjectListByQueryAs(toQueryWrapper(), asType);
153    }
154
155    /**
156     * {@inheritDoc}
157     */
158    default List<T> list() {
159        return baseMapper().selectListByQuery(toQueryWrapper());
160    }
161
162    /**
163     * {@inheritDoc}
164     */
165    default <R> List<R> listAs(Class<R> asType) {
166        return baseMapper().selectListByQueryAs(toQueryWrapper(), asType);
167    }
168
169    /**
170     * {@inheritDoc}
171     */
172    default Page<T> page(Page<T> page) {
173        return baseMapper().paginate(page, toQueryWrapper());
174    }
175
176    /**
177     * {@inheritDoc}
178     */
179    default <R> Page<R> pageAs(Page<R> page, Class<R> asType) {
180        return baseMapper().paginateAs(page, toQueryWrapper(), asType);
181    }
182
183    /**
184     * 使用 {@code Fields Query} 的方式进行关联查询。
185     *
186     * @return {@code Fields Query} 查询
187     */
188    default FieldsBuilder<T> withFields() {
189        return new FieldsBuilder<>(this);
190    }
191
192    /**
193     * 使用 {@code Relations Query} 的方式进行关联查询。
194     *
195     * @return {@code Relations Query} 查询
196     */
197    default RelationsBuilder<T> withRelations() {
198        return new RelationsBuilder<>(this);
199    }
200
201    /**
202     * 使用 Relations Query 的方式进行关联查询。
203     * @param columns 需要关联的字段
204     * @return Relations Query 查询
205     */
206    default RelationsBuilder<T> withRelations(LambdaGetter<T>... columns) {
207        if(columns != null && columns.length > 0) {
208            String[] array = Arrays.stream(columns)
209                .map(LambdaUtil::getFieldName)
210                .toArray(String[]::new);
211            RelationManager.addQueryRelations(array);
212        }
213        return new RelationsBuilder<>(this);
214    }
215
216}