With the release of Hibernate 6, once again I am scratching my head trying to figure out how to get Hibernate to convert a @Lob to bytea for a PostGres database. I also need the code to be testable with H2 (or any in memory database).
I am using Postgres 10+ (v13), so that takes care of that requirement.
This is what I used before, which was tricky, because I also needed it to work with H2. (The PostGres dialect was only loaded in production, not tests.)
Sadly, getting bytea to work is "outside the scope" of the Hibernate 6 user guide. See 2.2.47.
https://docs.jboss.org/hibernate/orm/6.0/userguide/html_single/Hibernate_User_Guide.html
The migration guide also seems silent on the topic.
https://github.com/hibernate/hibernate-orm/blob/6.0/migration-guide.adoc
The entire API for SQLDialect family has been rewritten, so I am back to square 1.
public class CustomPostgresSQL10Dialect extends PostgreSQL10Dialect{
public CustomPostgresSQL10Dialect() {
super();
registerColumnType(Types.BLOB, "bytea");
}
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
return BinaryTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
}
2
Answers
It’s hard to be sure, since you have not told us what the Java type of the field you’re trying to map with the
@Lob
annotation is, but hell, just this once I’ll have a go at reading your mind, and speculate that what you’ve written is this:Now, the Postgres JDBC driver doesn’t support using the LOB APIs to read/write
bytea
columns, and Hibernate knows about this, so it does the next-most-sensible thing, and assumes that this field maps to anoid
column. This turns out to not be what you want.Of course, you could try bypassing Hibernate’s knowledge of Postgres by writing:
And then you would get an error from Postgres or its driver (I forget which), because, as I said, the postgres driver doesn’t support this.
So what to do?
Well, sure, you could try hacking the Hibernate
Dialect
as you have done above, to tell Hibernate to:bytea
for the JDBC typeBLOB
, andBLOB
s using the usual handling for the JDBC typeBINARY
orVARBINARY
or whatever.And yeah, you could still make that work easily enough in H6.
Or, you know, you could just remove the stupid
@Lob
annotation which isn’t doing any useful work here, and let Hibernate treat your field as avarbinary
, which maps tobytea
by default.Now, look, there might be something more to what you’re doing here, but then you’ll need to help me out here by actually posting the details of the field and how you’ve mapped it.
We had exactly the same problem and manage to fix it with this dialect class (kotlin):