class RecoveryJdbcRepository extends JdbcRepository {

    public Pagination<Recovery> search(RecoverySearch domain) {
        RecoverySearchEntity recoverySearchEntity = new RecoverySearchEntity();
        recoverySearchEntity.toEntity(domain);

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

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

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

        String orderBy = "order by name";
        if (recoverySearchEntity.getSortBy() != null && !recoverySearchEntity.getSortBy().isEmpty()) {
            orderBy = "order by " + recoverySearchEntity.getSortBy();
        }

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

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

        // implement jdbc specfic search
        if (recoverySearchEntity.getTenantId() != null) {
            if (params.length() > 0) {
                params.append(" and ");
            }
            params.append("tenantId =:tenantId");
            paramValues.put("tenantId", recoverySearchEntity.getTenantId());
        }
        if (recoverySearchEntity.getId() != null) {
            if (params.length() > 0) {
                params.append(" and ");
            }
            params.append("id =:id");
            paramValues.put("id", recoverySearchEntity.getId());
        }
        if (recoverySearchEntity.getCode() != null) {
            if (params.length() > 0) {
                params.append(" and ");
            }
            params.append("code =:code");
            paramValues.put("code", recoverySearchEntity.getCode());
        }
        if (recoverySearchEntity.getName() != null) {
            if (params.length() > 0) {
                params.append(" and ");
            }
            params.append("name =:name");
            paramValues.put("name", recoverySearchEntity.getName());
        }
        if (recoverySearchEntity.getActive() != null) {
            if (params.length() > 0) {
                params.append(" and ");
            }
            params.append("active =:active");
            paramValues.put("active", recoverySearchEntity.getActive());
        }

        Pagination<Recovery> page = new Pagination<>();
        if (recoverySearchEntity.getOffset() != null) {
            page.setOffset(recoverySearchEntity.getOffset());
        }
        if (recoverySearchEntity.getPageSize() != null) {
            page.setPageSize(recoverySearchEntity.getPageSize());
        }


        if (params.length() > 0) {

            searchQuery = searchQuery.replace(":condition", " where " +
                    params.toString());

        } else

            searchQuery = searchQuery.replace(":condition", "");

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

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

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

        BeanPropertyRowMapper row = new BeanPropertyRowMapper(RecoveryEntity.class);

        List<RecoveryEntity> recoveryEntities = namedParameterJdbcTemplate.query(searchQuery.toString(), paramValues, row);

        page.setTotalResults(recoveryEntities.size());

        List<Recovery> recoveries = new ArrayList<>();
        for (RecoveryEntity recoveryEntity : recoveryEntities) {

            recoveries.add(recoveryEntity.toDomain());
        }
        page.setPagedData(recoveries);

        return page;
    }

    public  RecoveryJdbcRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate);

}