De ideale manier om dit te doen, is door de schemagerelateerde informatie van het verzoek vast te leggen en op te slaan in ThreadLocal en het schema in te stellen wanneer de verbinding wordt aangevraagd. Helaas, toen ik deze aanpak probeerde, ontdekte ik dat de setSchema-methode nog niet is geïmplementeerd in stuurprogramma's. Maar ik heb een andere manier (hack) gevonden om dit op te lossen. JDBI biedt een statement Locator die we hier kunnen gebruiken om dit probleem op te lossen.
Laten we zeggen dat we de schemanaam verzenden in de query Parameter, we kunnen het jersey-verzoekfilter gebruiken om de schemanaam te krijgen.
public class Schema {
public static ThreadLocal<String> name = new ThreadLocal<>();
}
public class SchemaNameFilter implements ContainerRequestFilter {
@Override
public ContainerRequest filter(ContainerRequest request) {
if(request.getQueryParameters().containsKey("schema")) {
Schema.name.set(request.getQueryParameters().get("schema").get(0));
}
return request;
}
}
Dit krijgt bij elk verzoek de schemanaam. Registreer deze filer op de bootstrap van uw toepassing.
environment.jersey().property(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, asList(new SchemaNameFilter()));
Nu moeten we het tweede deel schrijven, waarin we deze schema-informatie moeten gebruiken. Voeg deze SchemaRewriter toe,
public class SchemaReWriter implements StatementLocator {
@Override
public String locate(String sql, StatementContext ctx) throws Exception {
if (nonNull(Schema.name.get())) {
sql = sql.replaceAll(":schema", Schema.name.get());
}
return sql;
}
}
Laten we zeggen dat we toegang willen hebben tot de tabel "gebruikers" die in alle schema's staat, schrijf de query op deze manier.
@OverrideStatementLocatorWith(SchemaReWriter.class)
public interface UserDao {
@SqlQuery("select * from :schema.users")
public List<User> getAllUsers();
}
Vergeet niet om Dao te annoteren met StatementRewriter. Dat is alles. U hoeft zich geen zorgen te maken over meerdere schema's.