바이트에 대한 적절한 최대 절전 모드 주석
최대 절전 모드 3.1 및 JPA 주석을 사용하는 응용 프로그램이 있습니다. byte [] 속성 (크기 1k-200k)을 가진 몇 개의 오브젝트가 있습니다. JPA @Lob 주석을 사용하며 최대 절전 모드 3.1은 모든 주요 데이터베이스에서 잘 읽을 수 있습니다 .JDBC Blob 공급 업체의 특성을 숨기고있는 것처럼 보입니다.
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
우리는 postgresql에서 최대 절전 모드 3.5 가이 주석 조합을 중단하고 수정하지 않는다는 것을 발견했을 때 3.5로 업그레이드해야 했습니다 (해결 방법이 없음). 지금까지 명확한 수정 사항을 찾지 못했지만 @Lob을 제거하면 postgresql 유형 bytea (작동하지만 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 속성 사용)를 찾는 방법을 찾고 있습니다.
- byte [] 속성에 주석을 달 수있는 이식 가능한 방법은 무엇입니까?
- 이것은 최신 버전의 최대 절전 모드에서 수정 되었습니까?
업데이트 : 이 블로그를 읽은 후 마침내 JIRA 문제의 원래 해결 방법이 무엇인지 알아 냈습니다 : 분명히 @Lob을 삭제하고 속성에 주석을 달아야합니다.
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
그러나 이것은 나를 위해 작동하지 않습니다. 나는 여전히 bytea 대신 OID를 얻습니다. 그러나 그것은 무효를 원한 것처럼 보이는 JIRA 이슈의 저자에게는 효과가있었습니다.
A. Garcia의 답변 후, 나는이 조합을 시도했는데 실제로 postgresql에서는 작동하지만 오라클에서는 작동하지 않습니다.
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
내가 정말로해야 할 일은 @ org.hibernate.annotations. (@ Lob + byte []가 매핑 됨)을 (postgresql에서) 매핑하는 것을 제어하는 것입니다.
다음은 MaterializedBlobType (sql 유형 Blob)의 3.5.5.Final 스 니펫입니다. Steve의 블로그에 따르면 postgresql은 bytea에 스트림을 사용하고 (이유 묻지 않음) postgresql의 사용자 정의 Blob 유형을 Oid에 사용하려고합니다. 또한 JDBC에서 setBytes ()를 사용하는 것은 과거 경험에 의한 bytea에도 해당됩니다. 따라서 이것은 사용 스트림이 모두 'bytea'를 가정하는 데 영향을 미치지 않는 이유를 설명합니다.
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
업데이트 다음 논리적 질문은 "테이블 정의를 bytea로 수동 변경하지 않는 이유"와 (@Lob + byte [])를 유지하는 것입니다. 이것은 수행 , 작업을 UNTIL 당신은 [] 널 바이트를 저장하려고합니다. postgreSQL 드라이버가 OID 유형 표현식이라고 생각하고 열 유형은 bytea입니다. 이것은 PG 드라이버가 기대하는 JDBC.setBytes (null) 대신 최대 절전 모드 (상시 적으로) JDBC.setNull ()을 호출하기 때문입니다.
ERROR: column "signature" is of type bytea but expression is of type oid
최대 절전 모드의 형식 시스템은 현재 '작업 진행 중'입니다 (3.5.5 지원 중단 설명에 따라). 실제로 3.5.5 코드의 대부분은 더 이상 사용되지 않으므로 PostgreSQLDialect를 서브 클래 싱 할 때 무엇을 볼지 알기가 어렵습니다).
postgresql의 AFAKT, Types.BLOB / 'oid'는 OID 스타일 JDBC 액세스 (예 : PostgresqlBlobType 객체 및 NOT MaterializedBlobType)를 사용하는 일부 사용자 정의 유형에 매핑되어야합니다. 나는 실제로 postgresql과 함께 Blob을 성공적으로 사용하지는 않았지만 bytea는 단순히 하나 / 내가 기대하는대로 작동한다는 것을 알고 있습니다.
현재 BatchUpdateException을보고 있습니다. 드라이버가 일괄 처리를 지원하지 않을 수 있습니다.
2004 년의 큰 인용문 : "내 문제를 요약하려면, Hibernate를 변경하기 전에 JDBC 드라이버가 LOB를 제대로 수행 할 때까지 기다려야한다고 말했다."
참고 문헌 :
- https://forum.hibernate.org/viewtopic.php?p=2393203
- https://forum.hibernate.org/viewtopic.php?p=2435174
- http://hibernate.atlassian.net/browse/HHH-4617
- http://postgresql.1045698.n5.nabble.com/Migration-to-Hibernate-3-5-final-td2175339.html
- https://jira.springframework.org/browse/SPR-2318
- https://forums.hibernate.org/viewtopic.php?p=2203382&sid=b526a17d9cf60a80f13d40cf8082aafd
- http://virgo47.wordpress.com/2008/06/13/jpa-postgresql-and-bytea-vs-oid-type/
byte [] 속성에 주석을 달 수있는 이식 가능한 방법은 무엇입니까?
그것은 당신이 원하는 것에 달려 있습니다. JPA는 주석이없는 상태로 지속될 수 있습니다 byte[]
. JPA 2.0 스펙에서 :
11.1.6 기본 주석
Basic
주석 데이터베이스 컬럼에 매핑의 간단한 형식입니다.Basic
주석은 다음과 같은 유형의 불변의 재산 또는 인스턴스 변수에 적용 할 수 있습니다 : 자바 원시, 유형, 원시 타입 래퍼,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[]
, 열거, 그리고 다른 종류의 것을 구현Serializable
. 섹션 2.8에서 설명했듯이Basic
이러한 유형의 영구 필드 및 속성 에는 주석 사용이 선택 사항입니다. 이러한 필드 또는 특성에 기본 주석이 지정되지 않은 경우 기본 주석의 기본값이 적용됩니다.
그리고 Hibernate는 그것을 "기본으로" PostgreSQL이 처리 하는 SQL VARBINARY
(또는 크기 LONGVARBINARY
에 따라 SQL Column
?) 에 매핑 합니다 bytea
.
그러나를 byte[]
대형 객체에 저장하려면을 사용해야합니다 @Lob
. 사양에서 :
11.1.24 로브 주석
Lob
지속적인 속성 또는 필드가 데이터베이스 지원 대형 오브젝트 유형에 큰 개체로 유지해야하는지 주석 지정합니다. 이식 가능한 응용 프로그램은Lob
데이터베이스Lob
유형에 매핑 할 때 주석을 사용해야합니다 .Lob
주석은 주석 기본으로 또는 함께 사용될 수ElementCollection
있는 요소 컬렉션 값 기본 형인 경우 주석. ALob
는 이진 또는 문자 유형일 수 있습니다.Lob
유형은 문자열 및 문자 유형, 물방울 기본값을 제외하고, 지속 필드 또는 속성의 유형에서 유추된다.
그리고 Hibernate는 이것을 BLOB
PostgreSQL이 처리 하는 SQL에 매핑합니다 oid
.
이것은 최신 버전의 최대 절전 모드에서 수정 되었습니까?
글쎄, 문제는 문제가 정확히 무엇인지 모른다는 것입니다. 그러나 적어도 3.5.x 브랜치에서 3.5.0-Beta-2 (변경된 부분이 소개 된 곳) 이후로 변경된 것이 없다고 말할 수 있습니다.
그러나 HHH-4876 , HHH-4617 및 PostgreSQL 및 BLOB (의 javadoc에 언급 됨) 와 같은 문제에 대한 이해 PostgreSQLDialect
는 다음 속성을 설정해야한다는 것입니다.
hibernate.jdbc.use_streams_for_binary=false
oid
ie byte[]
와 함께 사용하고 싶다면 @Lob
( VARBINARY
오라클에서 원하는 것이 아니기 때문에 내 이해 입니다). 이것을 시도 했습니까?
대안으로, HHH-4876 은 더 이상 사용되지 않는 것을 사용 PrimitiveByteArrayBlobType
하여 이전 동작을 얻 도록 제안합니다 (Hibernate 3.5 이전).
참고 문헌
- JPA 2.0 사양
- 2.8 절 "비 관계형 필드 또는 속성에 대한 기본값 매핑"
- 11.1.6 "기본 주석"
- 11.1.24 "작업 주석"
자원
- http://opensource.atlassian.com/projects/hibernate/browse/HHH-4876
- http://opensource.atlassian.com/projects/hibernate/browse/HHH-4617
- http://relation.to/Bloggers/PostgreSQLAndBLOBs
다음은 O'reilly Enterprise JavaBeans, 3.0의 내용입니다.
JDBC에는 이러한 매우 큰 객체에 대한 특수 유형이 있습니다. java.sql.Blob 유형은 2 진 데이터 를 나타내고 java.sql.Clob은 문자 데이터를 나타냅니다.
다음은 PostgreSQLDialect 소스 코드입니다.
public PostgreSQLDialect() {
super();
...
registerColumnType(Types.VARBINARY, "bytea");
/**
* Notice it maps java.sql.Types.BLOB as oid
*/
registerColumnType(Types.BLOB, "oid");
}
그래서 당신이 할 수있는 일
다음과 같이 PostgreSQLDialect를 재정의하십시오.
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 에서 실행중인 응용 프로그램이 있고 모든 블롭 필드가 oid (java에서 byte [] 사용)
...
최대 절전 모드 3.5로 마이그레이션하면 모든 BLOB 필드가 더 이상 작동하지 않으며 서버 로그에 다음이 표시됩니다.
여기서 설명 할 수 있습니다
이 generaly는 PG JDBC에서 버그가 아닙니다 , 하지만 3.5 버전에서는 최대 절전 모드의 기본 구현의 변화 . 내 상황 에서 연결시 호환 속성을 설정하지 못했습니다 .
...
내가 3.5에서 보았던 훨씬 더 많은 것-베타 2, 이것이 고쳐 졌는지 모르겠다. @Type 주석없이- 유형의 열을 자동 생성하지만 bytea로 읽습니다.
흥미롭게도 Types.BOLB를 bytea로 매핑 할 때 (CustomPostgreSQLDialect 참조)
JDBC 배치 업데이트를 실행할 수 없습니다
삽입하거나 업데이트 할 때
나는 마침내이 일을했다. A. Garcia의 솔루션에서 확장되지만 문제는 최대 절전 모드 유형 MaterializedBlob 유형에 있기 때문에 Blob> bytea로는 충분하지 않으므로 최대 절전 모드 깨진 Blob 지원과 함께 작동하는 MaterializedBlobType을 대체해야합니다. 이 구현은 bytea에서만 작동하지만 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);
}
}
Postgres 9.3에서 Hibernate 4.2.7.SP1을 사용하고 있으며 다음과 같은 효과가 있습니다.
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
오라클은 그것에 문제가 없으므로 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);
}
}
내가 생각하는이 솔루션의 장점은 최대 절전 항아리를 그대로 유지할 수 있다는 것입니다.
Hibernate와 관련된 Postgres / Oracle 호환성 문제에 대해서는 내 블로그 게시물을 참조하십시오 .
i fixed My issue by adding the annotation of @Lob which will create the byte[] in oracle as blob , but this annotation will create the field as oid which not work properly , To make byte[] created as bytea i made customer Dialect for postgres as below
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);
}
}
Also need to override parameter for the Dialect
spring.jpa.properties.hibernate.dialect=com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom
more hint can be found her : https://dzone.com/articles/postgres-and-oracle
I got it work by overriding annotation with XML file for Postgres. Annotation is kept for Oracle. In my opinion, in this case it would be best we override the mapping of this trouble-some enity with xml mapping. We can override single / multiple entities with xml mapping. So we would use annotation for our mainly-supported database, and a xml file for each other database.
Note: we just need to override one single class , so it is not a big deal. Read more from my example Example to override annotation with XML
On Postgres @Lob is breaking for byte[] as it tries to save it as oid, and for String also same problem occurs. Below code is breaking on postgres which is working fine on oracle.
@Lob
private String stringField;
and
@Lob
private byte[] someByteStream;
In order to fix above on postgres have written below custom hibernate.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);
}
}
Now configure custom dialect in hibernate
hibernate.dialect=X.Y.Z.PostgreSQLDialectCustom
X.Y.Z is package name.
Now it working fine. NOTE- My Hibernate version - 5.2.8.Final Postgres version- 9.6.3
Thanks Justin, Pascal for guiding me to the right direction. I was also facing the same issue with Hibernate 3.5.3. Your research and pointers to the right classes had helped me identify the issue and do a fix.
For the benefit for those who are still stuck with Hibernate 3.5 and using oid + byte[] + @LoB combination, following is what I have done to fix the issue.
I created a custom BlobType extending MaterializedBlobType and overriding the set and the get methods with the oid style access.
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)); } }
Register the CustomBlobType with Hibernate. Following is what i did to achieve that.
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
'programing tip' 카테고리의 다른 글
속기 배경 속성의 배경 크기 (CSS3) (0) | 2020.08.06 |
---|---|
Visual Studio에서 Interop 유형 포함 참과 거짓의 차이점은 무엇입니까? (0) | 2020.08.06 |
동기화 작업 대신 비동기 WebAPI 작업을 만들어야하는 이유는 무엇입니까? (0) | 2020.08.06 |
NameNotFoundException 웹뷰 (0) | 2020.08.06 |
버전 관리 저장소를 어떻게 구성합니까? (0) | 2020.08.06 |