16

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

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

class MyType {

  // ...

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

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

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

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

4

4 回答 4

8

据此,只有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;
    }
}
于 2009-07-17T11:23:05.840 回答
5

与其使用休眠注释进行均衡,不如尝试将字段从String转换为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);  
} 

为我工作(该字段开始延迟加载,在 Oracle 上)。

于 2012-11-13T09:12:41.677 回答
4

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

使用惰性属性获取

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

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

请参阅使用 Maven 进行休眠的字节码检测

于 2014-02-04T11:55:35.170 回答
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 的初学者,希望对您有所帮助。

于 2018-03-07T18:48:40.390 回答