Вопрос

Есть много чего, что можно найти по этому поводу, немного погуглив, но я не совсем нашел работоспособное решение этой проблемы.

По сути, то, что у меня есть, - это большой СБОЙ в определенном классе, который я хочу загружать по требованию.Наивным способом сделать это было бы:

class MyType {

  // ...

  @Basic(fetch=FetchType.LAZY)
  @Lob
  public String getBlob() {
    return blob;
  }
}

Однако это не работает, по-видимому, из-за того, что я использую драйверы Oracle, т. е.Lob-объекты не обрабатываются как простые дескрипторы, но всегда загружаются.По крайней мере, так мне внушили мои набеги.Существует одно решение, которое использует специальные инструменты для отложенной загрузки свойств, но, поскольку документы Hibernate, похоже, предполагают, что они менее чем заинтересованы в том, чтобы это работало правильно, поэтому я бы предпочел не идти по этому пути.Особенно с учетом необходимости выполнить дополнительный проход компиляции и все такое.

Итак, следующее решение, которое я предполагал, состояло в том, чтобы разделить этот объект на другой тип и определить ассоциацию.К сожалению, хотя документы предоставляют противоречивую информацию, для меня очевидно, что отложенная загрузка не работает при ассоциациях OneToOne с общим первичным ключом.Я бы установил одну сторону ассоциации как ManyToOne, но я не совсем уверен, как это сделать, когда есть общий первичный ключ.

Итак, кто-нибудь может предложить наилучший способ сделать это?

Это было полезно?

Решение

Согласно это только PostgreSQL реализует Blob как действительно ленивый.Поэтому лучшее решение - переместить большой двоичный объект в другую таблицу.Обязательно ли вам использовать общий первичный ключ?Почему бы тебе не сделать что-нибудь подобное этому:

public class MyBlobWrapper {
    @Id
    public Long getId() {
       return id;
    }
    @Lob
    public String getBlob() {
        return blob;
    }
    @OneToOne(fetch=FetchType.LAZY,optional=false) 
    public MyClass getParent() {
        return parent;
    }
}

Другие советы

Вместо того чтобы выполнять эквилибристику с аннотациями гибернации, можно просто попробовать преобразовать поле из String в Clob (или Blob):

@Lob  
@Basic(fetch=FetchType.LAZY)  
@Column(name = "FIELD_COLUMN")  
public Clob getFieldClob() {  
  return fieldClob;  
}  

public void setFieldClob(Clob fieldClob) {  
  this.fieldClob = fieldClob;  
}  

@Transient  
public String getField()  
{  
  if (this.getFieldClob()==null){  
    return null;  
  }  
  try {  
    return MyOwnUtils.readStream(this.getFieldClob().getCharacterStream());  
  } catch (Exception e) {  
    e.printStackTrace();  
  }  

  return null;  
}  

public void setField(String field)  
{  
  this.fieldClob = Hibernate.createClob(field);  
} 

Сработало у меня (поле начало загружаться лениво, в Oracle).

Поскольку вы, похоже, используете гибернацию, мне интересно, связана ли ваша проблема со следующей функцией гибернации:

Использование отложенной выборки свойств

Hibernate3 поддерживает отложенную выборку отдельных свойств.Этот метод оптимизации также известен как группы выборки.Пожалуйста, обратите внимание, что это в основном маркетинговая функция;оптимизация чтения строк намного важнее , чем оптимизация чтения столбцов.Однако загружается только некоторые свойства класса могут быть полезны в крайних случаях.Для например, когда устаревшие таблицы содержат сотни столбцов и данные модель не может быть улучшена.

Отложенная загрузка свойств требуется инструментарий байт-кода во время сборки.Если ваши постоянные классы не улучшены, Hibernate проигнорирует отложенные настройки свойств и вернется к немедленной выборке.

Видишь Инструментарий байт-кода для гибернации с использованием Maven.

Старый пост, но только один, который помог мне, благодаря ответу @TadeuszKopec.

Похоже, что с помощью JPA сложно выполнить отложенную загрузку blob-объекта.Я попробовал ассоциацию @OneToOne, но это больше усложняет, чем помогает.Я просто переместил байты в другой класс, без связи с MyClass (parent.Та же таблица, тот же идентификатор):

@Entity
@Table(name="MyTable")
public class MyBlobWrapper{

    @Id
    @Column(name = "id") // id of MyTable, same as MyClass
    private Long id;

    @Lob
    private byte[] bytes;   
}

@Entity
@Table(name="MyTable")
public class MyClass{

    @Id
    @Column(name = "id")
    private Long id;
    // other fields  .....
}

Просто не забудьте сбросить родительский файл, прежде чем сохранять большой двоичный объект:

 em.persist(parent);
 em.flush();
 em.merge(new MyBlobWrapper(parent_id,new byte[1000]));

Теперь я могу загрузить PDF-файл самостоятельно:

String query1 = " select PDF from MyBlobWrapper PDF where PDF.id = :id";

Я всего лишь новичок в JPA, надеюсь, это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top