如何通过Hibernate将图像保存到SQLite数据库?

时间:2011-06-20 11:17:15

标签: image hibernate sqlite blob

感谢您的帮助。到目前为止,我已经花了好几个小时。

我一直试图弄清楚如何通过Hibernate在Sqlite数据库中存储图像,但是下面得到例外。正如异常消息所示,我的SQLite JDBC驱动程序不支持setBinaryStream。我试过sqlitejdbc-v056和xerial sqlite-jdbc-3.7.2罐子。

Caused by: java.sql.SQLException: not implemented by SQLite JDBC driver
    at org.sqlite.Unused.unused(Unused.java:29)
    at org.sqlite.Unused.setBinaryStream(Unused.java:60)
    at org.hibernate.type.BlobType.set(BlobType.java:99)

我已经在不同的地方看到过这个问题,并且从其他Q& A区域我发现应该使用setBytes而不是setBinaryStream用于PreparedStatement。然而对我来说,一切都是通过Hibernate发生的,而不是由我直接发表的任何声明。我还没有找到涉及Hibernate的解决方案。

我的映射文件为image列设置type =“blob”。如果我把它设置为某个论坛中提到的“二进制”,我会得到这个例外:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: $Proxy2
    at org.hibernate.type.BinaryType.toInternalFormat(BinaryType.java:38)
    at org.hibernate.type.AbstractBynaryType.deepCopyNotNull(AbstractBynaryType.java:172)

我想要存储的图像将放在与保存实体其余部分的表分开的关联表中。我不知道它是如何成为代理的,因为它是第一次通过session.save()持久化的新对象实例,导致ClassCastException。

我使用一个字节数组来保存我的java对象中的图像数据,使用其他人的代码(在论坛中找到)在BufferedImage和byte []之间进行转换。

所以我认为我的最终问题是“是否有通过Hibernate的解决方案,或者我必须自己使用PreparedStatement并绕过Hibernate?”

我是一个休眠的新手。

表创建语句:

create TABLE images (image_id INTEGER PRIMARY KEY AUTOINCREMENT, image BLOB not null);

Hibernate映射:

<class name="ImageImpl" table="images">
    <id name="id" column="image_id">
        <generator class="identity"/>
    </id>
    <property name="imageBlob" column="image" type="blob"/>
</class>

爪哇:

private byte[] m_imageBytes;

// for use by hibernate
@SuppressWarnings("unused")
protected Blob getImageBlob ()
{ return Hibernate.createBlob(m_imageBytes); }

// for use by hibernate
@SuppressWarnings("unused")
private void setImageBlob (Blob blob)
{ m_imageBytes = toByteArray(blob); }

private byte[] toByteArray (Blob blob)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try
    {
        return toByteArrayImpl(blob, baos);
    }
    catch (SQLException e)
    {
        throw new RuntimeException(e);
    }
    catch (IOException e)
    {
        throw new RuntimeException(e);
    }
    finally
    {
        if (baos != null)
        {
            try
            {
                baos.close();
            }
            catch (IOException ex)
            {}
        }
    }
}

private byte[] toByteArrayImpl (Blob fromBlob, ByteArrayOutputStream baos)
  throws SQLException, IOException
{
   byte[] buf = new byte[4000];
   InputStream is = fromBlob.getBinaryStream();
   try
   {
        for (;;)
        {
            int dataSize = is.read(buf);
            if (dataSize == -1)
                break;
            baos.write(buf, 0, dataSize);
        }
   }
   finally
   {
       if (is != null)
       {
            try
            {
                is.close();
            }
            catch (IOException ex)
            {}
       }
   }
   return baos.toByteArray();
}

1 个答案:

答案 0 :(得分:0)

在此discussion附加了sqlite jdbc驱动程序的补丁,其中包括setBinaryStream的实现。