All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bixuebihui.r2dbc.db.ActiveRecordImpl Maven / Gradle / Ivy

The newest version!
package com.bixuebihui.r2dbc.db;


import com.bixuebihui.DbException;
import com.bixuebihui.db.*;
import com.bixuebihui.jdbc.SqlFilter;
import com.bixuebihui.jdbc.SqlSort;
import com.bixuebihui.jdbc.entity.CountObject;
import com.bixuebihui.jdbc.entity.CountValue;
import com.bixuebihui.r2dbc.sql.*;
import io.r2dbc.spi.Connection;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import jakarta.validation.constraints.NotNull;

import java.util.*;

import static com.bixuebihui.db.Dialect.*;

/**
 * Created with IntelliJ IDEA. User: Administrator Date: 13-4-18 Time: 下午5:57 To
 * change this template use File | Settings | File Templates.
 *
 * @author xingwx
 * @version $Id: $Id
 */
public class ActiveRecordImpl implements ActiveRecord {

	private static final Logger LOG = LoggerFactory.getLogger(ActiveRecordImpl.class);
	/**
	 * NOTE that: class field make this class can't use in spring as singleton!
	 */
	SqlSort orderStack;
	SqlHelper filterStack;

	public SqlLimit getLimit() {
		return limit;
	}

	SqlLimit limit;
	BaseDao operator;
	Mono cn;
	private SqlPocket sqlPocket;
	private boolean useLast=false;

	private String tableAlias;
	private String resultFields =" * ";
	private List joins;


	private void init(BaseDao operator){
		this.operator = operator;
		orderStack = new SqlSort();
		filterStack = new SqlHelper();
		limit = SqlLimit.LIMIT_MAX;
	}

