programing

바이트의 적절한 휴지 상태 주석 []

newsource 2022. 9. 16. 21:04

바이트의 적절한 휴지 상태 주석 []

hibernate 3.1과 JPA 주석을 사용하는 어플리케이션을 가지고 있습니다.byte[] 속성(1k~200k 크기)을 가진 개체가 몇 개 있습니다.이것은 JPA @Lob 주석을 사용하며, 휴지 상태 3.1은 모든 주요 데이터베이스에서 이러한 주석을 올바르게 읽을 수 있습니다.JDBC BLOB 벤더의 특성을 숨기고 있는 것 같습니다(필요에 따라).

@Entity
public class ConfigAttribute {
  @Lob
  public byte[] getValueBuffer() {
    return m_valueBuffer;
  }
}

휴지 상태의 3.5가 이 주석 조합을 postgresql(회피책 없음)에서 깨짐(수정되지 않음)을 발견했을 때 3.5로 업그레이드해야 했습니다.아직 확실한 수정은 발견되지 않았지만, @Lob을 삭제하기만 하면 postgresql 타입의 바이트a가 사용된다는 것을 알게 되었습니다(이 타입은 postgres에서만 동작합니다).

annotation                   postgres     oracle      works on
-------------------------------------------------------------
byte[] + @Lob                oid          blob        oracle
byte[]                       bytea        raw(255)    postgresql
byte[] + @Type(PBA)          oid          blob        oracle
byte[] + @Type(BT)           bytea        blob        postgresql

once you use @Type, @Lob seems to not be relevant
note: oracle seems to have deprecated the "raw" type since 8i.

주요 데이터베이스 간에 이식 가능한 단일 주석 클래스(BLOB 속성 포함)를 만드는 방법을 찾고 있습니다.

  • 바이트[] 속성에 주석을 다는 휴대용 방법은 무엇입니까?
  • 이것은 최신 버전의 휴지 상태에서 수정되었습니까?

업데이트:블로그를 읽고 JIRA의 원래 회피책이 무엇이었는지 알게 되었습니다.아마 당신은 @Lob을 드롭하고 다음과 같이 속성에 주석을 달아야 할 것 같습니다.

