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