chú thích ngủ đông thích hợp cho byte []


120

Tôi có một ứng dụng sử dụng chú thích hibernate 3.1 và JPA. Nó có một vài đối tượng có thuộc tính byte [] (kích thước 1k - 200k). Nó sử dụng chú thích JPA @Lob và hibernate 3.1 có thể đọc những điều này tốt trên tất cả các cơ sở dữ liệu chính - nó dường như che giấu các đặc thù của nhà cung cấp JDBC Blob (như nó nên làm).

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

Chúng tôi đã phải nâng cấp lên 3,5, khi chúng tôi phát hiện ra rằng nghỉ ngủ 3,5 (và sẽ không sửa) kết hợp chú thích này trong postgresql (không có cách giải quyết). Tôi đã không tìm thấy một sửa chữa rõ ràng cho đến nay, nhưng tôi đã nhận thấy rằng nếu tôi chỉ gỡ bỏ @Lob, nó sử dụng loại bytea postgresql (hoạt động, nhưng chỉ trên 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.

Tôi đang tìm cách để có một lớp chú thích duy nhất (với thuộc tính blob) có thể di động trên các cơ sở dữ liệu chính.

  • Cách di động để chú thích một thuộc tính byte [] là gì?
  • Điều này có cố định trong một số phiên bản gần đây của ngủ đông không?

Cập nhật: Sau khi đọc blog này, cuối cùng tôi cũng đã tìm ra cách giải quyết ban đầu trong vấn đề JIRA là: Rõ ràng bạn phải bỏ @Lob và chú thích tài sản là:

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

Tuy nhiên, điều này không hiệu quả với tôi - tôi vẫn nhận được OID thay vì bytea; tuy nhiên nó đã làm việc cho tác giả của vấn đề JIRA, người dường như muốn oid.

Sau câu trả lời từ A. Garcia, sau đó tôi đã thử kết hợp này, thực sự hoạt động trên postgresql, nhưng không phải trên orory.

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

Điều tôi thực sự cần làm là kiểm soát @ org.hibernate.annotations. Gõ sự kết hợp (@Lob + byte [] được ánh xạ) thành (trên postgresql).


Đây là đoạn trích từ 3.5.5.Final từ MaterializedBlobType (kiểu sql Blob). Theo blog của Steve, postgresql muốn bạn sử dụng Streams cho bytea (đừng hỏi tôi tại sao) và loại Blob tùy chỉnh của postgresql cho các oids. Cũng lưu ý rằng việc sử dụng setBytes () trên JDBC cũng dành cho bytea (từ kinh nghiệm trong quá khứ). Vì vậy, điều này giải thích tại sao các luồng sử dụng không ảnh hưởng đến cả hai đều giả định '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 );
 }
}

Kết quả này trong:

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

Cập nhật Câu hỏi logic tiếp theo là: "tại sao không thay đổi định nghĩa bảng theo cách thủ công thành bytea" và giữ (@Lob + byte [])? Điều này không hoạt động, UNTIL bạn cố gắng lưu trữ một byte null []. Trình điều khiển postgreQuery nghĩ là biểu thức kiểu OID và kiểu cột là bytea - điều này là do hibernate (phải) gọi JDBC.setNull () thay vì JDBC.setBytes (null) mà trình điều khiển PG mong đợi.

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

Hệ thống loại trong chế độ ngủ đông hiện đang là một 'công việc đang tiến hành' (theo nhận xét khấu hao 3.5.5). Trong thực tế, rất nhiều mã 3.5.5 không được dùng nữa, thật khó để biết phải xem gì khi phân lớp PostgreQueryDialect).

AFAKT, Các loại.BLOB / 'oid' trên postgresql nên được ánh xạ tới một số loại tùy chỉnh sử dụng truy cập JDBC kiểu OID (ví dụ: đối tượng PostgresqlBlobType và KHÔNG MaterializedBlobType). Tôi chưa bao giờ thực sự sử dụng thành công Blobs với postgresql, nhưng tôi biết rằng bytea chỉ đơn giản là hoạt động như một / tôi mong đợi.

Tôi hiện đang xem BatchUpdateException - có thể trình điều khiển không hỗ trợ theo đợt.