@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType") 
byte[] getValueBuffer() {...

다만, 이것은 나에게 있어서 효과가 없습니다.Bytea가 아닌 OID를 취득하고 있습니다만, JIRA의 저자가 OID를 필요로 하는 것 같았던 것은 효과가 있었습니다.

A의 답변 뒤에.가르시아, 이 조합은 실제로 postgresql에서는 작동하지만 oracle에서는 작동하지 않습니다.

@Type(type="org.hibernate.type.BinaryType") 
byte[] getValueBuffer() {...

제가 정말 해야 할 일은 which@org.hibernate.an 주석을 제어하는 것입니다.(@Lob + byte[]가 매핑됨)의 조합을 (postgresql)에 입력합니다.


이것은 3.5.5의 단편입니다.MaterializedBlobType(sql type Blob)에서 최종.Steve의 블로그에 따르면, postgresql은 bytea에는 Streams를 사용하고(이유는 묻지 않음), oid에는 postgresql의 커스텀 Blob 타입을 사용하고 싶다고 합니다.또한 JDBC에서 setBytes()를 사용하는 것도 (과거 경험에서) 바이트에 대한 것입니다.따라서 use-streams가 모두 'byta'로 가정하는 데 영향을 미치지 않는 이유가 설명됩니다.

public void set(PreparedStatement st, Object value, int index) {
 byte[] internalValue = toInternalFormat( value );
 if ( Environment.useStreamsForBinary() ) {
  // use streams = true
   st.setBinaryStream( index, 
    new ByteArrayInputStream( internalValue ), internalValue.length );
 }
 else {
  // use streams = false
  st.setBytes( index, internalValue );
 }
}

그 결과 다음과 같습니다.

ERROR: column "signature" is of type oid but expression is of type bytea

업데이트 다음 논리적인 질문은 "테이블 정의를 수동으로 바이트로 변경하여 (@Lob + byte[])를 유지하면 어떨까요?"입니다.null 바이트[]를 저장하려고 할 까지 이 방법은 기능합니다.어떤 우체국?SQL 드라이버는 OID 타입의 표현으로 컬럼 타입은 bytea라고 생각합니다.이는 휴지 상태(오른쪽)가 JDBC가 아닌 JDBC.setNull()을 호출하기 때문입니다.PG 드라이버가 예기하는 setBytes(null).

ERROR: column "signature" is of type bytea but expression is of type oid

휴지 상태의 유형 시스템은 현재 '작업 진행 중'입니다(3.5.5 권장 해제 코멘트).사실 3.5.5 코드는 대부분 사용되지 않기 때문에 Postgre를 하위 분류할 때 무엇을 검토해야 하는지 알 수 없습니다.SQLDualect)

AFAKT, 유형.postgresql의 BLOB/'oid'는 OID 스타일의 JDBC 액세스를 사용하는 일부 사용자 지정 유형(PostgresqlBlobType 개체와 NOT MaterializedBlobType)에 매핑해야 합니다.실제로 Postgresql에서 Blobs를 성공적으로 사용한 적은 없지만, bytea는 단순히 1대로만 작동한다는 것은 알고 있습니다.

현재 BatchUpdateException을 보고 있습니다.드라이버가 일괄 처리를 지원하지 않을 수 있습니다.


2004년의 명언: "내 말을 요약하면, 휴지 상태를 변경하기 전에 JDBC 드라이버가 올바르게 LOB를 실행할 때까지 기다려야 한다고 생각합니다."

참고 자료:

바이트[] 속성에 주석을 다는 휴대용 방법은 무엇입니까?

그것은 당신이 무엇을 원하는 지에 달려 있어요.JPA는 주석이 없는 상태를 유지할 수 있습니다.byte[]JPA 2.0 사양부터:

11.1.6 기본 주석

Basic주석은 데이터베이스 열에 매핑하는 가장 간단한 유형입니다.Basic주석은 다음 유형의 영구 속성 또는 인스턴스 변수에 적용할 수 있습니다. Java primitive, type, primitive type의 래퍼,java.lang.String,java.math.BigInteger,java.math.BigDecimal,java.util.Date,java.util.Calendar,java.sql.Date,java.sql.Time,java.sql.Timestamp, byte[], Byte[],char[],Character[], enums 및 를 구현하는 기타 유형Serializable. 섹션 2.8에 기술된 바와 같이.Basic주석은 이러한 유형의 영구 필드 및 속성의 경우 옵션입니다.이러한 필드 또는 속성에 대해 기본 주석이 지정되지 않은 경우 기본 주석의 기본값이 적용됩니다.

휴지 상태에서는 "기본값"으로 SQL에 매핑됩니다.VARBINARY(또는 SQL)LONGVARBINARY에 따라서는Column사이즈가 어떻게 됩니까?)SQL 핸들:bytea.

하지만 당신이 원한다면byte[]Large Object에 저장하기 위해서는,@Lob. 사양서:

11.1.24 로브 주석

A Lobannotation은 영구 속성 또는 필드를 데이터베이스에서 지원되는 큰 개체 유형에 대한 큰 개체로 유지하도록 지정합니다.휴대용 어플리케이션에서는Lob데이터베이스에 매핑할 때 주석Lob입력.Lob주석은 기본 주석 또는 기본 주석과 함께 사용할 수 있습니다.ElementCollection요소 수집 값이 기본 유형인 경우 주석을 추가합니다.aLob이진 또는 문자 유형 중 하나일 수 있습니다.Lobtype은 영속적인 필드 또는 속성의 유형에서 유추되며 문자열 및 문자 유형을 제외하고 기본값은 Blob입니다.

휴지 상태에서는 SQL에 매핑됩니다.BLOB그 포스트그레SQL 핸들:oid.

이것은 최신 버전의 휴지 상태에서 수정되었습니까?

음, 문제는 정확히 뭐가 문제인지 모른다는 거야.그러나 적어도 3.5.x 브랜치의 3.5.0-Beta-2(변경된 부분) 이후로는 아무것도 변하지 않았다고 말할 수 있습니다.

