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