在Hibernate中将Java字节[]映射到MySQL二进制文件(64)
我在Hibernate中将字节数组映射到MySQL数据库时遇到了一些问题,我想知道是否遗漏了一些明显的内容。我的班级大致如下:在Hibernate中将Java字节[]映射到MySQL二进制文件(64),mysql,hibernate,hbm2ddl,hbm,Mysql,Hibernate,Hbm2ddl,Hbm,我在Hibernate中将字节数组映射到MySQL数据库时遇到了一些问题,我想知道是否遗漏了一些明显的内容。我的班级大致如下: public class Foo { private byte[] bar; // Getter and setter for 'bar' } <property name="bar"> <column name="bar" sql-type="binary" /> </property> 该表在MySQL
public class Foo {
private byte[] bar;
// Getter and setter for 'bar'
}
<property name="bar">
<column name="bar" sql-type="binary" />
</property>
该表在MySQL 5.5中定义如下:
CREATE TABLE foo (
bar BINARY(64) NOT NULL)
Hibernate 3.6.2映射与此类似:
<hibernate-mapping>
<class name="example.Foo" table="foo">
<property name="bar" column="bar" type="binary" />
</class>
</hibernate-mapping>
如果在映射中使用type=“binary”不会导致Hibernate期望列的类型为binary(而不是tinyblob),我不知道会是什么。我花了一些时间在谷歌上搜索,但找不到确切的错误。类似错误的解决方案是
此设置是否有任何突出之处会导致此不匹配?如果我指定type=“binary”而不是“blob”,为什么Hibernate期望一个blob而不是binary?我们最终解决了一个类似的问题,那就是编写我们自己的自定义用户类型 用户类型相对容易实现。只需创建一个实现org.hibernate.usertype.usertype的类并实现@override方法 在hibernate定义中,使用用户类型非常简单:
<property name="data" type="com.yourpackage.hibernate.CustomBinaryStreamUserType" column="binary_data" />
简单地说,它将执行这个类来读取和写入数据库中的数据。具体地说,使用了nullSafeGet和nullSafeSet方法
在我们的例子中,我们使用它来压缩二进制数据,然后将其写入数据库,并在读取时解压缩。这隐藏了这样一个事实,即使用此数据对应用程序压缩数据。我认为问题在于
type=“binary”
该类型是hibernate泛型类型。它不会直接映射到特定于DB引擎的类型。它们会根据您使用的驱动程序转换为不同的SQL类型。显然,MySQL驱动程序将hibernate类型“binary”映射到tinyblob
hibernate类型的完整列表可用
你有两个选择。您可以更改CREATE TABLE脚本以使用tinyblob数据类型存储该列。这样,您的hibernate验证就不会失败,您的应用程序也会正常工作。这将是建议的解决办法
仅当必须在数据库中使用二进制数据类型时,才应使用第二个选项。您可以做的是在hibernate映射中指定sql类型,以便强制hibernate使用所需的类型。映射如下所示:
public class Foo {
private byte[] bar;
// Getter and setter for 'bar'
}
<property name="bar">
<column name="bar" sql-type="binary" />
</property>
主要的缺点是失去了DB引擎的独立性,这就是为什么大多数人首先使用hibernate。这段代码只适用于具有二进制数据类型的DB引擎。我认为在hibernate中映射二进制列有一个简单的解决方案 “二进制”列可以很容易地映射到hibernate实体类中的“java.util.UUID” 例如,列定义如下所示
`tokenValue` BINARY(16) NOT NULL
Hibernate实体将有以下代码来支持二进制列
private UUID tokenValue;
@Column(columnDefinition = "BINARY(16)", length = 16)
public UUID getTokenValue() {
return this.tokenValue;
}
public void setTokenValue(UUID sessionTokenValue) {
this.tokenValue = tokenValue;
}
二进制类型在Java/Hibernate中让我沮丧不已。通常,我解决这个问题的方法是在Java端对二进制数据进行Base64编码,然后将其作为
文本
字段存储在数据库中。然后,实体中的属性可以是String
,并且一切工作都更加顺利。是的,字节数组在Hibernate中似乎很麻烦。映射显式地告诉Hibernate将二进制作为类型,但它却在寻找不同类型的blob,这不是一个bug吗?真令人沮丧!这并不是明确告诉Hibernate使用二进制文件。property元素的type属性不用于指定SQL数据类型。我在下面的回答中解释了这一点。我无法评论Hibernate在设置为使用二进制数据类型(正确)时的行为,我还没有尝试过。由于MySQL的二进制类型似乎被Hibernate“孤立”,解决方法似乎是映射它们的唯一方法,我将此发布到Hibernate论坛。我有点希望这被认为是一个bug并在将来得到修复。你是对的-type=“binary”肯定是问题所在。我只是(错误地)假设,既然存在blob Hibernate类型和二进制Hibernate类型,“blob”Hibernate类型将对应于各种MySQL blob类型,而二进制将对应于二进制。不幸的是,似乎没有任何与MySQL二进制文件对应的Hibernate类型,这似乎是一个相当大的疏忽。UserType很容易编写,当然可以工作,但它似乎并不比问题中的选项2更中立,即使用嵌套的sql type属性声明。不同之处在于,使用“选项2”是一种单行解决方案,不会向项目引入更多代码(bug的机会)。尽管我会说,在您的gzip数据示例中,用户类型似乎是它的最佳位置。我认为这很聪明。指定列的SQL定义是一个已经讨论过的选项(包括在问题中)