그러나 HH-4876, HH-4617Postgre와 같은 문제에 대한 저의 이해는SQLBLOB(의 javadoc에 기재되어 있습니다.PostgreSQLDialect)는 다음과 같은 속성을 설정하도록 되어 있습니다.

hibernate.jdbc.use_streams_for_binary=false

사용하고 싶다면oid예.byte[]와 함께@Lob(이후로 제가 이해한 것은VARBINARYOracle에서는 원하는 것이 아닙니다.)이거 먹어봤어?

그 대신 HH-4876은 권장되지 않는 것을 사용할 것을 권장합니다.PrimitiveByteArrayBlobType이전 동작을 얻습니다(3.5 이전 휴지 상태).

레퍼런스

  • JPA 2.0 사양
    • 섹션 2.8 "비관계 필드 또는 속성의 기본값 매핑"
    • 섹션 11.1.6 "기본 주석"
    • 섹션 11.1.24 "Lob 주석"

자원.

다음은 O'reilly Enterprise JavaBeans, 3.0의 설명입니다.

JDBC에는 이러한 매우 큰 오브젝트에 대한 특수한 타입이 있습니다.java.sql.BLOB 유형은 이진 데이터와 java.sql을 나타냅니다.Clob은 문자 데이터를 나타냅니다.

Postgre 갑니다SQLDirect 소스 코드

public PostgreSQLDialect() {
    super();
    ...
    registerColumnType(Types.VARBINARY, "bytea");
    /**
      * Notice it maps java.sql.Types.BLOB as oid
      */
    registerColumnType(Types.BLOB, "oid");
}

그래서 할 수 있는 건

Postgre 덮어쓰기SQLDirect는 다음과 같습니다.

public class CustomPostgreSQLDialect extends PostgreSQLDialect {

    public CustomPostgreSQLDialect() {
        super();

        registerColumnType(Types.BLOB, "bytea");
    }
}

이제 사용자 지정 사투리를 정의하십시오.

<property name="hibernate.dialect" value="br.com.ar.dialect.CustomPostgreSQLDialect"/>

또한 휴대용 JPA @Lob 주석을 사용합니다.

@Lob
public byte[] getValueBuffer() {

갱신하다

여기서 추출했습니다.

응용 프로그램이 휴지 상태 3.3.2로 실행되고 있으며 응용 프로그램은 정상적으로 동작하며 모든 blob 필드는 oid(자바의 바이트[])를 사용합니다.

...

휴지 상태 3.5로 이행하면 모든 blob 필드가 작동하지 않게 되어 서버 로그에 ERROR org.hibernate.util 이라고 표시됩니다.JDBCExceptionReporter - ERROR: 열은 oid 형식이지만 식이 바이트a 형식입니다.

설명할 수 있는 것은 여기서

일반은 PG JDBC의 버그아니라 3.5 버전의 휴지 상태 기본 구현 변경입니다.내 상황에서는 연결 시 호환 속성을 설정하는 것이 도움이 되지 않았습니다.

...

게다가 3.5에서 본 베타 2는, 이것이 Hibernate인지 아닌지는 모르겠지만, @Type 주석 없이, 타입 oid 컬럼을 자동적으로 작성하지만, 이것을 바이트로서 읽으려고 합니다.

흥미로운 건 그가 타이프 지도를 그릴 때죠바이트로서의 BOLB(Custom Postgr 참조)SQLDialect) 그는

JDBC 배치 업데이트를 실행할 수 없습니다.

삽입 또는 갱신 시

Hibernate 4.2.7을 사용하고 있습니다.Postgres 9.3을 탑재한 SP1은 다음과 같습니다.

@Entity
public class ConfigAttribute {
  @Lob
  public byte[] getValueBuffer() {
    return m_valueBuffer;
  }
}

Oracle에서는 문제가 없기 때문에 Postgres에서는 커스텀 사투리를 사용하고 있습니다.

public class PostgreSQLDialectCustom extends PostgreSQL82Dialect {

    @Override
    public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
      return BinaryTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }
}

이 솔루션의 장점은 겨울잠을 자는 병을 손대지 않고 유지할 수 있다는 것입니다.

휴지 상태에서의 Postgres/Oracle 호환성 문제에 대해서는 블로그 투고를 참조하십시오.

드디어 이 일을 해냈다.A에서 솔루션을 확장합니다.단, Garcia는 하이버네이트 타입의 Materialized Blob 타입에 문제가 있기 때문에 맵핑 Blob > bytea만으로는 불충분하기 때문에 하이버네이트가 파손된 Blob 지원으로 동작하는 Materialized Blob Type을 교체해야 합니다.이 실장은 바이트만 사용 가능하지만 OID를 원하는 JIRA 문제 담당자는 OID 구현에 기여할 수 있습니다.

안타깝게도 런타임에 이러한 유형을 교체하는 것은 매우 어렵습니다. 왜냐하면 그것들은 방언의 일부여야 하기 때문입니다. JIRA 확장만 3.6으로 하면 가능합니다.

public class PostgresqlMateralizedBlobType extends AbstractSingleColumnStandardBasicType<byte[]> {
 public static final PostgresqlMateralizedBlobType INSTANCE = new PostgresqlMateralizedBlobType();

 public PostgresqlMateralizedBlobType() {
  super( PostgresqlBlobTypeDescriptor.INSTANCE, PrimitiveByteArrayTypeDescriptor.INSTANCE );
 }

  public String getName() {
   return "materialized_blob";
  }
}

대부분의 경우 정적(getBinder()이 정말로 새로운 인스턴스가 필요한가?)일 수 있지만, 저는 휴지 상태의 내부 인스턴스를 잘 이해하지 못하기 때문에 대부분 복사 + 붙여넣기 + 수정입니다.

public class PostgresqlBlobTypeDescriptor extends BlobTypeDescriptor implements SqlTypeDescriptor {
  public static final BlobTypeDescriptor INSTANCE = new PostgresqlBlobTypeDescriptor();

  public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
   return new PostgresqlBlobBinder<X>(javaTypeDescriptor, this);
  }
  public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
   return new BasicExtractor<X>( javaTypeDescriptor, this ) {
    protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException { 
      return (X)rs.getBytes(name);
    }
   };
  }
}

public class PostgresqlBlobBinder<J> implements ValueBinder<J> {
 private final JavaTypeDescriptor<J> javaDescriptor;
 private final SqlTypeDescriptor sqlDescriptor;

 public PostgresqlBlobBinder(JavaTypeDescriptor<J> javaDescriptor, SqlTypeDescriptor sqlDescriptor) { 
  this.javaDescriptor = javaDescriptor; this.sqlDescriptor = sqlDescriptor;
 }  
 ...
 public final void bind(PreparedStatement st, J value, int index, WrapperOptions options) 
 throws SQLException {
  st.setBytes(index, (byte[])value);
 }
}

@Lob의 주석을 추가하여 문제를 해결했습니다.이 주석으로 oracle의 바이트[]가 blob으로 작성됩니다.bytea로 작성된 바이트[]는 아래와 같이 포스트그리어의 고객용 사투리로 작성됩니다.

Public class PostgreSQLDialectCustom extends PostgreSQL82Dialect {
    public PostgreSQLDialectCustom() {
        System.out.println("Init PostgreSQLDialectCustom");
        registerColumnType( Types.BLOB, "bytea" );

      }

    @Override
    public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
      return BinaryTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }
 }

또한 방언에 대한 매개 변수를 재정의해야 합니다.

spring.jpa.properties.hibernate.dispon=com.ntg.common 입니다.DBC CompatibilityHelper.PostgreSQLDualect 커스텀

더 많은 힌트를 찾을 수 있습니다:https://dzone.com/articles/postgres-and-oracle

Postgres @Lob은 바이트 []를 oid로 저장하려고 할 때 중단됩니다.String에서도 같은 문제가 발생합니다.아래 코드는 postgres에서 breaking되고 있으며, oracle에서는 정상적으로 동작하고 있습니다.

