【问题标题】:Performance tuning of a Hibernate+Spring+MySQL project operation that stores images uploaded by user存储用户上传图片的Hibernate+Spring+MySQL项目操作性能调优
【发布时间】:2010-05-02 12:03:04
【问题描述】:

我正在开发一个基于 Spring+Hibernate+MySQL 的 Web 项目。我被困在必须将用户上传的图像存储到数据库中的地步。虽然我已经编写了一些目前运行良好的代码,但我相信项目上线时事情会一团糟。

这是我携带图像字节的域类:

@Entity
public class Picture implements java.io.Serializable{
    long id;
    byte[] data;
    ... // getters and setters
}

这是我在提交时保存文件的控制器:

public class PictureUploadFormController extends AbstractBaseFormController{
    ...
    protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception{
         MutlipartFile file; 
         // getting MultipartFile from the command object
         ...
         // beginning hibernate transaction
         ...
         Picture p=new Picture();
         p.setData(file.getBytes());
         pictureDAO.makePersistent(p); // this method simply calls getSession().saveOrUpdate(p)

         // committing hiernate transaction
         ...
    }
    ...
}

显然是一段糟糕的代码。无论如何我可以使用 InputStreamBlob 来保存数据,而不是先将所有字节从用户加载到内存中,然后再将它们推送到数据库中?

我对 hibernate 对 Blob 的支持做了一些研究,并在 Hibernate In Action 书中找到了这一点:

java.sql.Blob 和 java.sql.Clob 是 处理大数据的最有效方法 Java 中的对象。不幸的是,一个 Blob 或 Clob 的实例仅 在 JDBC 事务之前可用 完成。 所以如果你的持久类 定义 java.sql.Clob 的属性或 java.sql.Blob(不是一个好主意 无论如何),您将受到限制 可以使用该类的实例。 在 特别是,您将无法使用 该类的实例为分离的 对象。此外,许多 JDBC 驱动程序没有工作支持 对于 java.sql.Blob 和 java.sql.Clob。 因此,映射更有意义 使用二进制或文本的大型对象 映射类型,假设检索 将整个大对象放入内存 不是性能杀手。

请注意 可以找到最新的设计模式 和大对象使用技巧 Hibernate 网站,有技巧 特定平台。

现在显然无法使用 Blob,因为它无论如何都不是一个好主意,还有什么可以用来提高性能的?我在 Hibernate 网站上找不到任何最新的设计模式或任何有用的信息。因此,我们将不胜感激来自 stackoverflowers 的任何帮助/建议。

谢谢

【问题讨论】:

    标签: java mysql hibernate spring blob


    【解决方案1】:

    这本书的修订版(Java Persistence with Hibernate)说:

    表 5.3 列出了用于处理二进制数据和大值的 Hibernate 类型。注意 仅支持 binary 作为标识符属性的类型。

    Mapping type   Java type   Standard SQL built-in type
    binary         byte[]               VARBINARY
    text           java.lang.String     CLOB
    clob           java.sql.Clob        CLOB
    blob           java.sql.Blob        BLOB
    serializable   Any Java class that  VARBINARY
                   implements
                   java.io.Serializable
    

    如果持久 Java 类中的属性是 byte[] 类型,Hibernate 可以映射 它到具有二进制映射类型的VARBINARY 列。 (注意,真正的 SQL 类型取决于方言;例如,在 PostgreSQL 中,SQL 类型是 BYTEA, 在 Oracle 中它是 RAW。)如果持久 Java 类中的属性是类型 java.lang.String,Hibernate 可以将它映射到一个 SQL CLOB 列,带有文本 映射类型。

    请注意,在这两种情况下,Hibernate 都会立即初始化属性值, 当保存属性变量的实体实例被加载时。这很不方便 当您必须处理可能较大的值时。

    一种解决方案是按需通过拦截字段访问进行延迟加载。 但是,这种方法需要对您的持久性进行字节码检测 用于注入额外代码的类。我们将讨论通过字节码进行延迟加载 第 13 章第 13.1.6 节“延迟加载”中的检测和拦截 拦截。”

    第二种解决方案是在您的 Java 类中使用不同类型的属性。 JDBC 支持 定位器对象 (LOB) 直接。1 如果您的 Java 属性是类型 java.sql.Clob 或 java.sql.Blob,你可以用 clob 或 blob 映射来映射它 类型以在没有字节码检测的情况下延迟加载大值。什么时候 加载了属性的所有者,属性值是一个定位器对象——实际上, 指向尚未实现的实际值的指针。一旦您访问 属性,价值被物化。这种按需加载仅在 数据库事务已打开,因此您需要访问此类类型的任何属性 当拥有实体实例处于持久和事务状态时,而不是 分离状态。您的域模型现在也绑定到 JDBC,因为 需要导入 java.sql 包。虽然领域模型类是 在独立的单元测试中可执行,没有数据库就无法访问 LOB 属性 连接。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2022-12-10
      • 2018-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多