spring-data-relational icon indicating copy to clipboard operation
spring-data-relational copied to clipboard

Make NamingStrategy return a SqlIdentifier instead of a String for Schema

Open houjibo opened this issue 4 years ago • 6 comments

I want a mapping table name as “lowercase_schema”.table_name,but got another one like “UPPERCASE_SCHEMA”.TABLE_NAME

I found that trace :

RelationalPersistentEntityImpl#getTableName -> SqlIdentifier.from(createDerivedSqlIdentifier(schema), tableName) -> new CompositeSqlIdentifier(sqlIdentifiers) -> CompositeSqlIdentifier#toString -> toSql(IdentifierProcessing.ANSI) -> then all my single SqlIdentifier execute toSql with IdentifierProcessing.ANSI before joining ->

My attribute quoted config is not working ...

houjibo avatar Dec 01 '21 09:12 houjibo

I have to extends JdbcMappingContext and override the method of protected <T> RelationalPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) to create a custom RelationalPersistentEntity.

houjibo avatar Dec 01 '21 09:12 houjibo

toString is not considering IdentifierProcessing by design. If you want to render the identifier within a SQL statement (to select a column), please use SqlIdentifier.toSql(…) or for references (e.g. retrieval from ResultSet) then call getReference(…).

mp911de avatar Dec 01 '21 09:12 mp911de

toString is not considering IdentifierProcessing by design. If you want to render the identifier within a SQL statement (to select a column), please use SqlIdentifier.toSql(…) or for references (e.g. retrieval from ResultSet) then call getReference(…).

I want using custom NamingStrategy to specified a customized schema as quoted "test", and i have to not config @Table on my domain type when i want to trigger the RelationalPersistentEntityImpl#namingStrategy build a new SqlIdentifier, then the toString() is auto called by return as:

public SqlIdentifier getTableName() {
    return tableName.get().orElseGet(() -> {

        String schema = namingStrategy.getSchema();
        SqlIdentifier tableName = createDerivedSqlIdentifier(namingStrategy.getTableName(getType()));

        return StringUtils.hasText(schema) ? SqlIdentifier.from(createDerivedSqlIdentifier(schema), tableName)
                : tableName;
    });
}

houjibo avatar Dec 01 '21 10:12 houjibo

So why the DerivedSqlIdentifier must as default SqlIdentifier both on when given custom NamingStrategy to provide schema and tableName ?

houjibo avatar Dec 01 '21 10:12 houjibo

I'm not 100% sure I understand your question.

My understandin is you want to a) specify the schema for a table to map to. For this we already have #1099 which should fix the problem of not being able to specify a schema. b) want to control how a schema given through a NamingStrategy is rendered for SQL. For this we already discussed that a NamingStrategy shouldn't return Strings but SqlIdentifier. I think there is an issue for this already, but I can't find it. So I propose to use this one here to track that.

schauder avatar Dec 06 '21 16:12 schauder

Specifing the schema with quoted or not has always been a headache. There is always something unsatisfying about. When I use Flyway, ORM, or even multi-tenancy, I need to switch schemas.

In the end, I chose AOP, change the current schema before using the connection, without NamingStrategy and specifing schema in POJO or Query SQL.

    @Around(value = "execution(public java.sql.Connection *.getConnection(..)) && target(javax.sql.DataSource)")
    public Object changeSchema(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object conn = proceedingJoinPoint.proceed();
        if (conn instanceof Connection) {
            changeSchema((Connection) conn);
        }
        return conn;
    }

houjibo avatar Dec 15 '21 01:12 houjibo