Большие объекты не могут использоваться в режиме автоматической фиксации
у меня есть приложение Spring, которое использует Hibernate в базе данных PostgreSQL. Я пытаюсь хранить файлы в таблице базы данных. Кажется, он хранит строку с файлом (я просто использую метод persist в EntityManager), но когда объект загружается из базы данных, я получаю следующее исключение:
org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
для загрузки данных я использую многопартийный переходный атрибут, и в его сеттере я устанавливаю информацию, которую хочу сохранить (байт [], имя файла, размер). Сущность Я настаиваю, выглядит как этот (я ommitted остальные геттеры / сеттеры):
@Entity
@Table(name="myobjects")
public class MyClass {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequence")
@SequenceGenerator(name="sequence", sequenceName="myobjects_pk_seq", allocationSize=1)
@Column(name="id")
private Integer id;
@Lob
private String description;
@Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
@Transient
private MultipartFile multipartFile;
@Lob
@Basic(fetch=FetchType.LAZY, optional=true)
byte[] file;
String fileName;
String fileContentType;
Integer fileSize;
public void setMultipartFile(MultipartFile multipartFile) {
this.multipartFile = multipartFile;
try {
this.file = this.multipartFile.getBytes();
this.fileName = this.multipartFile.getOriginalFilename();
this.fileContentType = this.multipartFile.getContentType();
this.fileSize = ((Long) this.multipartFile.getSize()).intValue();
} catch (IOException e) {
logger.error(e.getStackTrace());
}
}
}
Я вижу, что когда он сохраняется, у меня есть данные в строке, но когда я вызываю этот метод, он терпит неудачу:
public List<MyClass> findByDescription(String text) {
Query query = getEntityManager().createQuery("from MyClass WHERE UPPER(description) like :query ORDER BY creationDate DESC");
query.setParameter("query", "%" + text.toUpperCase() + "%");
return query.getResultList();
}
этот метод не только тогда, когда результат имеет объекты с файлами. Я пытался проявить настойчивость.в XML
<property name="hibernate.connection.autocommit" value="false" />
но это не решит проблему.
В общем, приложение работает хорошо, оно только фиксирует данные, когда сделка завершена и он выполняет откат, если что-то не удается, поэтому я не понимаю, почему это происходит.
есть идеи?
спасибо.
обновление
глядя на ссылку, данную Shekhar, предлагается включить вызов в транзакцию, поэтому я установил вызов службы внутри транзакции, и он работает (я добавил аннотацию @Transactional).
@Transactional
public List<myClass> find(String text) {
return myClassDAO.findByDescription(text);
}
проблема в том, что я не хочу, чтобы сохранить любые данные поэтому я не понимаю, почему это должно быть включено в транзакцию. Имеет ли смысл совершать фиксацию, когда я только загрузил некоторые данные из базы данных?
спасибо.
3 ответов
большой объект может храниться в нескольких записях, поэтому вы должны использовать транзакцию. Все записи верны или вообще ничего.
https://www.postgresql.org/docs/current/static/largeobjects.html
если можно, создайте промежуточную сущность между MyClass и свойством file, например. Что-то вроде:
@Entity
@Table(name="myobjects")
public class MyClass {
@OneToOne(cascade = ALL, fetch = LAZY)
private File file;
}
@Entity
@Table(name="file")
public class File {
@Lob
byte[] file;
}
вы не можете использовать @Lob и тип выборки Lazy. Это не работает. У вас должен быть средний класс.
Если вам не нужно хранить файлы размером более 1 ГБ, я предлагаю вам использовать bytea в качестве типа данных вместо большого объекта.
bytea-это в основном то, что BLOB находится в других базах данных (например, Oracle), и его обработка намного более совместима с JDBC.