org.yx.db.sql.Update Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sumk Show documentation
Show all versions of sumk Show documentation
A quick developing framewort for internet company
/**
* Copyright (C) 2016 - 2030 youtongluan.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.yx.db.sql;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.yx.annotation.db.ColumnType;
import org.yx.common.ItemJoiner;
import org.yx.db.event.UpdateEvent;
import org.yx.db.kit.NumUtil;
import org.yx.db.visit.SumkDbVisitor;
import org.yx.exception.SumkException;
import org.yx.util.CollectionUtil;
public class Update extends AbstractSqlBuilder implements Executable {
private ColumnType _byType;
private Map updateTo;
private boolean _updateDBID = true;
private Map incrMap;
/**
* @param update
* 如果为false,则数据库主键不会被更新。默认为true。
* @return 当前对象
*/
public Update updateDBID(boolean update) {
this._updateDBID = update;
return this;
}
/**
*
* @param fail
* 如果为true,会验证map参数中,是否存在无效的key,预防开发人员将key写错。默认为true
* @return 当前对象
*/
public Update failIfPropertyNotMapped(boolean fail) {
this.failIfPropertyNotMapped = fail;
return this;
}
/**
* 设置where条件,如果没有设置该条件。就用pojo的数据库主键或者redis主键
*
* - 调用本方法后,byDBID和byCacheID方法将被忽略
* - 本方法可以被多次调用,多次调用之间是OR关系
* - 注意:如果本表使用了缓存,本参数必须包含所有redis主键
*
*
* @param pojo
* bean类型或Map.如果是pojo对象,其中的null字段会被忽略掉
* @return 当前对象
*/
public Update addWhere(Object pojo) {
this._addIn(pojo, false);
return this;
}
@Override
public int execute() {
return this.accept(visitor);
}
public Update(SumkDbVisitor visitor) {
super(visitor);
}
/**
* @param fullUpdate
* 设置为true的话,整条记录全部更新,包括null字段。默认为false
* @return 当前对象
*/
public Update fullUpdate(boolean fullUpdate) {
this.withnull = fullUpdate;
return this;
}
private ColumnType byType() {
if (_byType != null) {
return _byType;
}
return OrmSettings.modifyByColumnType;
}
/**
* 默认是根据数据库主键更新
*
* @return 当前对象
*/
public Update byDBID() {
this._byType = ColumnType.ID_DB;
return this;
}
/**
* 分表的情况下,设置分区名。这个方法只能调用一次
*
* @param sub
* 分区名
* @return 当前对象
*/
public Update partition(String sub) {
sub(sub);
return this;
}
/**
* 根据缓存id更新数据。默认是根据数据库主键更新
*
* @return 当前对象
*/
public Update byCacheID() {
this._byType = ColumnType.ID_CACHE;
return this;
}
/**
* 记录被更新后的最终状态。
*
* - 有可能是部分字段,有可能是全部字段
* - 有可能只是单条记录变成这样,有可能是多条记录变成这样
*
*
* @param pojo
* Pojo或Map类型.如果是Map类型,要设置tableClass。
* 如果本表使用了缓存,并且没有where条件,本参数必须包含所有redis主键
* 如果本字段包含在自增长里面,那它将会被排除掉
* @return 当前对象
*/
@SuppressWarnings("unchecked")
public Update updateTo(Object pojo) {
if (Map.class.isInstance(pojo)) {
this.updateTo = new HashMap<>((Map) pojo);
return this;
}
this.pojoMeta = PojoMetaHolder.getPojoMeta(pojo.getClass(), this.sub);
if (this.pojoMeta == null) {
SumkException.throwException(36541, pojo.getClass() + " does not config as a table");
}
try {
this.updateTo = this.pojoMeta.populate(pojo, withnull);
} catch (Exception e) {
SumkException.throwException(-345461, e.getMessage(), e);
}
return this;
}
public Update tableClass(Class tableClass) {
this.tableClass = tableClass;
return this;
}
public MapedSql toMapedSql() throws Exception {
if (this.updateTo == null || this.updateTo.isEmpty()) {
SumkException.throwException(-34601, "updateTo is null or empty");
}
this.pojoMeta = this.parsePojoMeta(true);
this.checkMap(this.updateTo, this.pojoMeta);
if (CollectionUtil.isEmpty(this.in)) {
return this.toMapedSqlWithoutWhere();
}
return this.toMapedSqlWithWhere();
}
private MapedSql toMapedSqlWithWhere() throws Exception {
MapedSql ms = new MapedSql();
StringBuilder sb = new StringBuilder();
ColumnMeta[] fms = pojoMeta.fieldMetas;
sb.append("UPDATE ").append(pojoMeta.getTableName());
boolean notFirst = false;
Map to = new HashMap<>(this.updateTo);
for (ColumnMeta fm : fms) {
String fieldName = fm.getFieldName();
if (this.incrMap != null && this.incrMap.containsKey(fieldName)) {
to.remove(fieldName);
sb.append(notFirst ? " , " : " SET ").append(fm.dbColumn).append('=').append(fm.dbColumn)
.append(" +? ");
notFirst = true;
ms.addParam(this.incrMap.get(fieldName));
continue;
}
Object value = fm.value(this.updateTo);
if (value == null && !withnull) {
continue;
}
if (fm.accept(ColumnType.ID_DB) && !this._updateDBID) {
continue;
}
sb.append(notFirst ? " , " : " SET ");
sb.append(fm.dbColumn).append("=? ");
notFirst = true;
ms.addParam(value);
}
ItemJoiner orItem = new ItemJoiner(" OR ", " WHERE ", null);
for (Map where : this.in) {
this.checkMap(where, this.pojoMeta);
ItemJoiner andItem = new ItemJoiner(" AND ", " ( ", " ) ");
for (ColumnMeta fm : fms) {
Object value = null;
if (where.containsKey(fm.getFieldName())) {
value = where.get(fm.getFieldName());
andItem.item().append(fm.dbColumn).append("=? ");
ms.addParam(value);
}
}
orItem.item().append(andItem.toCharSequence());
}
CharSequence whereStr = orItem.toCharSequence(true);
if (whereStr == null || whereStr.length() == 0) {
SumkException.throwException(345445, "where cannot be null");
}
sb.append(whereStr);
ms.sql = sb.toString();
UpdateEvent event = new UpdateEvent(pojoMeta.getTableName(), to, this.incrMap, this.in, this.withnull,
this._updateDBID);
ms.event = event;
return ms;
}
private MapedSql toMapedSqlWithoutWhere() throws Exception {
MapedSql ms = new MapedSql();
StringBuilder sb = new StringBuilder();
sb.append("UPDATE ").append(pojoMeta.getTableName());
ColumnMeta[] fms = pojoMeta.fieldMetas;
ItemJoiner whereItem = new ItemJoiner(" AND ", " WHERE ", null);
ColumnType byType = byType();
boolean notFirst = false;
List