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

com.jaregu.database.queries.Queries Maven / Gradle / Ivy

Go to download

Java based SQL templating project. Store your queries in *.sql files and build queries for execution. Supports simple expressions and conditional clauses and interface proxying for java-sql bridge.

There is a newer version: 1.4.1
Show newest version
package com.jaregu.database.queries;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.jaregu.database.queries.building.Binders;
import com.jaregu.database.queries.building.ParameterBinder;
import com.jaregu.database.queries.building.Query;
import com.jaregu.database.queries.cache.Caches;
import com.jaregu.database.queries.cache.QueriesCache;
import com.jaregu.database.queries.compiling.Entities;
import com.jaregu.database.queries.compiling.PreparedQuery;
import com.jaregu.database.queries.compiling.QueryCompiler;
import com.jaregu.database.queries.dialect.Dialect;
import com.jaregu.database.queries.dialect.Dialects;
import com.jaregu.database.queries.parsing.QueriesParser;
import com.jaregu.database.queries.parsing.QueriesSource;
import com.jaregu.database.queries.parsing.QueriesSources;
import com.jaregu.database.queries.parsing.QueryParseException;
import com.jaregu.database.queries.parsing.Sources;
import com.jaregu.database.queries.proxy.ClassQueryMapper;
import com.jaregu.database.queries.proxy.Converters;
import com.jaregu.database.queries.proxy.Mappers;
import com.jaregu.database.queries.proxy.QueriesSourceClass;
import com.jaregu.database.queries.proxy.QueriesSourceId;
import com.jaregu.database.queries.proxy.QueriesSourceResource;
import com.jaregu.database.queries.proxy.QueryConverterFactory;
import com.jaregu.database.queries.proxy.QueryMapperFactory;

/**
 * Queries framework enables easy dynamic SQL creation and using in java code.
 * 

* Create Queries instance using {@link Queries#builder()} method * and returned builder. *

* * To create Queries instance there must be at least one * {@link QueriesSource} supplied. See all builder source... * methods for all possible values. *

* * With builder it is possible to set: *

    *
  • {@link ParameterBinder} for some SQL IN (?) clause support * or other purposes *
  • {@link Dialect} for some built-in conversions like OFFSET ? LIMIT ? * support or dynamic ORDER BY clause *
  • {@link QueriesCache} for some production ready caching mechanisms *
*

* * It is possible to use some dependency injection framework to develop feature * modules (using the same Queries instance) independently one of another (each * module registers own query sources) *

* * And there is annotation support for interface proxy creation, to use only * interface to access SQL sources and pass parameters, like: * *

 * Queries queries = Queries.builder()...build();
 * SomeInterface some = queries.proxy(SomeInterface.class);
 * 
 * Query query = some.getFooBarStatement(1, "foo", "BAR");
 * con.prepareStatement(query.getSql())
 * 
* */ public interface Queries extends QueriesFinder { /** * Returns cached {@link PreparedQuery} (see {@link QueriesCache}) or * prepare one using supplied SQL sources. Shorthand for * Queries.get(QueryId) with {@link QueryId#of(String)} * */ PreparedQuery get(String queryId); RelativeQueries relativeTo(SourceId sourceId); /** * Interface must have at least one of ({@link QueriesSourceClass}, * {@link QueriesSourceResource}, {@link QueriesSourceId}) source * identification annotations. *

* * By default interface method must return Query instance or there will be * {@link ClassCastException} exception *

* * Use {@link ClassQueryMapper} annotation to perform additional * {@link Query} mapping to something else. ClassQueryMapper expects class * to be instantiable class with accessible zero argument constructor or use * custom annotations for more powerful conversions. Use * {@link Builder#converter(Class, QueryConverterFactory)} builder method to * register custom factories. * * @param classOfInterface * @return */ T proxy(Class classOfInterface); /** * Shorthand for builder().sources(...).build(). Use * {@link #builder()} for more configuration options * * @param sources * @return */ static Queries of(QueriesSources sources) { return builder().sources(sources).build(); } /** * Shorthand for builder().sources(...).build(). Use * {@link #builder()} for more configuration options * * @param sources * @return */ static Queries of(Collection sources) { return of(QueriesSources.of(sources)); } /** * Shorthand for builder().sources(...).build(). Use * {@link #builder()} for more configuration options * * @param sources * @return */ static Queries of(QueriesSource... sources) { return of(QueriesSources.of(sources)); } /** * Creates builder for Queries instance creation. To create * Queries instance creator must supply at least one SQL queries source. See * all builder.source... methods for possible options. *

* {@link Builder#sources(QueriesSources)} */ static Queries.Builder builder() { return new Builder(); } /** * Queries builder class. Use builder to configure Queries instance. * */ public static class Builder implements Sources, Binders, Dialects, Caches, Mappers, Converters, Entities { private List sources = new LinkedList<>(); private Optional cache = Optional.empty(); private Optional dialect = Optional.empty(); private Optional parameterBinder = Optional.empty(); private Map, QueryMapperFactory> mappers = new HashMap<>(); private Map, QueryConverterFactory> converters = new HashMap<>(); private Map> entities = new HashMap<>(); Builder() { } @Override public Builder sources(QueriesSources sources) { this.sources.addAll(sources.getSources()); return this; } @Override public Builder binder(ParameterBinder binder) { this.parameterBinder = Optional.of(binder); return this; } @Override public Builder dialect(Dialect dialect) { this.dialect = Optional.of(dialect); return this; } @Override public Builder cache(QueriesCache cache) { this.cache = Optional.of(cache); return this; } @Override public Builder mapper(Class annotatedWith, QueryMapperFactory factory) { this.mappers.put(annotatedWith, factory); return this; } @Override public Builder converter(Class annotatedWith, QueryConverterFactory factory) { this.converters.put(annotatedWith, factory); return this; } @Override public Builder entity(Class entity) { return this.entity(entity, entity.getSimpleName()); } @Override public Builder entity(Class entity, String alias) { if (entities.containsKey(alias)) { throw new IllegalArgumentException("Entity by alias '" + alias + "' is already added!"); } entities.put(alias, entity); return this; } public Queries build() { if (sources.isEmpty()) throw new QueryParseException("Can't build Queries, sources is empty"); QueriesConfig config = new QueriesConfigImpl(dialect.orElse(Dialects.defaultDialect()), parameterBinder.orElse(Binders.defaultBinder()), mappers, converters, entities); return new QueriesImpl(QueriesSources.of(sources), QueriesParser.create(), QueryCompiler.of(config), cache.orElse(Caches.noCache()), config); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy