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

com.blade.jdbc.core.ActiveRecord Maven / Gradle / Ivy

There is a newer version: 0.2.2-RELEASE
Show newest version
package com.blade.jdbc.core;

import com.blade.jdbc.Base;
import com.blade.jdbc.annotation.Table;
import com.blade.jdbc.annotation.Transient;
import com.blade.jdbc.page.Page;
import com.blade.jdbc.page.PageRow;
import com.blade.jdbc.utils.Unchecked;
import lombok.Setter;
import org.sql2o.Connection;
import org.sql2o.Query;
import org.sql2o.Sql2o;

import java.io.Serializable;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Stream;

public class ActiveRecord implements Serializable {

    @Transient
    @Setter
    protected Sql2o sql2o;

    @Transient
    Set whereValues = new LinkedHashSet<>();

    @Transient
    private Set saveOrUpdateProperties = new TreeSet<>();

    public ActiveRecord() {
    }

    public Sql2o getSql2o() {
        if (null != sql2o) {
            return sql2o;
        }
        return Base.sql2o;
    }

    public  T where(String key, Object value) {
        return this.where(key, "=", value);
    }

    public  T where(String key, String opt, Object value) {
        this.whereValues.add(WhereParam.builder().key(key).opt(opt).value(value).build());
        this.saveOrUpdateProperties.add(key);
        return (T) this;
    }

    public  T like(String key, Object value) {
        return this.where(key, "like", value);
    }

    public  T and(String key, Object value) {
        return this.where(key, value);
    }

    public  T and(String key, String opt, Object value) {
        return this.where(key, opt, value);
    }

    public  T or(String key, Object value) {
        return this.or(key, "=", value);
    }

    public  T or(String key, String opt, Object value) {
        return this.where(" or " + key, opt, value);
    }

    //    TODO
    public  T between(String key, Object val1, Object val2) {
        // date between ? and ?
        this.whereValues.add(WhereParam.builder().key(key).opt("between").value(val1).build());
        this.saveOrUpdateProperties.add(key);
        return (T) this;
    }

    public  S save() {
        QueryMeta queryMeta = SqlBuilder.buildInsertSql(this);
        try (Connection con = getConn()) {
            return (S) con.createQuery(queryMeta.getSql()).bind(this).executeUpdate().getKey();
        }
    }

    public void update(Serializable pk) {
        this.update(getPk(), pk);
    }

    public void update(String field, Object value) {
        this.whereValues.add(WhereParam.builder().key(field).opt("=").value(value).build());
        this.update();
    }

    public int update() {
        QueryMeta queryMeta = SqlBuilder.buildUpdateSql(this);
        int       result    = this.invoke(queryMeta);
        this.cleanParam();
        return result;
    }

    public void execute(String sql, Object... params) {
        int pos = 1;
        while (sql.indexOf("?") != -1) {
            sql = sql.replaceFirst("\\?", ":p" + pos);
        }
        invoke(new QueryMeta(sql, params));
    }

