FAQ
I was doing some tests on multitenancy implementations using cayenee 3.1
beta 2 and postgres , using 1 schema per tenant.

I instancend one ServerRuntime per tennant this way:

    public static ServerRuntime createServerRuntime(final String
tenantSchema) {

         ServerRuntime runtime = new ServerRuntime("/cayenne-...xml", new
Module() {

             public void configure(Binder binder) {

                 binder.bind(DataMapLoader.class).toInstance(new
TenantMapLoader(tenantSchema));

             }

          // in a custom module override the schema of all loaded DataMaps
         });

         return runtime;
     }

     static class TenantMapLoader extends XMLDataMapLoader {

         private String tenantSchema;

         TenantMapLoader(String tenantSchema) {
             this.tenantSchema = tenantSchema;
         }

         public DataMap load(Resource configurationResource) {
             DataMap map = super.load(configurationResource);
             map.setDefaultSchema(tenantSchema);

             for (DbEntity e : map.getDbEntities()) {
                 e.setSchema(tenantSchema);

                 // workaround else cayenne would search for postgress
sequences
                 // in public schema.

                 String
sequence=tenantSchema.concat(".").concat(e.getPrimaryKeyGenerator().getGeneratorName());
                 e.getPrimaryKeyGenerator().setGeneratorName(sequence);

             }

             return map;
         }
     }

I had to put a workaround for handling sequences in the right schema, else
cayenne would look in public schema (as performig a query in postgres
omitting the schema name will end peforming it in public schema).

Is there another way to specify to cayenne which schema must be used for
sequences?

Search Discussions

  • Andrus Adamchik at Nov 12, 2013 at 7:54 am
    I recently had a similar problem that required setting a default connection *catalog* (this was on MySQL that does not support schemas). I solved that with a custom DataSource wrapper per stack [1]. However JDBC connection class does not have a notion of default schema, so this will not work with schemas, however maybe you can replace ‘setCatalog’ call in [1] with a quick schema change statement execution (“set search_path to 'schema’", per [2])?

    Having said that, we also have an open Jira to handle it explicitly [3]. It is on the list of things for 3.2.

    Andrus


    [1]
    class TenantDataSource implements DataSource {

      private DataSource delegate;
      private String defaultCatalog;

      TenantDataSource(DataSource delegate, String defaultCatalog) {
       this.delegate = delegate;
       this.defaultCatalog = defaultCatalog;
      }

      @Override
      public Connection getConnection() throws SQLException {
       Connection c = delegate.getConnection();
       c.setCatalog(defaultCatalog);
       return c;
      }

      @Override
      public Connection getConnection(String username, String password) throws SQLException {
       throw new UnsupportedOperationException("Unsupported");
      }

      // other DataSource methods, delegated to the underlying DS
             …
    }

    [2] http://stackoverflow.com/questions/4168689/is-it-possible-to-specify-schema-when-connecting-to-postgres-with-jdbc
    [3] https://issues.apache.org/jira/browse/CAY-1824

    On Nov 11, 2013, at 4:25 AM, Emanuele Maiarelli wrote:

    I was doing some tests on multitenancy implementations using cayenee 3.1
    beta 2 and postgres , using 1 schema per tenant.

    I instancend one ServerRuntime per tennant this way:

    public static ServerRuntime createServerRuntime(final String
    tenantSchema) {

    ServerRuntime runtime = new ServerRuntime("/cayenne-...xml", new
    Module() {

    public void configure(Binder binder) {

    binder.bind(DataMapLoader.class).toInstance(new
    TenantMapLoader(tenantSchema));

    }

    // in a custom module override the schema of all loaded DataMaps
    });

    return runtime;
    }

    static class TenantMapLoader extends XMLDataMapLoader {

    private String tenantSchema;

    TenantMapLoader(String tenantSchema) {
    this.tenantSchema = tenantSchema;
    }

    public DataMap load(Resource configurationResource) {
    DataMap map = super.load(configurationResource);
    map.setDefaultSchema(tenantSchema);

    for (DbEntity e : map.getDbEntities()) {
    e.setSchema(tenantSchema);

    // workaround else cayenne would search for postgress
    sequences
    // in public schema.

    String
    sequence=tenantSchema.concat(".").concat(e.getPrimaryKeyGenerator().getGeneratorName());
    e.getPrimaryKeyGenerator().setGeneratorName(sequence);

    }

    return map;
    }
    }

    I had to put a workaround for handling sequences in the right schema, else
    cayenne would look in public schema (as performig a query in postgres
    omitting the schema name will end peforming it in public schema).

    Is there another way to specify to cayenne which schema must be used for
    sequences?

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupuser @
categoriescayenne
postedNov 11, '13 at 1:26a
activeNov 12, '13 at 7:54a
posts2
users2
websitecayenne.apache.org

People

Translate

site design / logo © 2022 Grokbase