Как написать java.sql.Blob в сущность JPA?

У меня есть объект JPA с java.sql.Blob:

@Entity
public class LargeData {

  @Lob
  private java.sql.Blob data;

  //getters/setters
}

Как создать экземпляр этой сущности? Я хочу установить Blob методом setData(), но как получить Blob из JPA? java.sql.Blob - это только интерфейс, для разных баз данных существуют разные реализации, поэтому я предполагаю, что JPA должен дать мне правильную реализацию. Как его получить?


person amorfis    schedule 17.02.2011    source источник


Ответы (2)


Используйте массив байтов:

@Lob
@Column(length=100000)
private byte[] data;

Если вы хотите использовать потоки, создайте большой двоичный объект с помощью Hibernate.createBlob(..)

person Bozho    schedule 17.02.2011
comment
Дополнительная информация к принятому ответу. Подтверждено личным опытом в 2016 году. stackoverflow.com/a/16599953/102658 определить длину столбца › полей String (это игнорируется для других типов) - person Rope; 25.08.2016
comment
Это использует для меня каплю, а не каплю. - person Fund Monica's Lawsuit; 12.10.2018
comment
Я не указываю атрибут length. Я также использую java nio для чтения из файла: myEntity.data = Files.readAllBytes(myPath). - person Julien Kronegg; 27.12.2018

использовать файловый поток. Однако это может иметь различные сложности, в зависимости от вашей базы данных, драйвера и реализации JPA. Я построил универсальное решение, которое было медленным и не работало с большими файлами, затем нашел решение для Hibernate, которое работало с Oracle 11.2.0.4.

Я использую Spring Data/JPA, но проблема, похоже, связана с Hibernate, а не с Spring.

Спящий режим:

private void testLoadFile() throws SQLException, IOException {


  File f = new File("//C:/tmp/6mb_file.wmv");
  BufferedInputStream fstream = new BufferedInputStream(new FileInputStream(f));

  Session session = entityManager.unwrap(Session.class);
  Blob blob = Hibernate.getLobCreator(session).createBlob(fstream, f.length());

  FileBLOBEntity file = new FileBLOBEntity();

  file.setName("//C:/tmp/6mb_file.wmv");
  file.setTheData(blob);
  blobRepository.saveAndFlush(file);
}

Общий Spring/JPA:

private void testLoadFile() throws SQLException, IOException {

  File f = new File("//C:/tmp/6mb_file.wmv");
  BufferedInputStream fstream = new BufferedInputStream(new FileInputStream(f));

  Blob blob = connection.getConnection().createBlob();
  BufferedOutputStream bstream = new  BufferedOutputStream(blob.setBinaryStream(1));
  // stream copy runs a high-speed upload across the network
  StreamUtils.copy(fstream, bstream);

  FileBLOBEntity file = new FileBLOBEntity();

  file.setName("//C:/tmp/6mb_file.wmv");
  file.setTheData(blob);
  // save runs a low-speed download across the network.  this is where
  // Spring does the SQL insert.  For a large file, I get an OutOfMemory exception here.
  blobRepository.saveAndFlush(file);
}

и для поиска:

public void unloadFile() throws SQLException, IOException {

  File f = new File("//C:/tmp/6mb_file.wmv" + "_fromDb");

  FileOutputStream fstream = new FileOutputStream(f);

  FileBLOBEntity file = blobRepository.findByName("//C:/tmp/6mb_file.wmv");
  Blob data = file.getTheData();

  InputStream bstream = data.getBinaryStream();
  StreamUtils.copy(bstream, fstream);

}
person Phil Horder    schedule 26.06.2015
comment
работает, но специфичен для Hibernate, если вы используете EclipseLink, он сломается - person wutzebaer; 21.01.2020
comment
... о чем я говорил в начале поста. Я не люблю конкретизировать реализацию, но это было единственное найденное мной решение, которое было одновременно и стабильным, и достаточно быстрым. - person Phil Horder; 22.01.2020