	/**
	 * 

Constructor for ActiveRecordImpl.

* * @param operator a {@link BaseDao} object. */ public ActiveRecordImpl(BaseDao operator) { init(operator); } /** *

Constructor for ActiveRecordImpl.

* * @param operator a {@link BaseDao} object. * @param cn a {@link Connection} object. */ public ActiveRecordImpl(BaseDao operator, Mono cn) { this.cn = cn; init(operator); } /** {@inheritDoc} */ @Override public ActiveRecord in(String field, Object[] values) { filterStack.in(field, values); return this; } @Override public ActiveRecord emptyStringAsNullCondition() { filterStack.setAcceptEmptyStringAsNullObjectInCondition(true); return this; } /** {@inheritDoc} */ @Override public ActiveRecord in(String field, Object values) { if(!(values instanceof Collection) && !(values instanceof SqlString)){ throw new IllegalArgumentException("InFilter values must be Collection or SqlString objects"); } if (values instanceof Collection) { filterStack.in(field, (Collection) values); } else { filterStack.in(field, (SqlString) values); } return this; } /** {@inheritDoc} */ @Override public ActiveRecord like(String field, String value) { filterStack.like(field, value); return this; } /** {@inheritDoc} */ @Override public ActiveRecord startWith(String field, String value) { filterStack.startWith(field, value); return this; } /** {@inheritDoc} */ @Override public ActiveRecord eq(String field, Object value) { filterStack.eq(field, value); return this; } /** {@inheritDoc} */ @Override public ActiveRecord ne(String field, Object value){ filterStack.ne(field, value); return this; } /** {@inheritDoc} */ @Override public ActiveRecord eq(String[] fields, Object[] value) { filterStack.eq(fields, value); return this; } /** {@inheritDoc} */ @Override public ActiveRecord greaterThan(String field, Object value) { filterStack.greaterThan(field, value); return this; } /** {@inheritDoc} */ @Override public ActiveRecord smallerThan(String field, Object value) { filterStack.smallerThan(field, value); return this; } /** {@inheritDoc} */ @Override public ActiveRecord greaterOrEqualThan(String field, Object value) { filterStack.greaterOrEqualThan(field, value); return this; } /** {@inheritDoc} */ @Override public ActiveRecord smallerOrEqualThan(String field, Object value) { filterStack.smallerOrEqualThan(field, value); return this; } @Override public ActiveRecord isNull(String field) { filterStack.isNull(field); return this; } @Override public ActiveRecord isNotNull(String field) { filterStack.isNotNull(field); return this; } /** {@inheritDoc} */ @Override public SqlHelper getCondStack(){ return filterStack; } /** {@inheritDoc} */ @Override public ActiveRecord or(SqlHelper andStack){ filterStack.or(andStack); return this; } protected ActiveRecord order(String field, int order) { orderStack.addSort(field, order == ORDER_DESC ? SqlSort.Sort.DESC : SqlSort.Sort.ASC); return this; } /** {@inheritDoc} */ @Override public ActiveRecord orderByIn(String field, Object[] order) { operator.getDbType().flatMap(type -> { if( type != DERBY) { orderStack.addSortByIn(field, order); } return Mono.empty(); }).subscribe(); return this; } /** {@inheritDoc} */ @Override public ActiveRecord limit(int begin, int num) { limit = new SqlLimit(begin, num); return this; } /** * {@inheritDoc} */ @Override public Mono> findAll() throws DbException { try { sqlPocket = this.getSql(); String where = formWhereClause(); Object[] params = getParams().toArray(); return operator.selectWithJoin(resultFields, where, params, parseOrder(), limit.getBegin(), limit.getEnd()); } finally { clear(); } } protected List getParams(){ List res = sqlPocket.getParams(); operator.getDbType().flatMap(type -> { if(type!= DERBY) { res.addAll(orderStack.getParams()); } return Mono.empty(); }).subscribe(); return res; } /** * {@inheritDoc} */ @Override public Mono> findAll(Class clz) throws DbException { sqlPocket = this.getSql(); String where = formWhereClause(); Object[] params = getParams().toArray(); String select = "select " + resultFields + " from " + operator.getTableName() + " "; return operator.select(select, where, parseOrder(), params, limit.getBegin(), limit.getEnd(), clz).doFinally(c -> clear()); } /** *

formWhereClause.

* * @return a {@link String} object. */ protected String formWhereClause() { String res = sqlPocket.getCondition().toString(); if(StringUtils.isNotBlank(this.tableAlias) ){ StringBuilder join =new StringBuilder(); if(joins !=null && joins.size()>0){ for(String t : joins) { join.append(t); } } res = " "+this.tableAlias +" "+join+" "+res; } return res; } private void clear() { LOG.debug("do clear"); this.filterStack.clear(); this.orderStack.clear(); this.joins =null; this.limit = SqlLimit.LIMIT_MAX; useLast = false; this.cn = null; } /** * {@inheritDoc} */ @Override public Mono find() throws DbException { sqlPocket = this.getSql(); String where = formWhereClause(); Object[] params = getParams().toArray(); Mono> res = operator.selectWithJoin(resultFields, where, params, parseOrder(), SqlLimit.LIMIT_ONE.getBegin(), SqlLimit.LIMIT_ONE.getEnd()); return res.map(list -> list.isEmpty()?null: list.get(0)).doFinally(c -> clear()); } /** * {@inheritDoc} * @return */ @Override public Mono delete() throws DbException { sqlPocket = this.getSql(); String where = formWhereClause(); Object[] params = getParams().toArray(); if (where.length() < " where ".length()) { LOG.warn("因 where 条件没有设定,安全原因delete操作不被允许"); clear(); return Mono.just(false); } String sql = "delete from " + operator.getTableName() + " " + where; if (limit != null && limit.getBegin()==0 && limit.getEnd()>0) { sql +=" limit "+limit.getEnd(); } if(cn==null) { return operator.getDbHelper().executeNoQuery(sql, params).map(x -> x>0).doFinally(c -> clear()); } String finalSql = sql; return cn.flatMap(connection -> operator.getDbHelper().executeNoQuery(finalSql, params, connection)) .map(x -> x > 0 ).doFinally(c -> clear()); } /** * {@inheritDoc} */ @Override public Mono get(String field){ return Mono.usingWhen(getVectorSql(field), sql -> { Object[] params = getParams().toArray(); if (cn == null) { return operator.getDbHelper().executeScalar(sql, params); } return operator.getDbHelper().executeScalar(sql, params, cn); } , sql -> {clear(); return Mono.empty();} ); } /** * {@inheritDoc} */ @Override public Mono> getVector(String field) throws DbException { return Mono.usingWhen(getVectorSql(field), sql -> { Object[] params = getParams().toArray(); RowCallbackHandler handle = result -> Flux.from(result.map((row, meta) -> row.get(0))).collectList(); return operator.getDbHelper().executeQuery(sql, params, handle); }, sql -> {clear(); return Mono.empty();} ); } /** * {@inheritDoc} */ @Override public Mono> getLongVector(String field) { return getVectorSql(field).flatMap( sql -> { Object[] params = getParams().toArray(); IDbHelper dbhelper = operator.getDbHelper(); LongReader reader = new LongReader(); return dbhelper.executeQuery(sql, params, reader); }).doFinally(c -> clear()); } public Mono parseLimitSql() { return operator.getDbType().map(type -> { if (type == MYSQL || type == H2) { if (limit == null) { limit = SqlLimit.LIMIT_ONE; } return limit.toString(); } else { LOG.warn("limit not implemented for this type of BaseDao.getDBTYPE()=" + type); return ""; } }); } private Mono getVectorSql(String field) throws DbException { String fieldFilter = SqlFilter.transactSQLInjection(field); sqlPocket = this.getSql(); String where = formWhereClause()+ " " + parseOrder(); return parseLimitSql().map( limit -> { String whereCondition = where + " " +limit; return "select " + fieldFilter + " from " + operator.getTableName() + " " + whereCondition; }); } /** * {@inheritDoc} */ @Override public SqlPocket getSql() throws DbException { if (useLast && sqlPocket != null) { return sqlPocket; } sqlPocket = filterStack.build(); return sqlPocket; } public String parseOrder() { return this.orderStack.toString(); } /** * {@inheritDoc} * @return */ @Override public Mono count() throws DbException { sqlPocket = this.getSql(); String where = formWhereClause(); Object[] params = getParams().toArray(); return operator.countWhere(where, params).doFinally(c -> clear()); } /** * {@inheritDoc} * @return */ @Override public Mono exists() throws DbException { sqlPocket = this.getSql(); String where = formWhereClause(); Object[] params = getParams().toArray(); return operator.exists(where, params).doFinally(c -> clear()); } /** *

Constructor for ActiveRecordImpl.

* * @param src a {@link ActiveRecordImpl} object. */ public ActiveRecordImpl(ActiveRecordImpl src) { this.filterStack = new SqlHelper(src.filterStack); this.limit = new SqlLimit(src.limit); this.orderStack = new SqlSort(this.orderStack); this.resultFields = src.resultFields; } /** {@inheritDoc} */ @Override public Record last() { if(sqlPocket==null){ LOG.error("ERROR: ActiveRecordImpl.last() - there not conditions set to use last."); } useLast = true; return this; } /** {@inheritDoc} */ @Override public ActiveRecord asc(String field) { return this.order(field, ORDER_ASC); } /** {@inheritDoc} */ @Override public ActiveRecord desc(String field) { return this.order(field, ORDER_DESC); } /** * {@inheritDoc} */ @Override public Mono> getStringVector(String field) throws DbException { return getVectorSql(field).flatMap( sql -> { Object[] params = getParams().toArray(); RowCallbackHandler handle = result -> Flux.from(result.map((row, meta) -> Objects.requireNonNull(row.get(0)).toString())).collectList(); return operator.getDbHelper().executeQuery(sql, params, handle).doFinally(c -> clear()); }); } /** {@inheritDoc} */ @Override public ActiveRecord alias(String shortName) { tableAlias = shortName; return this; } /** {@inheritDoc} */ @Override public ActiveRecord fields(String resultFields) { this.resultFields = resultFields; return this; } /** {@inheritDoc} */ @Override public ActiveRecord join(String joinClause) { if (joins == null) { joins = new ArrayList<>(); } joins.add(joinClause); return this; } /** * {@inheritDoc} */ @Override @Deprecated public Mono countSum(String field)throws DbException { return countValue(field, GroupFunction.SUM); } /** {@inheritDoc} * @return*/ @Override @Deprecated public Mono countValue(String field, GroupFunction fun) { sqlPocket = this.getSql(); String where = formWhereClause(); Object[] params = getParams().toArray(); Mono> res = operator.countGroupValue(field, fun.toString(), where, null, null, params); return res.map(list -> list.size() == 0 ? new CountValue() : list.get(0)).doFinally((c) -> clear()); } /** * {@inheritDoc} */ @Override public Mono inc(@NotNull String field){ sqlPocket = this.getSql(); String whereClause = formWhereClause(); Object[] params = getParams().toArray(); String sql = "update " + operator.getTableName() + " set " + field + "=" + field + "+1 " + whereClause; if (cn==null) { return operator.getDbHelper().executeNoQuery(sql, params); } return cn.flatMap(conn -> operator.getDbHelper().executeNoQuery(sql, params, conn) ).doFinally(c -> clear()); } /** * {@inheritDoc} */ @Override public Mono update(@NotNull String[] fields, @NotNull Object[] values) { if (fields.length != values.length) { throw new IllegalArgumentException("fields and values must have some length"); } sqlPocket = this.getSql(); String whereClause = formWhereClause(); List params = new ArrayList<>(); StringBuilder sb = new StringBuilder(); int i=0; for(String field:fields){ Object val = values[i]; if(val instanceof SqlString){ sb.append(field).append(" = ").append(val); }else{ sb.append(field).append(" = ? "); params.add(val); } i++; if(i clear()); } return cn.flatMap(conn -> operator.getDbHelper().executeNoQuery(sql, params.toArray(), conn) ).doFinally(c -> clear()); } /** {@inheritDoc} */ @Override public Mono update(@NotNull String fields, Object values) { return update(new String[]{fields}, new Object[]{values}); } /** {@inheritDoc} */ @Override public Mono> countObject(String field, GroupFunction fun, Class objectType) { sqlPocket = this.getSql(); String where = formWhereClause(); Object[] params = getParams().toArray(); Mono>> res = operator.countGroupObject(field, fun.toString(), where, null, null, objectType, params).doFinally(c -> clear()); return res.map(list -> list.size() == 0 ? new CountObject<>() : list.get(0)); } }