    private int invoke(QueryMeta queryMeta) {
        if (null == Base.connectionThreadLocal.get()) {
            try (Connection con = getSql2o().open()) {
                return con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams()).executeUpdate().getResult();
            }
        } else {
            Connection con = getConn();
            return con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams()).executeUpdate().getResult();
        }
    }

    private Connection getConn() {
        return null != Base.connectionThreadLocal.get() ? Base.connectionThreadLocal.get() : getSql2o().open();
    }

    public  T query(String sql, Object... args) {
        int pos = 1;
        while (sql.indexOf("?") != -1) {
            sql = sql.replaceFirst("\\?", ":p" + pos);
        }
        Class type = (Class) getClass();
        try (Connection con = getSql2o().open()) {
            this.cleanParam();
            return con.createQuery(sql).withParams(args)
                    .executeAndFetchFirst(type);
        }
    }

    public  List queryAll(String sql, Object... args) {
        int pos = 1;
        while (sql.indexOf("?") != -1) {
            sql = sql.replaceFirst("\\?", ":p" + pos);
        }
        Class type = (Class) getClass();
        try (Connection con = getSql2o().open()) {
            this.cleanParam();
            return con.createQuery(sql).withParams(args)
                    .executeAndFetch(type);
        }
    }

    public  List findAll() {
        return this.findAll(null);
    }

    public  List findAll(Supplier... conditions) {
        QueryMeta queryMeta = SqlBuilder.buildFindAllSql(this, conditions);
        Class  type      = (Class) getClass();
        try (Connection con = getSql2o().open()) {
            Query query = con.createQuery(queryMeta.getSql()).withParams(queryMeta.getParams());
            if (queryMeta.hasColumnMapping()) {
                queryMeta.getColumnMapping().forEach(query::addColumnMapping);
            }
            this.cleanParam();
            return query.executeAndFetch(type);
        }
    }

    public  Page page(int page, int limit) {
        return this.page(new PageRow(page, limit));
    }

    public  Page page(PageRow pageRow) {
        return page(pageRow, null, null);
    }

    public  Page page(PageRow pageRow, String sql, Object... params) {
        Base.pageLocal.set(pageRow);
        int page  = pageRow.getPage();
        int limit = pageRow.getLimit();
        if (null != sql) {
            int pos = 1;
            while (sql.indexOf("?") != -1) {
                sql = sql.replaceFirst("\\?", ":p" + pos);
            }
        }

        String countSql = "select count(*) from (" + sql + ") tmp";
        long   count    = this.count(countSql);

        List list = this.queryAll(sql, params);

        Page pageBean = new Page<>();
        pageBean.setTotalRow(count);
        pageBean.setRows(list);
        pageBean.setPage(page);
        pageBean.setPrevPage(page < 2 ? 1 : page - 1);
        pageBean.setNextPage(page + 1);
        pageBean.setTotalPages(count / limit + (count % limit != 0 ? 1 : 0));

        Base.pageLocal.remove();
        return pageBean;
    }

    public  T find() {
        QueryMeta queryMeta = SqlBuilder.buildFindSql(this);
        Class  type      = (Class) getClass();
        try (Connection con = getSql2o().open()) {
            this.cleanParam();
            Query query = con.createQuery(queryMeta.getSql())
                    .withParams(queryMeta.getParams());
            if (queryMeta.hasColumnMapping()) {
                queryMeta.getColumnMapping().forEach(query::addColumnMapping);
            }
            return query.executeAndFetchFirst(type);
        }
    }

    public  T find(Serializable id) {
        String    sql       = "select * from " + getTableName() + " where " + getPk() + " = :p1";
        QueryMeta queryMeta = new QueryMeta();
        SqlBuilder.mapping(queryMeta, this.getClass());

        Class type = (Class) getClass();
        try (Connection con = getSql2o().open()) {
            this.cleanParam();
            Query query = con.createQuery(sql).withParams(id);
            if (queryMeta.hasColumnMapping()) {
                queryMeta.getColumnMapping().forEach(query::addColumnMapping);
            }
            return query.executeAndFetchFirst(type);
        }
    }

    private long count(boolean cleanParam) {
        QueryMeta queryMeta = SqlBuilder.buildCountSql(this);
        try (Connection con = getSql2o().open()) {
            if (cleanParam) this.cleanParam();
            return con.createQuery(queryMeta.getSql())
                    .withParams(queryMeta.getParams())
                    .executeAndFetchFirst(Long.class);
        }
    }

    public long count() {
        return this.count(true);
    }

    public long count(String sql, Object... args) {
        int pos = 1;
        while (sql.indexOf("?") != -1) {
            sql = sql.replaceFirst("\\?", ":p" + pos);
        }
        try (Connection con = getSql2o().open()) {
            this.cleanParam();
            return con.createQuery(sql).withParams(args)
                    .executeAndFetchFirst(Long.class);
        }
    }

    String getTableName() {
        Class modelType = getClass();
        Table    table     = modelType.getAnnotation(Table.class);
        if (null != table) {
            return table.value().toLowerCase();
        }
        return modelType.getSimpleName().toLowerCase();
    }

    private String getPk() {
        Class modelType = getClass();
        Table    table     = modelType.getAnnotation(Table.class);
        if (null != table) {
            return table.pk().toLowerCase();
        }
        return "id";
    }

    public void delete() {
        QueryMeta queryMeta = SqlBuilder.buildDeleteSql(this);
        this.invoke(queryMeta);
        this.cleanParam();
    }

    public void delete(Serializable pk) {
        this.delete(getPk(), pk);
    }

    public void delete(String field, Object value) {
        whereValues.add(WhereParam.builder().key(field).opt("=").value(value).build());
        this.delete();
    }

    private void cleanParam() {
        this.whereValues.clear();
        this.saveOrUpdateProperties.clear();
        Stream.of(getClass().getDeclaredFields())
                .filter(field -> Objects.isNull(field.getAnnotation(Transient.class)))
                .forEach(field -> Unchecked.wrap(() -> {
                    field.setAccessible(true);
                    field.set(this, null);
                    return null;
                }));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy