java 在休眠状态下懒惰地加载一个clob

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1142505/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 15:20:28  来源:igfitidea点击:

Lazily loading a clob in hibernate

javahibernatejpacloblob

提问by wds

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:

基本上,我拥有的是我想要按需加载的特定类上的一个大 CLOB。这样做的天真方法是:

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.

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

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.

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

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

那么任何人都可以建议最好的方法来解决这个问题吗?

采纳答案by Tadeusz Kopec

According to thisonly 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:

根据这个唯一的PostgreSQL实现了斑点为真懒。所以最好的解决方案是将 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;
    }
}

回答by John Donn

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

与其使用 hibernate 注释进行均衡,不如尝试将字段从Stringinto Clob(或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).

对我来说有效(该字段开始在 Oracle 上延迟加载)。

回答by Edwin Dalorzo

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

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

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.

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

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

See Bytecode Instrumentation for Hibernate Using Maven.

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

回答by Marco linux

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

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

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):

看起来很难用 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  .....
}

Just remember to flush parent, before saving the blob:

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

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

Now I can load the pdf alone:

现在我可以单独加载pdf:

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

I am just beginner with JPA, hope that helps.

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