在休眠状态下延迟加载 Clob

发布于 2024-07-27 23:22:22 字数 607 浏览 4 评论 0原文

人们可以通过谷歌搜索找到很多关于这个问题的信息,但我还没有找到解决这个问题的可行解决方案。

基本上我拥有的是一个特定类的大 CLOB,我想按需加载它。 执行此操作的天真的方法是:

class MyType {

  // ...

  @Basic(fetch=FetchType.LAZY)
  @Lob
  public String getBlob() {
    return blob;
  }
}

但这不起作用,显然是因为我使用的是 oracle 驱动程序,即 Lob 对象不被视为简单的句柄,而是始终被加载。 或者说,我的尝试让我相信了这一点。 有一种解决方案使用特殊的仪器来延迟属性加载,但 Hibernate 文档似乎表明他们对使其正常工作不太感兴趣,所以我宁愿不走这条路。 特别是必须运行额外的编译过程等等。

因此,我设想的下一个解决方案是将这个对象分离为另一种类型并定义一个关联。 不幸的是,虽然文档提供了相互冲突的信息,但对我来说,显然延迟加载不适用于具有共享主键的 OneToOne 关联。 我将关联的一侧设置为 ManyToOne,但我不太确定当存在共享主键时如何执行此操作。

那么有人可以建议解决这个问题的最佳方法吗?

There's a lot one can find about this googling a bit but I haven't quite found a workable solution to this problem.

Basically what I have is a big CLOB on a particular class that I want to have loaded on demand. The naive way to do this would be:

class MyType {

  // ...

  @Basic(fetch=FetchType.LAZY)
  @Lob
  public String getBlob() {
    return blob;
  }
}

That doesn't work though, apparently due to the fact I'm using oracle drivers, i.e. Lob objects aren't treated as simple handles but are always loaded. Or so I've been led to believe from my forays. There is one solution that uses special instrumentation for lazy property loading, but as the Hibernate docs seem to suggest they're less than interested in making that work correctly, so I'd rather not go that route. Especially with having to run an extra compile pass and all.

So the next solution I had envisioned was separating out this object to another type and defining an association. Unfortunately, while the docs give conflicting information, it's apparent to me that lazy loading doesn't work on OneToOne associations with shared primary key. I'd set one side of the association as ManyToOne, but I'm not quite sure how to do this when there's a shared primary key.

So can anybody suggest the best way to go about this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

倒数 2024-08-03 23:22:22

根据this,只有 PostgreSQL 将 Blob 实现为真正的惰性。 所以最好的解决方案是将 blob 移动到另一个表。 必须使用共享主键吗? 你为什么不做这样的事情:

public class MyBlobWrapper {
    @Id
    public Long getId() {
       return id;
    }
    @Lob
    public String getBlob() {
        return blob;
    }
    @OneToOne(fetch=FetchType.LAZY,optional=false) 
    public MyClass getParent() {
        return parent;
    }
}

According to this only PostgreSQL implements Blob as really lazy. So the best solution is to move the blob to another table. Do you have to use a shared primary key? Why don't you do something like this:

public class MyBlobWrapper {
    @Id
    public Long getId() {
       return id;
    }
    @Lob
    public String getBlob() {
        return blob;
    }
    @OneToOne(fetch=FetchType.LAZY,optional=false) 
    public MyClass getParent() {
        return parent;
    }
}
烂人 2024-08-03 23:22:22

您可以尝试将字段从 String 转换为 Clob (或 Blob),而不是使用 Hibernate 注释进行均衡:

@Lob  
@Basic(fetch=FetchType.LAZY)  
@Column(name = "FIELD_COLUMN")  
public Clob getFieldClob() {  
  return fieldClob;  
}  

public void setFieldClob(Clob fieldClob) {  
  this.fieldClob = fieldClob;  
}  

@Transient  
public String getField()  
{  
  if (this.getFieldClob()==null){  
    return null;  
  }  
  try {  
    return MyOwnUtils.readStream(this.getFieldClob().getCharacterStream());  
  } catch (Exception e) {  
    e.printStackTrace();  
  }  

  return null;  
}  

public void setField(String field)  
{  
  this.fieldClob = Hibernate.createClob(field);  
} 

对我有用(在 Oracle 上,字段开始延迟加载)。