Câu nói hay từ năm 2004: "Để tổng hợp những lời huyên thuyên của tôi, tôi muốn nói rằng chúng ta nên chờ trình điều khiển JDBC thực hiện LOB đúng cách trước khi thay đổi Hibernate."

Người giới thiệu:


Điều này dường như đã được sửa trong 3.6, không chắc chắn về 3.5.6; lớp MaterializedBlobType được viết lại hoàn toàn từ 3.5.5> 3.6. Loại OID hiện hoạt động kể từ khi họ thay đổi triển khai.
Justin

Đẹp! Tôi tự hỏi vấn đề Jira đang theo dõi việc viết lại này là gì, nếu có (có thể việc viết lại là hậu quả của một sự thay đổi sâu sắc hơn). Sẽ là tốt để backport những thay đổi trong 3.5, nếu có thể. Tin xấu nếu không thể.
Pascal Thivent

Trên thực tế, lần thử nghiệm đầu tiên của tôi đã cho tôi kết quả dương tính giả (biết rằng tôi nên đợi!) - nó vẫn chưa được sửa, lỗi vừa chuyển sang BlobTypeDescriptor.
Justin

Cảm ơn. @Type (type = "org.hibernate.type.BinaryType") đã làm việc cho tôi đối với một bảng lưu trữ tệp PDF. Tôi đã di chuyển cơ sở dữ liệu từ Oracle sang Postgres bằng cách sử dụng Oracle-To-PostgreSQL từ Bộ chuyển đổi thông minh và nó tự động chuyển đổi và chèn từ BLOB sang BYTEA nhưng BlobType không hoạt động với tôi.
jmoran

Câu trả lời:


68

Cách di động để chú thích một thuộc tính byte [] là gì?

Nó phụ thuộc vào những gì bạn muốn. JPA có thể tồn tại không chú thích byte[]. Từ thông số kỹ thuật JPA 2.0:

11.1.6 Chú thích cơ bản

Các Basicchú thích là loại đơn giản nhất của ánh xạ tới một cột cơ sở dữ liệu. Các Basicchú thích có thể được áp dụng cho một tài sản hoặc trường hợp biến dai dẳng của bất kỳ các loại sau đây: Java nguyên thủy, các loại, giấy gói các loại nguyên thủy, 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, và loại nào khác mà cụ Serializable. Như được mô tả trong Phần 2.8, việc sử dụng Basicchú thích là tùy chọn cho các trường và thuộc tính liên tục của các loại này. Nếu chú thích cơ bản không được chỉ định cho một trường hoặc thuộc tính như vậy, các giá trị mặc định của chú thích cơ bản sẽ được áp dụng.

Và Hibernate sẽ ánh xạ nó "theo mặc định" sang SQL VARBINARY(hoặc SQL LONGVARBINARYtùy thuộc vào Columnkích thước?) Mà PostgreQuery xử lý với a bytea.

Nhưng nếu bạn muốn byte[]lưu trữ trong Đối tượng lớn, bạn nên sử dụng a @Lob. Từ thông số kỹ thuật:

11.1.24 Chú thích Thùy

Một Lobchú thích xác định rằng một thuộc tính hoặc trường liên tục phải được duy trì dưới dạng một đối tượng lớn đối với loại đối tượng lớn được hỗ trợ cơ sở dữ liệu. Các ứng dụng di động nên sử dụng Lobchú thích khi ánh xạ tới Lobloại cơ sở dữ liệu . Các Lobchú thích có thể được sử dụng cùng với các chú thích cơ bản hoặc với ElementCollectionchú thích khi giá trị bộ sưu tập phần tử là các loại hình cơ bản. A Lobcó thể là kiểu nhị phân hoặc ký tự. Các Lobloại được suy ra từ các loại lĩnh vực dai dẳng hoặc tài sản và, ngoại trừ chuỗi và nhân vật các loại, giá trị mặc định để Blob.

Và Hibernate sẽ ánh xạ nó tới SQL BLOBmà PostgreSQL xử lý với a oid .

Điều này có cố định trong một số phiên bản gần đây của ngủ đông không?

Chà, vấn đề là tôi không biết chính xác vấn đề là gì. Nhưng ít nhất tôi có thể nói rằng không có gì thay đổi kể từ 3.5.0-Beta-2 (đó là nơi một sự thay đổi đã được giới thiệu) trong nhánh 3.5.x.

Nhưng sự hiểu biết của tôi về các vấn đề như HHH-4876 , HHH-4617PostgreQuery và BLOB (được đề cập trong javadoc của PostgreSQLDialect) là bạn phải thiết lập thuộc tính sau

hibernate.jdbc.use_streams_for_binary=false

nếu bạn muốn sử dụng oidtức là byte[]với @Lob(đó là sự hiểu biết của tôi từVARBINARY không phải là điều bạn muốn với Oracle). Bạn đã thử điều này?

Thay vào đó, HHH-4876 đề nghị sử dụng loại không dùng nữaPrimitiveByteArrayBlobType để có được hành vi cũ (trước Hibernate 3.5).

Người giới thiệu

  • Đặc điểm kỹ thuật JPA 2.0
    • Mục 2.8 "Mặc định ánh xạ cho các trường hoặc thuộc tính không liên quan"
    • Mục 11.1.6 "Chú thích cơ bản"
    • Mục 11.1.24 "Chú thích Thùy"

Tài nguyên


OMG, tôi nhận ra câu hỏi này đã thay đổi rất nhiều kể từ khi tôi bắt đầu trả lời. Sẽ đọc tất cả các thay đổi sau đó và cập nhật câu trả lời của tôi sau khi tiêu hóa các thay đổi nếu cần thiết.
Pascal Thivent

Thật tốt khi thấy thông số kỹ thuật, vì vậy ngủ đông là hoàn toàn chính xác để ánh xạ (@Lob + byte []) sang một loại đối tượng lớn được hỗ trợ. Trong Postgresql có 2 (bytea hoặc oid). Tuy nhiên, trong khi hibernate 3.5 ánh xạ thành oid (theo mặc định), nó đọc bằng cách sử dụng JDBC getBytes () mà trình điều khiển PGQuery trả về oid 6 byte thay vì dữ liệu. Cũng lưu ý rằng tác giả blog đã trả lời hữu ích nhất (trên blog của mình) kể từ khi câu hỏi được đặt ra.
Justin

@Justin Tuy nhiên, trong khi hibernate 3.5 ánh xạ thành oid (theo mặc định), nó đọc bằng cách sử dụng JDBC getBytes () mà trình điều khiển PGQuery trả về oid 6 byte thay vì dữ liệu - điều này có xảy ra khi sử dụng hibernate.jdbc.use_streams_for_binary=falsekhông? (sẽ kiểm tra những gì Steve nói bây giờ).
Pascal Thivent

Tôi sẽ thử chỉ định nó trong tệp thuộc tính, tuy nhiên PostgreSQLDialect đã sử dụngInputStreamToInsertBlob () trả về false vì vậy tôi giả sử rằng tôi - vì tôi không đặt rõ ràng thuộc tính này.
Justin

Sau khi đặt thuộc tính này (thành đúng hoặc sai), tôi nhận được một ngoại lệ thời gian chạy: ERROR: cột "chữ ký" thuộc loại bytea nhưng biểu thức là loại oid ". Tôi nên đề cập đến việc tôi đang sử dụng hibernate 3.5.5.Final + PG Trình điều khiển 8.2.
Justin

10

Dưới đây là những gì O'reilly Enterprise JavaBeans, 3.0 nói

JDBC có các loại đặc biệt cho các đối tượng rất lớn này. Kiểu java.sql.Blob đại diện cho dữ liệu nhị phân và java.sql.Clob đại diện cho dữ liệu ký tự.

Dưới đây là mã nguồn PostgreSQLDialect

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

Vậy bạn có thể làm gì

Ghi đè PostgreSQLDialect như sau

public class CustomPostgreSQLDialect extends PostgreSQLDialect {

