class BudgetJdbcRepository extends JdbcRepository {

    public Pagination<Budget> search(final BudgetSearch domain) {
        final BudgetSearchEntity budgetSearchEntity = new BudgetSearchEntity();
        budgetSearchEntity.toEntity(domain);

        String searchQuery = "select :selectfields from :tablename :condition  :orderby   ";

        final Map<String, Object> paramValues = new HashMap<>();

        if (budgetSearchEntity.getSortBy() != null && !budgetSearchEntity.getSortBy().isEmpty()) {
            validateSortByOrder(budgetSearchEntity.getSortBy());
            validateEntityFieldName(budgetSearchEntity.getSortBy(), BudgetEntity.class);
        }

        String orderBy = "order by id";
        if (budgetSearchEntity.getSortBy() != null && !budgetSearchEntity.getSortBy().isEmpty())
            orderBy = "order by " + budgetSearchEntity.getSortBy();

        final StringBuffer params = new StringBuffer();

        searchQuery = searchQuery.replace(":tablename", BudgetEntity.TABLE_NAME);

        searchQuery = searchQuery.replace(":selectfields", " * ");

        // implement jdbc specfic search
        if (budgetSearchEntity.getTenantId() != null) {
			if (params.length() > 0) {
				params.append(" and ");
			}
			params.append("tenantId =:tenantId");
			paramValues.put("tenantId", budgetSearchEntity.getTenantId());
		}
        if (budgetSearchEntity.getId() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("id =:id");
            paramValues.put("id", budgetSearchEntity.getId());
        }
        if (budgetSearchEntity.getName() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("name =:name");
            paramValues.put("name", budgetSearchEntity.getName());
        }
        if (budgetSearchEntity.getFinancialYearId() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("financialYearid =:financialYear");
            paramValues.put("financialYear", budgetSearchEntity.getFinancialYearId());
        }
        if (budgetSearchEntity.getEstimationType() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("estimationType =:estimationType");
            paramValues.put("estimationType", budgetSearchEntity.getEstimationType());
        }
        if (budgetSearchEntity.getParentId() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("parentid =:parent");
            paramValues.put("parent", budgetSearchEntity.getParentId());
        }
        if (budgetSearchEntity.getActive() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("active =:active");
            paramValues.put("active", budgetSearchEntity.getActive());
        }
        if (budgetSearchEntity.getPrimaryBudget() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("primaryBudget =:primaryBudget");
            paramValues.put("primaryBudget", budgetSearchEntity.getPrimaryBudget());
        }
        if (budgetSearchEntity.getReferenceBudgetId() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("referenceBudgetid =:referenceBudget");
            paramValues.put("referenceBudget", budgetSearchEntity.getReferenceBudgetId());
        }
        if (budgetSearchEntity.getStatusId() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("statusid =:status");
            paramValues.put("status", budgetSearchEntity.getStatusId());
        }
        if (budgetSearchEntity.getDocumentNumber() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("documentNumber =:documentNumber");
            paramValues.put("documentNumber", budgetSearchEntity.getDocumentNumber());
        }
        if (budgetSearchEntity.getDescription() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("description =:description");
            paramValues.put("description", budgetSearchEntity.getDescription());
        }
        if (budgetSearchEntity.getMaterializedPath() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("materializedPath =:materializedPath");
            paramValues.put("materializedPath", budgetSearchEntity.getMaterializedPath());
        }

        Pagination<Budget> page = new Pagination<>();
        if (budgetSearchEntity.getOffset() != null)
            page.setOffset(budgetSearchEntity.getOffset());
        if (budgetSearchEntity.getPageSize() != null)
            page.setPageSize(budgetSearchEntity.getPageSize());

        if (params.length() > 0)
            searchQuery = searchQuery.replace(":condition", " where " + params.toString());
        else
            searchQuery = searchQuery.replace(":condition", "");

        searchQuery = searchQuery.replace(":orderby", orderBy);

        page = (Pagination<Budget>) getPagination(searchQuery, page, paramValues);
        searchQuery = searchQuery + " :pagination";

        searchQuery = searchQuery.replace(":pagination",
                "limit " + page.getPageSize() + " offset " + page.getOffset() * page.getPageSize());

        final BeanPropertyRowMapper row = new BeanPropertyRowMapper(BudgetEntity.class);

        final List<BudgetEntity> budgetEntities = namedParameterJdbcTemplate.query(searchQuery.toString(), paramValues, row);

        page.setTotalResults(budgetEntities.size());

        final List<Budget> budgets = new ArrayList<Budget>();
        for (final BudgetEntity budgetEntity : budgetEntities)
            budgets.add(budgetEntity.toDomain());
        page.setPagedData(budgets);

        return page;
    }

    public  BudgetJdbcRepository(final NamedParameterJdbcTemplate namedParameterJdbcTemplate, final JdbcTemplate jdbcTemplate);

}