懒惰地在冬眠中加载一个clob

问题描述 投票:15回答:4

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

基本上我所拥有的是一个特定类的大型CLOB,我希望按需加载它。这种天真的方式是:

class MyType {

  // ...

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

这虽然不起作用,显然是因为我使用的是oracle驱动程序,即Lob对象不被视为简单的句柄,但总是被加载。或者我已经被引导相信我的想法。有一种解决方案使用特殊的工具来进行延迟属性加载,但是由于Hibernate文档似乎表明他们对使这项工作正确无益,所以我宁愿不去那条路。特别是必须运行额外的编译通道和所有。

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

所以有人能提出最好的解决方法吗?

java hibernate jpa clob lob
4个回答
5
投票

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;
    }
}

5
投票

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

@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上)。


3
投票

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

Using Lazy Properties Fetching

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

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

Bytecode Instrumentation for Hibernate Using Maven


1
投票

感谢@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的初学者,希望有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.