    public CustomPostgreSQLDialect() {
        super();

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

Bây giờ chỉ cần xác định phương ngữ tùy chỉnh của bạn

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

Và sử dụng chú thích JPA @Lob di động của bạn

@Lob
public byte[] getValueBuffer() {

CẬP NHẬT

Ở đây đã được trích xuất ở đây

Tôi có một ứng dụng chạy trong hibernate 3.3.2 và các ứng dụng hoạt động tốt , với tất cả các trường blob sử dụng oid (byte [] trong java)

...

Di chuyển sang chế độ ngủ đông 3.5 tất cả các trường blob không hoạt động nữa và nhật ký máy chủ hiển thị: ERROR org.hibernate.util.JDBCExceptionReporter - ERROR: cột thuộc loại oid nhưng biểu thức là loại bytea

có thể giải thích ở đây

Thế hệ này không phải là lỗi trong PG JDBC , nhưng thay đổi cách triển khai mặc định của Hibernate ở phiên bản 3.5 . Trong tình huống của tôi, thiết lập thuộc tính tương thích trên kết nối không giúp được gì .

...

Nhiều hơn những gì tôi thấy trong 3.5 - beta 2, và tôi không biết liệu cái này có được sửa hay không là Hibernate - không có chú thích @Type - sẽ tự động tạo cột loại oid, nhưng sẽ cố đọc nó dưới dạng bytea

Thú vị là bởi vì khi anh ta ánh xạ các loại.BOLB dưới dạng bytea (Xem CustomPostgreQueryDialect) Anh ta nhận được

Không thể thực hiện cập nhật hàng loạt JDBC

khi chèn hoặc cập nhật


Giải pháp này có vẻ vinh quang, tôi đang thử nó ngay bây giờ.
Justin

Điều này tạo ra DDL chính xác, nhưng thất bại trong thời gian chạy: Tôi nhận được java.sql.BatchUpdateException khi thử một đối tượng có thuộc tính blob.
Justin

@Justin Hãy thử một kịch bản tương tự bằng cách sử dụng Oracle thay vì PostgreSQL và xem những gì bạn nhận được. BatchUpdateException phải thực hiện với các lỗi xảy ra trong một hoạt động cập nhật hàng loạt.
Arthur Ronald

Trên thực tế, điều tôi thực sự muốn không phải là ánh xạ BLOB thành "bytea" mà thay vào đó là ánh xạ (byte [] + @Lob) kết hợp chú thích vào các loại.VARBINARY!
Justin


7

Tôi đang sử dụng Hibernate 4.2.7.SP1 với Postgres 9.3 và các công việc sau đây cho tôi:

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

vì Oracle không gặp rắc rối với điều đó và đối với Postgres, tôi đang sử dụng phương ngữ tùy chỉnh:

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);
  }
}

lợi thế của giải pháp này tôi xem xét, rằng tôi có thể giữ cho các bình ngủ đông không bị ảnh hưởng.

Để biết thêm các vấn đề tương thích Postgres / Oracle với Hibernate, hãy xem bài đăng trên blog của tôi .


2
Làm việc cho tôi bằng Hibernate 4.3.6 và Postgresql 9.3 với việc mở rộng Postgresql9Dialect. Cảm ơn bạn!
Andrés Oviedo

Hoạt động với Hibernate 5.3.7.Final và Postgres95Dialect. Thx
Bernhard Kern

6

Cuối cùng tôi đã làm việc này. Tuy nhiên, nó mở rộng giải pháp từ A. Garcia, vì vấn đề nằm ở loại hibernate loại MaterializedBlob chỉ ánh xạ Blob> bytea là không đủ, chúng tôi cần một sự thay thế cho MaterializedBlobType hoạt động với hỗ trợ blob bị hỏng. Việc triển khai này chỉ hoạt động với bytea, nhưng có lẽ anh chàng từ vấn đề JIRA muốn OID có thể đóng góp cho việc thực hiện OID.

Đáng buồn thay thế các loại này trong thời gian chạy là một nỗi đau, vì chúng nên là một phần của Phương ngữ. Nếu chỉ có sự tăng cường JIRA này vào 3.6 thì điều đó là có thể.

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";
  }
}

Phần lớn điều này có thể là tĩnh (getBinder () có thực sự cần một thể hiện mới không?), Nhưng tôi không thực sự hiểu nội bộ ngủ đông nên đây chủ yếu là sao chép + dán + sửa đổi.

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);
 }
}

+1 cho nghiên cứu của bạn. Xin chúc mừng. Chỉ cần một lời khuyên: Thích chỉnh sửa câu hỏi / câu trả lời của riêng bạn lên đến 8 lần. Mặt khác, câu hỏi / câu trả lời của bạn sẽ trở thành wiki cộng đồng và bạn sẽ không đạt được danh tiếng và phiếu bầu UP sẽ không được tính toán nữa
Arthur Ronald

