使用Hibernate将字节数组存储到MySQL数据库中

3

我正在尝试保存一个带有字节数组字段的实体。我在MySQL数据库上使用Hibernate和JPA。 这是字段定义,对于嵌入式H2数据库工作正常:

@Entity(name = "blob")
public class Blob {
    ...
    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(name = "blobImg", nullable = false)
    private byte[] blobImg;
}

现在,使用MySQL数据库时,每次执行blobRepository.save()时都会抛出异常。实际上,在Hibernate尝试自动创建Blob实体表时可能会抛出该异常。该异常如下:
o.h.engine.jdbc.spi.SqlExceptionHelper : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'blob (blobCols, blobImg, blobRows, channel, idBlobPersistence) values (50, _bina' at line 1
我已尝试使用网络上找到的多种方法更改字段定义:
方法1:
@Column(name = "blobImg", nullable = false, columnDefinition = "BINARY(256)", length = 256)
private byte[] blobImg;

方法2:

@Lob
@Column(name="blobImg", columnDefinition="bytea")
private byte[] blobImg;

方案三:
在blob.hbm.xml文件中定义hibernate映射,并从entityManagerFactory bean引用它:

<?xml version='1.0' encoding='UTF-8'?>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="mappingResources">  
        <list>  
            <value>blob.hbm.xml</value>  
        </list>  
    </property>
</bean>

blob.hbm.xml映射:

<hibernate-mapping>
    <class name="guiatv.persistence.domain.Blob" table="blob">
        <property name="blobImgProperty">
            <column name="blobImg" sql-type="binary"></column>
        </property>
    </class>
</hibernate-mapping>

方法四: 将blob.hbm.xml的映射更改为以下内容:

<?xml version='1.0' encoding='UTF-8'?>
<hibernate-mapping>
    <class name="guiatv.persistence.domain.Blob" table="blob">
        <property name="blobImg" type="binary">
            <column name="blobImg" />
        </property>
    </class>
</hibernate-mapping>

所有的它们都抛出了相同的异常。

我该如何解决呢? 谢谢!

3个回答

4
如果你想将你的byte[]转换为sql类型的Blob,你可以按照以下步骤进行操作:
@Lob(type = LobType.BLOB)

或者
@Type(type = "org.hibernate.type.BlobType")
@Lob

希望能对您有所帮助。

您无需指定LOB的类型,它会从字段的类型中推断。对于字节数组,JPA会自动认为它是BLOB。对于字符串,它会认为是CLOB。 - OndroMih
1
@Emusc 直接在 Javadoc 中写明了 @Lob:https://docs.oracle.com/javaee/7/api/javax/persistence/Lob.html -“Lob 类型是从持久字段或属性的类型推断出来的,除了字符串和字符类型以外,默认为 Blob。” - OndroMih

4

好的,

我尝试了你的建议@Ernusc。第一项:

@Lob(type = LobType.BLOB)
private byte[] blobImg;

我这里编译不通过。可能是因为我的Hibernate版本与你的不同。 关于第二个选项:

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

它编译通过,但在运行时失败。它显示了以下错误:
2015-09-14 23:21:01.324  WARN 7436 --- [bTaskExecutor-3] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1064, SQLState: 42000
2015-09-14 23:21:01.324 ERROR 7436 --- [bTaskExecutor-3] o.h.engine.jdbc.spi.SqlExceptionHelper   : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'blob blob0_ where blob0_.idBlobPersistence=326' at line 1
2015-09-14 23:21:01.337  INFO 7436 --- [bTaskExecutor-3] o.h.e.internal.DefaultLoadEventListener  : HHH000327: Error performing load command : org.hibernate.exception.SQLGrammarException: could not extract ResultSet   

此外,当我试图跟踪该代码时,发现实际上抛出了以下异常:
java.lang.ClassCastException: [B cannot be cast to java.sql.Blob

后来我意识到第一个错误信息实际上是由于我愚蠢地将我的实体命名为“blob”,这在Hibernate中可能是保留关键字。因此,我从以下实体声明进行了更改:

@Entity(name = "blob")
public class Blob {
   ...
}

to:

@Entity(name = "blobframe")
public class Blob {
   ...
}

那么,你的第二个建议就是只抛出ClassCastException异常。 然而,我之前尝试过的一些方法现在确实可行。例如:

@Column(name = "blobImg", nullable = false, columnDefinition = "BINARY(256)", length = 256)
private byte[] blobImg;

更新: 这种方法对我来说不起作用。在创建blobframe表时,它失败了,出现了以下字段定义(尽管我不知道原因):

@Lob
@Column(name="blobImg", columnDefinition="bytea")
private byte[] blobImg;

感谢Ernusc的快速回复。

这种方法的可移植性如何?你可以在Postgres上运行它,但不能在MySQL上运行。 - Alexey Usharovski

0
@Lob
@Column(name="image_column", columnDefinition="BLOB")
private byte[] image;

您可以将columnDefinition简单设置为BLOB类型。这适用于MySQL,并将生成blob类型的列。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接