@Lob
private String stringField;

그리고.

@Lob
private byte[]   someByteStream;

위의 postgres를 수정하기 위해 커스텀 휴지 상태 아래에 기술되어 있습니다.dialect

public class PostgreSQLDialectCustom extends PostgreSQL82Dialect{

public PostgreSQLDialectCustom()
{
    super();
    registerColumnType(Types.BLOB, "bytea");
}

 @Override
 public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
      return LongVarcharTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }
}

이제 최대 절전 모드에서 사용자 지정 방언 구성

hibernate.dialect=X.Y.Z.PostgreSQLDialectCustom   

X.Y.Z는 패키지 이름입니다.

이제 잘 작동한다.메모 - 휴지 상태 버전 - 5.2.8.최종 Postgres 버전 - 9.6.3

  1. 엔티티에서 사용할 수 있습니다.
@Lob
@Type(type = "org.hibernate.type.BinaryType")
@Column(name = "stringField")
private byte[] stringField;

Postgres용 XML 파일로 주석을 덮어쓰면서 작업을 했습니다.주석은 Oracle용으로 유지됩니다.이 경우 xml 매핑으로 이 문제의 매핑을 덮어쓰는 것이 최선이라고 생각합니다.xml 매핑으로 단일/복수의 엔티티를 덮어쓸 수 있습니다.따라서 주로 지원되는 데이터베이스에는 주석을 사용하고 서로 데이터베이스에는 xml 파일을 사용합니다.

주의: 1개의 클래스만 덮어쓸 필요가 있기 때문에 큰 문제는 아닙니다.예제에서 자세히 알아보기 XML로 주석을 재정의하는 예

Justin, Pascal이 나를 올바른 방향으로 인도해줘서 고마워.Hibernate 3.5.3에서도 같은 문제가 발생했습니다.올바른 수업에 대한 당신의 연구와 조언은 문제를 식별하고 수정하는 데 도움이 되었습니다.

Hibernate 3.5에서 여전히 oid + byte [] + @LoB 조합을 사용하고 있는 사용자에게 이 문제를 해결하기 위해 다음과 같은 작업을 수행했습니다.

  1. MaterializedBlobType을 확장하고 oid 스타일 액세스로 set 및 get 메서드를 덮어쓰는 커스텀 BlobType을 만들었습니다.

    public class CustomBlobType extends MaterializedBlobType {
    
    private static final String POSTGRESQL_DIALECT = PostgreSQLDialect.class.getName();
    
    /**
     * Currently set dialect.
     */
    private String dialect = hibernateConfiguration.getProperty(Environment.DIALECT);
    
    /*
     * (non-Javadoc)
     * @see org.hibernate.type.AbstractBynaryType#set(java.sql.PreparedStatement, java.lang.Object, int)
     */
    @Override
    public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        byte[] internalValue = toInternalFormat(value);
    
        if (POSTGRESQL_DIALECT.equals(dialect)) {
            try {
    
    //I had access to sessionFactory through a custom sessionFactory wrapper.
    st.setBlob(index, Hibernate.createBlob(internalValue, sessionFactory.getCurrentSession()));
                } catch (SystemException e) {
                    throw new HibernateException(e);
                }
            } else {
                st.setBytes(index, internalValue);
            }
        }
    
    /*
     * (non-Javadoc)
     * @see org.hibernate.type.AbstractBynaryType#get(java.sql.ResultSet, java.lang.String)
     */
    @Override
    public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
        Blob blob = rs.getBlob(name);
        if (rs.wasNull()) {
            return null;
        }
        int length = (int) blob.length();
        return toExternalFormat(blob.getBytes(1, length));
      }
    }
    
    1. CustomBlobType을 휴지 상태로 등록합니다.내가 그것을 이루기 위해 한 일은 다음과 같다.

      hibernateConfiguration= new AnnotationConfiguration();
      Mappings mappings = hibernateConfiguration.createMappings();
      mappings.addTypeDef("materialized_blob", "x.y.z.BlobType", null);
      

언급URL : https://stackoverflow.com/questions/3677380/proper-hibernate-annotation-for-byte