Sống và học hỏi Tôi cho rằng, tôi đã có rất nhiều chỉnh sửa, vì tôi đã quên làm một việc này hay việc khác với môi trường thử nghiệm của mình.
Justin

Tương tự ở đây, 1 cho việc nghiên cứu và một giải pháp cho tình hình của bạn.
Pascal Thivent

bất kỳ cơ hội cho giải pháp với phiên bản Hibernate 4.2.x? Nội bộ của Hibernate đã thay đổi một chút (Tôi nhận xét vấn đề được giới thiệu: hibernate.atlassian.net/browse/HHH-5584 ).
Peter Butkovic

2

i đã khắc phục sự cố của tôi bằng cách thêm chú thích của @Lob sẽ tạo byte [] trong orory dưới dạng blob, nhưng chú thích này sẽ tạo trường dưới dạng oid không hoạt động chính xác, Để tạo byte [] được tạo như bytea tôi đã tạo ra khách hàng postgres như dưới đây

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);
  }
 }

Cũng cần ghi đè tham số cho Phương ngữ

spring.jpa.properIES.hibernate.dialect = com.ntg.common.DBCompabilitiesHelper.PostgreQueryDialectCustom

có thể tìm thấy nhiều gợi ý hơn: https://dzone.com/articles/postgres-and-oracle


0

Tôi đã làm cho nó hoạt động bằng cách ghi đè chú thích bằng tệp XML cho Postgres. Chú thích được giữ cho Oracle. Theo tôi, trong trường hợp này, tốt nhất là chúng ta nên ghi đè lên ánh xạ của sự cố này - một số thù địch với ánh xạ xml. Chúng tôi có thể ghi đè lên một / nhiều thực thể với ánh xạ xml. Vì vậy, chúng tôi sẽ sử dụng chú thích cho cơ sở dữ liệu được hỗ trợ chủ yếu của chúng tôi và tệp xml cho cơ sở dữ liệu khác.

Lưu ý: chúng ta chỉ cần ghi đè một lớp duy nhất, vì vậy nó không phải là vấn đề lớn. Đọc thêm từ ví dụ của tôi Ví dụ để ghi đè chú thích bằng XML


0

Trên Postgres @Lob đang phá vỡ byte [] khi nó cố lưu nó dưới dạng oid và đối với String cũng xảy ra vấn đề tương tự. Dưới đây mã đang phá vỡ các postgres đang hoạt động tốt trên orory.

@Lob
private String stringField;

@Lob
private byte[]   someByteStream;

Để khắc phục ở trên trên postgres đã viết bên dưới hibernate.dialect tùy chỉnh

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);
  }
}

Bây giờ cấu hình phương ngữ tùy chỉnh trong chế độ ngủ đông

hibernate.dialect=X.Y.Z.PostgreSQLDialectCustom   

XYZ là tên gói.

Bây giờ nó hoạt động tốt. LƯU Ý- Phiên bản Hibernate của tôi - 5.2.8.Final Postgres phiên bản- 9.6.3


0

Cảm ơn Justin, Pascal đã hướng dẫn tôi đi đúng hướng. Tôi cũng gặp phải vấn đề tương tự với Hibernate 3.5.3. Nghiên cứu và gợi ý của bạn đến đúng lớp đã giúp tôi xác định vấn đề và khắc phục.

Vì lợi ích cho những người vẫn bị mắc kẹt với Hibernate 3.5 và sử dụng kết hợp oid + byte [] + @LoB, sau đây là những gì tôi đã làm để khắc phục sự cố.

  1. Tôi đã tạo một BlobType tùy chỉnh mở rộng MaterializedBlobType và ghi đè tập hợp và phương thức get với quyền truy cập kiểu oid.

    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. Đăng ký CustomBlobType với Hibernate. Sau đây là những gì tôi đã làm để đạt được điều đó.

      hibernateConfiguration= new AnnotationConfiguration();
      Mappings mappings = hibernateConfiguration.createMappings();
      mappings.addTypeDef("materialized_blob", "x.y.z.BlobType", null);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.