001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (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 */ 016package io.jboot.service; 017 018import com.jfinal.kit.LogKit; 019import com.jfinal.plugin.activerecord.*; 020import io.jboot.db.model.Columns; 021import io.jboot.db.model.JbootModel; 022import io.jboot.utils.ClassUtil; 023import io.jboot.utils.ObjectFunc; 024import io.jboot.utils.ObjectUtil; 025 026import java.lang.reflect.ParameterizedType; 027import java.lang.reflect.Type; 028import java.util.ArrayList; 029import java.util.Collection; 030import java.util.List; 031 032/** 033 * JbootServiceBase 类 034 * Jboot 1.x 的 Service 需要 Join 功能的话,需要实现 JbootServiceJoiner 接口 035 */ 036public class JbootServiceBase<M extends JbootModel<M>> 037 extends JbootServiceJoinerImpl 038 implements JbootServiceJoiner { 039 040 protected static final int ACTION_ADD = 1; 041 protected static final int ACTION_DEL = 2; 042 protected static final int ACTION_UPDATE = 3; 043 044 protected JbootModel<M> DAO = null; 045 046 public JbootServiceBase() { 047 DAO = initDao(); 048 } 049 050 /** 051 * 初始化 DAO 052 * 子类可以复写 自定义自己的DAO 053 * 054 * @return 055 */ 056 protected M initDao() { 057 Class<?> usefulClass = ClassUtil.getUsefulClass(getClass()); 058 return createDao(usefulClass); 059 } 060 061 062 private M createDao(Class<?> usefulClass) { 063 Type type = usefulClass.getGenericSuperclass(); 064 if (type instanceof ParameterizedType) { 065 Class<M> modelClass = (Class<M>) ((ParameterizedType) type).getActualTypeArguments()[0]; 066 return ClassUtil.newInstance(modelClass, false).dao(); 067 } 068 //from child class 069 else if (type instanceof Class) { 070 Class<?> typeClass = (Class<?>) type; 071 if (typeClass != JbootServiceBase.class 072 && typeClass != Object.class 073 ) { 074 return createDao(typeClass); 075 } 076 } 077 078 LogKit.warn("Not define Model class in service: " +usefulClass); 079 return null; 080 } 081 082 083 public JbootModel getDao() { 084 return DAO; 085 } 086 087 088 /** 089 * 根据ID查找model 090 * 091 * @param id 092 * @return 093 */ 094 public M findById(Object id) { 095 return DAO.findById(id); 096 } 097 098 099 /** 100 * 根据 Columns 查找单条数据 101 * 102 * @param columns 103 * @return 104 */ 105 public M findFirstByColumns(Columns columns) { 106 return findFirstByColumns(columns, null); 107 } 108 109 110 /** 111 * 根据 Columns 查找单条数据 112 * 113 * @param columns 114 * @param orderBy 115 * @return 116 */ 117 public M findFirstByColumns(Columns columns, String orderBy) { 118 return DAO.findFirstByColumns(columns, orderBy); 119 } 120 121 122 /** 123 * 查找全部数据 124 * 125 * @return 126 */ 127 public List<M> findAll() { 128 return DAO.findAll(); 129 } 130 131 132 /** 133 * 根据 Columns 查找数据 134 * 135 * @param columns 136 * @return 137 */ 138 public List<M> findListByColumns(Columns columns) { 139 return DAO.findListByColumns(columns); 140 } 141 142 143 /** 144 * 根据 Columns 查找数据 145 * 146 * @param columns 147 * @param orderBy 148 * @return 149 */ 150 public List<M> findListByColumns(Columns columns, String orderBy) { 151 return DAO.findListByColumns(columns, orderBy); 152 } 153 154 /** 155 * 根据 Columns 查找数据 156 * 157 * @param columns 158 * @param count 159 * @return 160 */ 161 public List<M> findListByColumns(Columns columns, Integer count) { 162 return DAO.findListByColumns(columns, count); 163 } 164 165 /** 166 * 根据 Columns 查找数据 167 * 168 * @param columns 169 * @param orderBy 170 * @param count 171 * @return 172 */ 173 public List<M> findListByColumns(Columns columns, String orderBy, Integer count) { 174 return DAO.findListByColumns(columns, orderBy, count); 175 } 176 177 178 /** 179 * 根据多个 id 查找多个对象 180 * 181 * @param ids 182 * @return 183 */ 184 public List<M> findListByIds(Object... ids) { 185 return DAO.findListByIds(ids); 186 } 187 188 189 /** 190 * 根据提交查询数据量 191 * 192 * @param columns 193 * @return 194 */ 195 public long findCountByColumns(Columns columns) { 196 return DAO.findCountByColumns(columns); 197 } 198 199 200 /** 201 * 根据ID 删除model 202 * 203 * @param id 204 * @return 205 */ 206 public boolean deleteById(Object id) { 207 boolean result = DAO.deleteById(id); 208 if (result) { 209 shouldUpdateCache(ACTION_DEL, null, id); 210 } 211 return result; 212 } 213 214 215 /** 216 * 删除 217 * 218 * @param model 219 * @return 220 */ 221 public boolean delete(M model) { 222 boolean result = model.delete(); 223 if (result) { 224 shouldUpdateCache(ACTION_DEL, model, model._getIdValue()); 225 } 226 return result; 227 } 228 229 230 /** 231 * 根据 多个 id 批量删除 232 * 233 * @param ids 234 * @return 235 */ 236 public boolean batchDeleteByIds(Object... ids) { 237 boolean result = DAO.batchDeleteByIds(ids); 238 if (result) { 239 for (Object id : ids) { 240 shouldUpdateCache(ACTION_DEL, null, id); 241 } 242 } 243 return result; 244 } 245 246 247 /** 248 * 保存到数据库 249 * 250 * @param model 251 * @return id if success 252 */ 253 public Object save(M model) { 254 boolean result = model.save(); 255 if (result) { 256 shouldUpdateCache(ACTION_ADD, model, model._getIdValue()); 257 return model._getIdValue(); 258 } 259 return null; 260 } 261 262 263 /** 264 * 保存或更新 265 * 266 * @param model 267 * @return id if success 268 */ 269 public Object saveOrUpdate(M model) { 270 if (model._getIdValue() == null) { 271 return save(model); 272 } else if (update(model)) { 273 return model._getIdValue(); 274 } 275 return null; 276 } 277 278 /** 279 * 更新 280 * 281 * @param model 282 * @return 283 */ 284 public boolean update(M model) { 285 boolean result = model.update(); 286 if (result) { 287 shouldUpdateCache(ACTION_UPDATE, model, model._getIdValue()); 288 } 289 return result; 290 } 291 292 293 /** 294 * 分页 295 * 296 * @param page 297 * @param pageSize 298 * @return 299 */ 300 public Page<M> paginate(int page, int pageSize) { 301 return DAO.paginate(page, pageSize); 302 } 303 304 305 /** 306 * 分页 307 * 308 * @param page 309 * @param pageSize 310 * @return 311 */ 312 public Page<M> paginateByColumns(int page, int pageSize, Columns columns) { 313 return DAO.paginateByColumns(page, pageSize, columns); 314 } 315 316 317 /** 318 * 分页 319 * 320 * @param page 321 * @param pageSize 322 * @param columns 323 * @param orderBy 324 * @return 325 */ 326 public Page<M> paginateByColumns(int page, int pageSize, Columns columns, String orderBy) { 327 return DAO.paginateByColumns(page, pageSize, columns, orderBy); 328 } 329 330 331 /** 332 * 同步 model 数据到数据库 333 * 334 * @param columns 335 * @param syncModels 336 * @param compareAttrGetters 337 */ 338 public void syncModels(Columns columns, Collection<M> syncModels, ObjectFunc<M>... compareAttrGetters) { 339 if (columns == null) { 340 throw new NullPointerException("columns must not be null"); 341 } 342 343 if (syncModels == null || syncModels.isEmpty()) { 344 DAO.deleteByColumns(columns); 345 return; 346 } 347 348 List<M> existModels = findListByColumns(columns); 349 if (existModels == null || existModels.isEmpty()) { 350 Db.batchSave(new ArrayList<>(syncModels), syncModels.size()); 351 return; 352 } 353 354 355 for (M existModel : existModels) { 356 if (!ObjectUtil.isContainsObject(syncModels, existModel, compareAttrGetters)) { 357 existModel.delete(); 358 } 359 } 360 361 362 for (M syncModel : syncModels) { 363 M existModel = ObjectUtil.getContainsObject(existModels, syncModel, compareAttrGetters); 364 if (existModel == null) { 365 syncModel.save(); 366 } else { 367 existModel._setAttrs(syncModel).update(); 368 } 369 } 370 } 371 372 373 /** 374 * 复写 JbootServiceJoinerImpl 的方法 375 * 376 * @param columnValue 377 * @return 378 */ 379 @Override 380 protected JbootModel joinByValue(Object columnValue, JbootModel sourceModel) { 381 return findById(columnValue); 382 } 383 384 385 /** 386 * 用于给子类复写,用于刷新缓存 387 * 388 * @param action 389 * @param model 390 * @param id 391 */ 392 public void shouldUpdateCache(int action, Model model, Object id) { 393 } 394 395 396 @Override 397 protected <M extends JbootModel> List<M> joinManyByValue(String columnName, Object value, M sourceModel) { 398 return (List<M>) findListByColumns(Columns.create(columnName, value)); 399 } 400}