Лениво загружая саб в спящем режиме - PullRequest
15 голосов
/ 17 июля 2009

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

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

class MyType {

  // ...

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

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

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

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

Ответы [ 4 ]

5 голосов
/ 13 ноября 2012

Вместо того, чтобы делать эквилибристику со спящими аннотациями, можно просто попытаться преобразовать поле из 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).

5 голосов
/ 17 июля 2009

Согласно , только 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;
    }
}
4 голосов
/ 04 февраля 2014

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

Использование Lazy Properties Fetching

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

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

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

1 голос
/ 07 марта 2018

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

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

@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  .....
}

Просто не забудьте очистить родительский элемент перед сохранением BLOB-объекта:

 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, надеюсь, это поможет.

...