Files
llm-wiki/vault/10-projects/errors/spring-jpa-postgres-lob-oid-cast-2026-06-23.md
T

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
```