使用Hibernate延迟获取单列(类属性)

我有一张我正在使用的旧桌子,看起来像这样:

+------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------+--------------+------+-----+---------+-------+ | BINARY_DATA_ID | varchar(255) | NO | PRI | | | | BINARY_DATA | longblob | YES | | NULL | | | BINARY_DATA_NAME | varchar(255) | YES | | NULL | | +------------------+--------------+------+-----+---------+-------+ 

这个问题的主要问题是BinaryData Java类加载了BINARY_DATA列,即使我只需要BINARY_DATA_NAME 。 我知道构建这个的最好方法是从元数据中分割数据(比如文件名),以便它们存在于不同的表中。 从那里,使数据延迟加载是微不足道的。 这应该是首先应该做的。

不幸的是,由于组织方面的限制,我可能无法完成上述任务。 作为一种解决方法,是否可以使用一些注释使该列延迟加载而不是将事物拆分为单独的表? 我修改了BinaryData类,使它有一个内部静态BinaryDataData类,它是@Embedded ,属性是@Basic(fetch=FetchType.LAZY)

 @Entity @Table @Proxy(lazy=false) @Inheritance(strategy=InheritanceType.JOINED) public class BinaryData implements Serializable, Persistable, Cloneable { private static final long serialVersionUID = /** blah */; @Id @Column @GeneratedValue(generator="uuid") @GenericGenerator(name="uuid", strategy="uuid") private String id; @Column private String binaryDataName; @Embedded @Basic(fetch = FetchType.LAZY) private BinaryDataData binaryData; @Transient private String cacheId; /** * Hibernate constructor */ public BinaryData() { /* Creates a new instance of Attachment. */} public BinaryData(byte[] binaryData, String binaryDataName) { this.binaryData = new BinaryDataData(ArrayUtils.clone(binaryData)); this.binaryDataName = binaryDataName; } /** * Returns the BinaryData byte stream. * * @return binaryData byte stream */ @Embedded @Basic(fetch = FetchType.LAZY) public byte[] getBinaryData() { if (this.binaryData == null) { return new byte[0]; } return binaryData.getActualData(); } @Embeddable public static class BinaryDataData implements Serializable { @Column(length=32*1024*1024, columnDefinition="longblob", name="BINARY_DATA") @Lob private byte[] actualData; public BinaryDataData() { } public BinaryDataData(byte[] data) { this.actualData = data; } public byte[] getActualData() { if (this.actualData == null) { return new byte[0]; } return this.actualData; } public void setBinaryData(byte[] newData) { this.actualData = newData; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof BinaryDataData)) { return false; } final BinaryDataData other = (BinaryDataData) obj; if (!Arrays.equals(actualData, other.actualData)) { return false; } return true; } } /** onwards... */ 

不幸的是,这不起作用。 即使没有请求二进制数据,我看到的SQL仍会显示对象的完整提取:

 select ideaattach0_.BINARY_DATA_ID as BINARY1_9_, ideaattach0_1_.BINARY_DATA as BINARY2_9_, ideaattach0_1_.BINARY_DATA_NAME as BINARY3_9_, ideaattach0_.IDEA_BUCKET_ID as IDEA2_136_ from IDEA_ATTACHMENT ideaattach0_ inner join BINARY_DATA ideaattach0_1_ on ideaattach0_.BINARY_DATA_ID=ideaattach0_1_.BINARY_DATA_ID where ideaattach0_.BINARY_DATA_ID=? 

有任何想法吗? 谢谢。

来自Hibernate,第19章。提高性能 :

延迟属性获取:访问实例变量时获取属性或单值关联。 这种方法需要构建时字节码检测 ,并且很少需要。

对于maven项目,需要在pom.xml中添加以下插件依赖项:

  org.hibernate.orm.tooling hibernate-enhance-maven-plugin ${hibernate.version}    true true   enhance     

我在我的项目中检查了它并且它有效,实体的例子:

 @Entity(name = "processing_record") public class ProcessingRecord { /** * Why uuid: https://www.clever-cloud.com/blog/engineering/2015/05/20/why-auto-increment-is-a-terrible-idea/ */ @Id @Column(name = "record_id") @org.hibernate.annotations.Type(type = "pg-uuid") private UUID id; ... /** * Processing result. */ @Column(name = "result") @Basic(fetch = FetchType.LAZY) private String result; ... 

有关详细信息,请查看以下文章: LINK

我知道这个查询的日期,但是,我也会尝试使用映射为列子集的投影值类,并将该投影与指定的命名查询一起使用,该查询实例化该投影值对象,而不是这里引用的基础对象。

我正在研究一种使用这种方法的解决方案,所以我目前没有完整的例子。 但是,基本思想是您将创建一个JPA查询,该查询使用“select NEW Projection_Object_Target”语法,其中的字段在“Projection_Object_Target”的构造函数中直接引用。

IE使用构造函数表达式,如下所示:

 SELECT NEW fully.qualified.package.name.ProjectionObject(baseObject.column_target_0,baseObject.column_target_1,...,baseObject.column_target_n) FROM BaseObjectMappedInDBTable AS baseObject 

通用示例用例:

 String queryStr = "SELECT NEW fully.qualified.package.name.ProjectionObject(baseObject.column_target_0) " + "FROM BaseObjectMappedInTable AS baseObject"; TypedQuery query = em.createQuery(queryStr, ProjectionObject.class); List results = query.getResultList();