使用spring-data-jpa并尝试从表中获取数据,该表中约有十二列用于查询中以查找特定行,然后是Clob类型的有效负载列,其中包含已编组的实际数据放入要返回的Java对象。
实体对象大概是
@Entity
@Table(name = "Person")
public class Person {
@Column(name="PERSON_ID", length=45) @Id private String personId;
@Column(name="NAME", length=45) private String name;
@Column(name="ADDRESS", length=45) private String address;
@Column(name="PAYLOAD") @Lob private String payload;
//Bunch of other stuff
}
(这种方法是否明智是另一个讨论的主题)
Clob列会导致大型查询的性能下降...
为了稍微改进一下,我创建了一个单独的实体对象...没有有效载荷...
@Entity
@Table(name = "Person")
public class NotQuiteAWholePerson {
@Column(name="PERSON_ID", length=45) @Id private String personId;
@Column(name="NAME", length=45) private String name;
@Column(name="ADDRESS", length=45) private String address;
//Bunch of other stuff
}
这使我得到一个NotQuiteAPerson页面...然后,我通过personIds查询完整的人对象页面。
希望是,在原始查询中不使用有效负载(可以过滤大量支持表上的数据)时,我只在获取要查看的对象的当前页面时才关心有效负载...一块小得多。
所以我现在想将NotQuiteAWholePerson的原始返回页面的内容映射到我的人员列表,同时保持所有分页信息不变,但是map方法只采用了一个Converter,它将迭代NotQuiteAWholePerson对象...不太适合我想要做的事情。
是否有明智的方法来实现这一目标?
@itsallas的其他说明,说明为什么现有的map()无法满足要求。
PageImpl :: map具有
@Override
public <S> Page<S> map(Converter<? super T, ? extends S> converter) {
return new PageImpl<S>(getConvertedContent(converter), pageable, total);
}
Chunk :: getConvertedContent具有
protected <S> List<S> getConvertedContent(Converter<? super T, ? extends S> converter) {
Assert.notNull(converter, "Converter must not be null!");
List<S> result = new ArrayList<S>(content.size());
for (T element : this) {
result.add(converter.convert(element));
}
return result;
}
因此,原始目录列表通过...进行迭代,并应用提供的convert方法,以构建新的目录列表,以将其插入现有的Pageable中。
但是,我不能将NotQuiteAWholePerson单独转换为Person,因为我不能简单地构造有效负载...好吧,如果我通过转换中的ID通过每个ID为每个Person调用了DB,则可以...但是可以单独调用从性能角度来看并不理想...
在获取我的NotQuiteAWholePerson页面后,我正在一次呼叫中查询ID的整个人员列表...现在,我正在寻找一种替代整个内容列表的方法...就像现有的map()一样,只是简单地替换。
这个特殊的用例也将有助于将json的有效负载更合适地持久存储在像Mongo这样的NoSql数据存储中...而不是sql数据存储clob ...
希望可以更好地阐明这一点。
答案 0 :(得分:2)
您可以完全避免使用Spring Data JPA功能的问题。
最明智的方法是使用Spring Data JPA projections,该文档具有广泛的文档。
例如,您首先需要确保对属性的延迟获取,这可以通过在属性本身上添加注释来实现。
即:
@Basic(fetch = FetchType.LAZY) @Column(name="PAYLOAD") @Lob private String payload;
或通过neatly supported at repository-level的“获取/加载图”。
您需要以一种或另一种方式进行定义,因为从文档中逐字逐句地得出结论:
查询执行引擎在运行时为返回的每个元素创建该接口的代理实例,并将对公开方法的调用转发给目标对象。
然后您可以像这样定义投影:
interface NotQuiteAWholePerson {
String getPersonId();
String getName();
String getAddress();
//Bunch of other stuff
}
并将查询方法添加到您的存储库中:
interface PersonRepository extends Repository<Person, String> {
Page<NotQuiteAWholePerson> findAll(Pageable pageable);
// or its dynamic equivalent
<T> Page<T> findAll(Pageable pageable, Class<T>);
}
鉴于相同的可分页,一页投影将指向同一会话中的相同实体。
如果由于某种原因不能使用投影(即,如果您使用JPA <2.1或在投影之前使用Spring Data JPA版本),则可以使用所需的列和关系定义一个显式的JPQL查询,或者保留2实体设置。然后,您可以手动或(最好)使用所选的对象映射框架将Person
和NotQuiteAWholePerson
映射到PersonDTO
类。
NB。 :有多种使用和设置懒惰/渴望关系的方法。 This covers more in detail。