Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Hibernate中将Java字节[]映射到MySQL二进制文件(64)_Mysql_Hibernate_Hbm2ddl_Hbm - Fatal编程技术网

在Hibernate中将Java字节[]映射到MySQL二进制文件(64)

在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

我在Hibernate中将字节数组映射到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),我不知道会是什么。我花了一些时间在谷歌上搜索,但找不到确切的错误。类似错误的解决方案是

  • 在屏幕上指定“长度”。这改变了Hibernate所期望的类型,但它总是各种各样的blob,而不是它所找到的“二进制”类型
  • 不要在property元素上声明“type”,而是嵌套一个column元素并给它一个sql type属性。这是可行的,但这也会使绑定特定于MySQL,因此如果可能的话,我希望避免使用它

  • 此设置是否有任何突出之处会导致此不匹配?如果我指定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定义是一个已经讨论过的选项(包括在问题中)