JPA 및 PostgreSQL 텍스트

다음은 www.jpa-buddy.com의 친구들과 논의한 후 오랫동안 초안으로 작성한 블로그 게시물이며 (https://www.jpa-buddy.com/blog/how-to-store-text-in-postgresql-tips-tricks-and-traps/) 주제에 대한 훌륭한 기사를 작성했기 때문에 여기에 작은 테스트를 게시하고 있습니다.



JPA 주석 없이 String를 선언합니다.

public class UnlimitedText {
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Long id;
    private String name;


재현하려는 경우 전체 프로그램은 다음과 같습니다.
https://gist.github.com/FranckPachot/fcd11b5a63b7512cfe3404ed61a3fa53

이것은 hbm2ddl로 다음을 생성합니다.

    create table unlimited_text (
       id int8 not null,
        name varchar(255),
        primary key (id)
    )


255자... 너무 크거나 작습니다. 아마도 당신이 원하는 것이 아닐 것입니다.

@컬럼(길이=)



길이를 지정할 수 있습니다.

    @Column(length=10485760)
    private String name;


생성된 DDL:

    create table unlimited_text (
       id int8 not null,
        name varchar(10485760),
        primary key (id)
    )


좋습니다. 일부 데이터베이스에는 적합하지만 PostgreSQL에는 크기에 대해 생각할 필요가 없는 text 데이터 유형이 있습니다. 나는 이것을 선호한다. YugabyteDB는 블록 제한 없이 문서로 저장하므로 크기를 제한하지 않으려면 크기를 지정할 필요가 없습니다.

@Type(type="org.hibernate.type.StringType")



StringType을 표시하는 것은 올바른 방법이 아닙니다. 기본값과 같이 varchar(255) 생성됩니다.

    @Type(type="org.hibernate.type.StringType")
    private String name;


생성된 DDL:

    create table unlimited_text (
       id int8 not null,
        name varchar(255),
        primary key (id)
    )


@Type(type="org.hibernate.type.TextType")


text에 대한 올바른 Hibernate 유형은 TextType입니다.

    @Type(type="org.hibernate.type.TextType")
    private String name;


생성된 DDL:

    create table unlimited_text (
       id int8 not null,
        name text,
        primary key (id)
    )


엄청난. 이것이 내가 원하는거야.

@열(열 정의="텍스트")



어떤 이유로든 PostgreSQL 데이터 유형 이름을 언급하는 것을 선호하는 경우 다음과 같이 작동합니다.

    @Column(columnDefinition="text")
    private String name;


생성된 DDL:

    create table unlimited_text (
       id int8 not null,
        name text,
        primary key (id)
    )


이제 텍스트는 PostgreSQL 또는 YugabyteDB에서 제한이 있습니다.
예시:

yugabyte=# create table demo as select lpad('x',269000000,'x');
DROP TABLE
ERROR:  invalid memory alloc request size 1076000004

yugabyte=# create table demo as select lpad('x',900000000,'x');
ERROR:  requested length too large





더 큰 개체를 원할 때 PosttgreSQL은 큰 개체(LOB)를 일부 지원합니다.

    @Lob
    private String name;


생성된 DDL:

    create table unlimited_text (
       id int8 not null,
        name text,
        primary key (id)
    )


좋아 보이지만 Hello World를 삽입하고 무엇이 있는지 살펴보겠습니다.

select * from unlimited_text

 id | name
----+-------
  1 | 16592
(1 row)



텍스트 필드의 OID입니다. 이것은 최대 절전 모드 버그입니다. PostgreSQL에서는 LOB를 잘못된 위치에 저장하고 OID 식별자를 저장하는 것이 올바르지만 이것은 text 데이터 유형 열이 아니어야 합니다.

Heover, 큰 개체 함수는 이것을 oid로 변환하면 작동합니다.

postgres=# select * from pg_largeobject;

 loid  | pageno |           data
-------+--------+--------------------------
 16533 |      0 | \x48656c6c6f20576f726c64
 16542 |      0 | \x48656c6c6f20576f726c64
 16592 |      0 | \x48656c6c6f20576f726c64
(3 rows)

postgres=# select *,lo_get(name::oid),convert_from(lo_get(name::oid),'UTF8') from unlimited_text;

 id | name  |          lo_get          | convert_from
----+-------+--------------------------+--------------
  1 | 16592 | \x48656c6c6f20576f726c64 | Hello World
(1 row)


@Column(columnDefinition="oid")



다음은 oid 데이터 유형을 지정하는 해결 방법입니다.

    @Column(columnDefinition="oid")
    @Lob


생성된 DDL:

    create table unlimited_text (
       id int8 not null,
        name oid,
        primary key (id)
    )


이것은 PostgreSQL에서 올바르게 작동하지만 YugabyteDB는 대형 개체를 지원하지 않습니다. 당신은 만날 것입니다:

Jul 07, 2022 3:52:20 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: ERROR: Illegal state: Transaction for catalog table write operation 'pg_largeobject_metadata' not found
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not insert: [PostgresText$UnlimitedText]
Caused by: org.hibernate.exception.GenericJDBCException: could not insert: [PostgresText$UnlimitedText]
Caused by: org.postgresql.util.PSQLException: ERROR: Illegal state: Transaction for catalog table write operation 'pg_largeobject_metadata' not found


필요하신 분들은 팔로우#3576 부탁드립니다. 그러나 클라우드 네이티브 환경에서는 해당 객체가 URL만 있는 데이터베이스가 아니라 AWS의 Amazon S3와 같은 객체 스토리지에 저장될 가능성이 높습니다.

좋은 웹페이지 즐겨찾기