69 lines
3.4 KiB
Markdown
69 lines
3.4 KiB
Markdown
---
|
|
title: error / spring-jpa-postgres-lob-oid-cast-2026-06-23
|
|
source_type: error-note
|
|
status: raw
|
|
branch: feature-build-release-supply-chain-contract
|
|
related_projects: [ca-skeleton]
|
|
tags: [error, spring-boot, hibernate, jpa, postgresql, lob, oid]
|
|
created: 2026-06-23
|
|
updated: 2026-06-23
|
|
---
|
|
|
|
# PostgreSQL column cannot be cast automatically to type oid during Hibernate ddl-auto update
|
|
|
|
## Parent
|
|
- Parent branch note: [[raw/branch-notes/feature-build-release-supply-chain-contract]]
|
|
|
|
## Symptoms
|
|
|
|
During application boot, Hibernate threw a warning/exception when trying to run auto-DDL commands:
|
|
|
|
```text
|
|
2026-06-23 14:32:01.573 WARN [main] o.h.t.s.i.ExceptionHandlerLoggedImpl - GenerationTarget encountered exception accepting command : Error executing DDL "alter table if exists outbox_event alter column payload set data type oid" via JDBC [ERROR: column "payload" cannot be cast automatically to type oid
|
|
Hint: You might need to specify "USING payload::oid".]
|
|
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table if exists outbox_event alter column payload set data type oid" via JDBC [ERROR: column "payload" cannot be cast automatically to type oid
|
|
Hint: You might need to specify "USING payload::oid".]
|
|
```
|
|
|
|
## Root Cause
|
|
|
|
1. The Flyway migration script `V3__outbox_event.sql` defines the `payload` column as `text`:
|
|
```sql
|
|
payload text NOT NULL,
|
|
```
|
|
2. The Java entity `OutboxEventEntity.java` declared the property using `@Lob`:
|
|
```java
|
|
@Lob
|
|
@Column(name = "payload", nullable = false, updatable = false)
|
|
private String payload;
|
|
```
|
|
3. In Hibernate (especially when using a PostgreSQL dialect), a `@Lob` annotation on a `String` property maps it to the JDBC type `Types.BLOB`/`CLOB`, which in PostgreSQL defaults to the `oid` (Object Identifier) type rather than standard `text`.
|
|
4. When `ddl-auto` is set to `update` (typical in dev/local environments), Hibernate compares its internal mapping (`oid`) with the actual DB column type (`text`). Finding a mismatch, it generates an alter-table command to change the data type to `oid`.
|
|
5. PostgreSQL rejects this conversion implicitly because converting a text column to `oid` requires a custom cast expression (`USING payload::oid`).
|
|
|
|
## Solution
|
|
|
|
Remove the `@Lob` annotation from `payload` in `OutboxEventEntity.java` and map it using a portable long varchar hint instead of an RDBMS-specific column definition:
|
|
|
|
```java
|
|
@JdbcTypeCode(SqlTypes.LONGVARCHAR)
|
|
@Column(name = "payload", nullable = false, updatable = false)
|
|
private String payload;
|
|
```
|
|
|
|
### Why it works
|
|
- `@JdbcTypeCode(SqlTypes.LONGVARCHAR)` maps the `String` property to standard JDBC `LONGVARCHAR` type.
|
|
- On PostgreSQL, the Hibernate dialect translates `LONGVARCHAR` to `text`.
|
|
- On other databases (like Oracle or H2), it maps to `clob` or `varchar` with maximum capacity, preserving vendor-neutrality.
|
|
- Because both Flyway and Hibernate now agree that the column type is `text`, no DDL alterations are triggered during startup.
|
|
|
|
## Verification & Outcomes
|
|
|
|
### Local Verification
|
|
1. Replaced the annotation in `OutboxEventEntity.java`.
|
|
2. Ran `./gradlew clean` to ensure all stale compilation caches are invalidated.
|
|
3. 기동 검증: `./gradlew :app-bootstrap:bootRun` 실행 결과, DDL alteration 경고 및 오류 없이 완전히 깨끗하게 기동되었습니다:
|
|
```text
|
|
2026-06-23 14:41:40.748 INFO [main] d.c.bootstrap.CaSkeletonApplication - Started CaSkeletonApplication in 4.193 seconds
|
|
```
|