Reputation: 11
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.
Upvotes: 1
Views: 363
Reputation: 11
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.
Upvotes: 0