Instead of doing equilibristics with hibernate annotations, one may just try converting the field from String into Clob (or Blob):

@Lob  
@Basic(fetch=FetchType.LAZY)  
@Column(name = "FIELD_COLUMN")  
public Clob getFieldClob() {  
  return fieldClob;  
}  

public void setFieldClob(Clob fieldClob) {  
  this.fieldClob = fieldClob;  
}  

@Transient  
public String getField()  
{  
  if (this.getFieldClob()==null){  
    return null;  
  }  
  try {  
    return MyOwnUtils.readStream(this.getFieldClob().getCharacterStream());  
  } catch (Exception e) {  
    e.printStackTrace();  
  }  

  return null;  
}  

public void setField(String field)  
{  
  this.fieldClob = Hibernate.createClob(field);  
} 

Worked for me (the field started to load lazily, on Oracle).

一袭白衣梦中忆 2024-08-03 23:22:22

由于您似乎正在使用 Hibernate,我想知道您的问题是否与以下 Hibernate 功能有关:

使用延迟属性获取

Hibernate3 支持延迟获取各个属性。 这
优化技术也称为获取组。 请注意
这主要是一种营销功能; 优化行读取的意义远不止这些
比列读取的优化更重要。 然而,仅加载
类的某些属性在极端情况下可能有用。 为了
例如,当遗留表有数百列并且数据
模型无法改进。

延迟属性加载需要构建时字节码检测。 如果
你的持久化类没有被增强,Hibernate会忽略lazy
属性设置并返回立即获取。

请参阅使用 Maven 的 Hibernate 字节码检测

Since you appear to be using Hibernate I wonder if your problem is related to the following Hibernate feature:

Using Lazy Properties Fetching

Hibernate3 supports the lazy fetching of individual properties. This
optimization technique is also known as fetch groups. Please note that
this is mostly a marketing feature; optimizing row reads is much more
important than optimization of column reads. However, only loading
some properties of a class could be useful in extreme cases. For
example, when legacy tables have hundreds of columns and the data
model cannot be improved.

Lazy property loading requires buildtime bytecode instrumentation. If
your persistent classes are not enhanced, Hibernate will ignore lazy
property settings and return to immediate fetching.

See Bytecode Instrumentation for Hibernate Using Maven.

初心 2024-08-03 23:22:22

老帖子,但只有一篇对我有帮助,感谢@TadeuszKopec 的回答。

看起来很难用 JPA 延迟加载 blob。 我尝试过 @OneToOne 关联,但它比帮助更复杂。
我只是将字节移动到另一个类,与 MyClass 没有关联(父级。相同的表,相同的 id):

@Entity
@Table(name="MyTable")
public class MyBlobWrapper{

    @Id
    @Column(name = "id") // id of MyTable, same as MyClass
    private Long id;

    @Lob
    private byte[] bytes;   
}

@Entity
@Table(name="MyTable")
public class MyClass{

    @Id
    @Column(name = "id")
    private Long id;
    // other fields  .....
}

只需记住在保存 blob 之前刷新父级:

 em.persist(parent);
 em.flush();
 em.merge(new MyBlobWrapper(parent_id,new byte[1000]));

现在我可以单独加载 pdf:

String query1 = " select PDF from MyBlobWrapper PDF where PDF.id = :id";

我只是 JPA 的初学者,希望有帮助。

Old post, but only one that helped me, thanks to @TadeuszKopec answer.

Looks like it is hard to do lazy loading of blob with JPA. I tried @OneToOne association, but it complicates more than help.
I just moved the bytes to another class, with no association with MyClass (parent. Same table, same id):

@Entity
@Table(name="MyTable")
public class MyBlobWrapper{

    @Id
    @Column(name = "id") // id of MyTable, same as MyClass
    private Long id;

    @Lob
    private byte[] bytes;   
}

@Entity
@Table(name="MyTable")
public class MyClass{

    @Id
    @Column(name = "id")
    private Long id;
    // other fields  .....
}

Just remember to flush parent, before saving the blob:

 em.persist(parent);
 em.flush();
 em.merge(new MyBlobWrapper(parent_id,new byte[1000]));

Now I can load the pdf alone:

String query1 = " select PDF from MyBlobWrapper PDF where PDF.id = :id";

I am just beginner with JPA, hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文