大型对象不能在自动提交模式下使用

2022-09-01 05:05:42

我有一个Spring应用程序,它在PostgreSQL数据库上使用Hibernate。我正在尝试将文件存储在数据库的表中。它似乎将行与文件一起存储(我只是在EntityManager上使用持久化方法),但是当从数据库中加载对象时,我得到以下异常:

org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.

为了加载数据,我使用的是 MultipartFile 瞬态属性,并在其 setter 中设置要保留的信息(byte[]、文件名、大小)。我正在保留的实体看起来像这样(我已经省略了其余的 getter/setters):

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

问题是我不想保留任何数据,所以我不明白为什么它应该包含在事务中。当我只从数据库中加载了一些数据时,进行提交是否有任何意义?

谢谢。


答案 1

一个大对象可以存储在多个记录中,这就是为什么你必须使用一个事务。所有记录都是正确的,或者根本没有。

https://www.postgresql.org/docs/current/static/largeobjects.html


答案 2

我没有使用 ,而是针对此问题所做的只是将 PostgreSQL DB 中的此列从类型更新为另一种类型,并为字段添加。@Transactionaloidbytea@Type@Lob

ALTER TABLE person DROP COLUMN image;
ALTER TABLE person ADD COLUMN image bytea;

并改变了

@Lob
private byte[] image;

@Lob
@Type(type = "org.hibernate.type.ImageType")
private byte[] image;

推荐