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