1

In my JPA-Springboot-app I have to support different databases, i.e. postgres and oracle. I have an entity with a lob type and i want to store the data as string. Because postgres stores lobs differently to other databases, I tried to choose the sql type dependent on the database dialect, according to these instruction: https://geeknet.me/hibernate-postgresql-the-lob-annotation/

So here is what i have:

@Entity
public class MyEntity {

    @EmbeddedId
    private MyPk myPk;

    @Lob
    @Column(name = "value", nullable = false)
    @Type(type = "org.example.DatabaseAwareLobType")
    private String value;
}

The DatabaseAwareLobType looks like:

import org.hibernate.type.descriptor.java.StringTypeDescriptor;
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
...

@Component
public class DatabaseAwareLobType extends AbstractSingleColumnStandardBasicType<String> {

    @Value("${spring.jpa.properties.hibernate.dialect}")
    private String dbDialect;

    private static String DBDIALECT_STATIC;

    public static final DatabaseAwareLobType INSTANCE = new DatabaseAwareLobType();

    public DatabaseAwareLobType() {
        super(getDbDescriptor(), StringTypeDescriptor.INSTANCE );
    }
    public static SqlTypeDescriptor getDbDescriptor() {
        if( isPostgres() ) {
            return VarcharTypeDescriptor.INSTANCE;
        }
        else {
            return ClobTypeDescriptor.DEFAULT;
        }
    }

    private static boolean isPostgres() {
        if(Objects.isNull(DBDIALECT_STATIC) ) {
            return false;
        }

        return DBDIALECT_STATIC.contains( "postgres" );
    }

    @Value("${spring.jpa.properties.hibernate.dialect}")
    public void setDbDialectStatic(String dbDialect) {
        DatabaseAwareLobType.DBDIALECT_STATIC = dbDialect;
    }

}

My problem are the dbDialect resp. DBDIALECT_STATIC properties. They have no value, because the hibernate initialization is done before loading the application properties.

In the linked instruction the properties were read manually. I cant to this, because i dont know which property file is used (different spring profiles, customization via docker environment).

I'm searched for loading properties prior application startup, maybe to initialize a bean for the database type. But I have found no suitable solution for my problem. Maybe I'm trying it the wrong way.

Does anyone have an idea how i can solve this? I am thankful for any suggestions.

1 Answer 1

0

So I have found no solution. I have an alternative implementation.

First I changed the attribute type from String to byte[] and used Hibernates BinaryType for mapping it

@Entity
public class MyEntity {

    @EmbeddedId
    private MyPk myPk;

    @Lob
    @Column(name = "data", nullable = false)
    @Type(type="org.hibernate.type.BinaryType")
    private byte[] data;
}

I set up the database with liquibase. The LOB column is no longer from type clob but from blob. So my liquibase-changelog looks like:

<createTable tableName="my_entity" schemaName="importservice">
...
    <column name="data" type="${blob_type}">
        <constraints nullable="false" />
    </column>
</createTable>

And the target database is taken into account by the associated properties for the lob type:

<property name="blob_type" value="bytea" dbms="postgresql"/>
<property name="blob_type" value="blob"/>

So now there is an extra step for converting the byte array in string and vice versa. But this is ok for me.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.