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.row; 018 019import com.mybatisflex.core.exception.FlexExceptions; 020import com.mybatisflex.core.paginate.Page; 021import com.mybatisflex.core.query.QueryColumn; 022import com.mybatisflex.core.query.QueryTable; 023import com.mybatisflex.core.query.QueryWrapper; 024import com.mybatisflex.core.query.QueryWrapperAdapter; 025import com.mybatisflex.core.table.ColumnInfo; 026import com.mybatisflex.core.table.IdInfo; 027import com.mybatisflex.core.table.TableInfo; 028import com.mybatisflex.core.table.TableInfoFactory; 029import com.mybatisflex.core.update.PropertySetter; 030import com.mybatisflex.core.util.FieldWrapper; 031import com.mybatisflex.core.util.LambdaGetter; 032import com.mybatisflex.core.util.SqlUtil; 033 034import java.util.ArrayList; 035import java.util.List; 036import java.util.Map; 037import java.util.Optional; 038import java.util.stream.Collectors; 039 040/** 041 * 链式构建 {@link QueryWrapper} 并执行 {@link Db} 方法。 042 * 043 * @author 王帅 044 * @since 2023-07-22 045 */ 046public class DbChain extends QueryWrapperAdapter<DbChain> implements PropertySetter<DbChain> { 047 048 private final String schema; 049 private final String tableName; 050 private Row rowData; 051 052 private DbChain(String tableName) { 053 this(null, tableName); 054 } 055 056 private DbChain(String schema, String tableName) { 057 this.schema = schema; 058 this.tableName = tableName; 059 this.queryTables = new ArrayList<>(); 060 this.queryTables.add(new QueryTable(schema, tableName)); 061 } 062 063 public static DbChain create() { 064 throw new UnsupportedOperationException("Please use DbChain#table(...) to replace DbChain.create()"); 065 } 066 067 public static DbChain create(Object entity) { 068 throw new UnsupportedOperationException("Please use DbChain#table(...) to replace DbChain.create(entity)"); 069 } 070 071 public static DbChain table(String tableName) { 072 return new DbChain(tableName); 073 } 074 075 public static DbChain table(String schema, String tableName) { 076 return new DbChain(schema, tableName); 077 } 078 079 public static DbChain table(Class<?> entityClass) { 080 TableInfo tableInfo = TableInfoFactory.ofEntityClass(entityClass); 081 return table(tableInfo.getSchema(), tableInfo.getTableName()); 082 } 083 084 public static DbChain table(QueryTable queryTable) { 085 return table(queryTable.getSchema(), queryTable.getName()); 086 } 087 088 private Row getRow() { 089 if (rowData == null) { 090 this.rowData = new Row(); 091 } 092 return rowData; 093 } 094 095 public DbChain setId(RowKey rowKey) { 096 getRow().getPrimaryKeys().add(rowKey); 097 return this; 098 } 099 100 public DbChain setId(RowKey rowKey, Object value) { 101 getRow().getPrimaryKeys().add(rowKey); 102 getRow().put(rowKey.keyColumn, value); 103 return this; 104 } 105 106 @Override 107 public DbChain set(String property, Object value, boolean isEffective) { 108 getRow().set(property, value, isEffective); 109 return this; 110 } 111 112 @Override 113 public DbChain set(QueryColumn property, Object value, boolean isEffective) { 114 getRow().set(property, value, isEffective); 115 return this; 116 } 117 118 @Override 119 public <T> DbChain set(LambdaGetter<T> property, Object value, boolean isEffective) { 120 getRow().set(property, value, isEffective); 121 return this; 122 } 123 124 @Override 125 public DbChain setRaw(String property, Object value, boolean isEffective) { 126 getRow().setRaw(property, value, isEffective); 127 return this; 128 } 129 130 @Override 131 public DbChain setRaw(QueryColumn property, Object value, boolean isEffective) { 132 getRow().setRaw(property, value, isEffective); 133 return this; 134 } 135 136 @Override 137 public <T> DbChain setRaw(LambdaGetter<T> property, Object value, boolean isEffective) { 138 getRow().setRaw(property, value, isEffective); 139 return this; 140 } 141 142 public boolean save(Object entity) { 143 return SqlUtil.toBool(Db.insert(schema, tableName, toRow(entity))); 144 } 145 146 public boolean save() { 147 return SqlUtil.toBool(Db.insert(schema, tableName, getRow())); 148 } 149 150 public boolean remove() { 151 return SqlUtil.toBool(Db.deleteByQuery(schema, tableName, this)); 152 } 153 154 public boolean removeById() { 155 return SqlUtil.toBool(Db.deleteById(schema, tableName, getRow())); 156 } 157 158 public boolean update() { 159 return SqlUtil.toBool(Db.updateByQuery(schema, tableName, getRow(), this)); 160 } 161 162 public boolean updateById() { 163 return SqlUtil.toBool(Db.updateById(schema, tableName, getRow())); 164 } 165 166 private static Row toRow(Object entity) { 167 Class<?> entityClass = entity.getClass(); 168 TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass()); 169 Row row = new Row(); 170 171 // 添加非主键列设置的值 172 for (ColumnInfo columnInfo : tableInfo.getColumnInfoList()) { 173 try { 174 FieldWrapper fieldWrapper = FieldWrapper.of(entityClass, columnInfo.getProperty()); 175 Object value = fieldWrapper.get(entity); 176 if (value != null) { 177 row.put(columnInfo.getColumn(), value); 178 } 179 } catch (Exception e) { 180 throw FlexExceptions.wrap(e); 181 } 182 } 183 184 // 添加主键列设置的值 185 for (IdInfo idInfo : tableInfo.getPrimaryKeyList()) { 186 try { 187 FieldWrapper fieldWrapper = FieldWrapper.of(entityClass, idInfo.getProperty()); 188 Object value = fieldWrapper.get(entity); 189 if (value != null) { 190 RowKey rowKey = RowKey.of(idInfo.getColumn() 191 , idInfo.getKeyType() 192 , idInfo.getValue() 193 , idInfo.getBefore()); 194 row.getPrimaryKeys().add(rowKey); 195 row.put(rowKey.keyColumn, value); 196 } 197 } catch (Exception e) { 198 throw FlexExceptions.wrap(e); 199 } 200 } 201 202 return row; 203 } 204 205 public boolean update(Object entity) { 206 return update(toRow(entity)); 207 } 208 209 public boolean update(Row data) { 210 return SqlUtil.toBool(Db.updateByQuery(schema, tableName, data, this)); 211 } 212 213 public boolean update(Map<String, Object> data) { 214 Row row = new Row(); 215 row.putAll(data); 216 return update(row); 217 } 218 219 public long count() { 220 return Db.selectCountByQuery(schema, tableName, this); 221 } 222 223 public boolean exists() { 224 return SqlUtil.toBool(count()); 225 } 226 227 public Row one() { 228 return Db.selectOneByQuery(schema, tableName, this); 229 } 230 231 public Optional<Row> oneOpt() { 232 return Optional.ofNullable(one()); 233 } 234 235 public <R> R oneAs(Class<R> asType) { 236 return one().toEntity(asType); 237 } 238 239 public <R> Optional<R> oneAsOpt(Class<R> asType) { 240 return Optional.ofNullable(oneAs(asType)); 241 } 242 243 public Object obj() { 244 return Db.selectObject(schema, tableName, this); 245 } 246 247 public Optional<Object> objOpt() { 248 return Optional.ofNullable(obj()); 249 } 250 251 @SuppressWarnings("unchecked") 252 public <R> R objAs() { 253 return (R) obj(); 254 } 255 256 public <R> R objAs(Class<R> asType) { 257 return asType.cast(obj()); 258 } 259 260 public <R> Optional<R> objAsOpt() { 261 return Optional.ofNullable(objAs()); 262 } 263 264 public <R> Optional<R> objAsOpt(Class<R> asType) { 265 return Optional.ofNullable(objAs(asType)); 266 } 267 268 public List<Object> objList() { 269 return Db.selectObjectList(schema, tableName, this); 270 } 271 272 @SuppressWarnings("unchecked") 273 public <R> List<R> objListAs() { 274 return objList() 275 .stream() 276 .map(obj -> (R) obj) 277 .collect(Collectors.toList()); 278 } 279 280 public <R> List<R> objListAs(Class<R> asType) { 281 return objList() 282 .stream() 283 .map(asType::cast) 284 .collect(Collectors.toList()); 285 } 286 287 public List<Row> list() { 288 return Db.selectListByQuery(schema, tableName, this); 289 } 290 291 public <R> List<R> listAs(Class<R> asType) { 292 return list() 293 .stream() 294 .map(row -> row.toEntity(asType)) 295 .collect(Collectors.toList()); 296 } 297 298 public Page<Row> page(Page<Row> page) { 299 return Db.paginate(schema, tableName, page, this); 300 } 301 302 public <R> Page<R> pageAs(Page<R> page, Class<R> asType) { 303 Page<Row> rowPage = new Page<>(); 304 rowPage.setPageNumber(page.getPageNumber()); 305 rowPage.setPageSize(page.getPageSize()); 306 rowPage.setTotalRow(page.getTotalRow()); 307 return page(rowPage).map(row -> row.toEntity(asType)); 308 } 309 310}