繁体   English   中英

如何在 DB session 之外序列化延迟加载的 Hibernate collections(如 PersistentSet)

[英]How to serialize lazy loaded Hibernate collections (like PersistentSet) outside a DB session

我正在开发一个 Spring MVC 门面来访问许多服务。 没有实施 DTO,由于规模庞大,目前还不能这样做。

序列化由 Jackson 直接完成,作为对服务中方法的事务调用的结果返回给控制器的实体,这些方法通过 ORM(休眠)从 DB 中获取实体。

问题来自具有来自一对多或多对多关系的集合属性(例如Set s)的实体,Hibernate 返回为PersistentCollection s(例如PersistentSet ),并且是延迟加载的,因此,可以'不能在 DB session 的 scope 之外读取(此时 Jackson 正在尝试序列化来自控制器的响应)。

理想情况下,我希望 Hibernate 返回 Java collections 的代理( HibernateProxy ),它们确实维护对它们包装的实体的引用(标识符)。 也可以继续使用专门的数据结构(如PersistentCollection ),但保留对项目的引用,因为一旦包装,它们只能从位于 BD session 的 map 中检索,没有它,集合的关键完全没用(为什么要这样?如果我们不想要整个项目,而只是将它的标识符序列化为参考呢?叹息)。

我想知道...

是否可以强制 Hibernate 返回 Java collections 的代理包装实体?

如果没有,是否可以扩展 Hibernate collections (如PersistentCollection )以维护对包装实体的引用,以便在专门的 Jackson-Hibernate 序列化程序中读取它们?

If not, is it possible to convert Hibernate collections to Java collections before closing the BD session, without using additional data structures, besides the entity itself (ie convert the collection back to a Java type)?

好吧,您可以使用例如 HQL select u from User u join fetch u.groups并使用interface ReferenceJsonView { Integer getId(); }使用@JsonView(ReferenceJsonView.class)注释User实体中的groups属性。 interface ReferenceJsonView { Integer getId(); } ,但这会比必要的获取更多的 state。 我建议您考虑实施适当的 DTO,这可以通过Blaze-Persistence Entity Views轻松完成。

Blaze-Persistence 是 JPA 之上的查询构建器,它支持 JPA model 之上的许多高级 DBMS 功能。 我在它上面创建了实体视图,以便在 JPA 模型和自定义接口定义模型之间轻松映射,例如 Spring 数据投影。 这个想法是您以您喜欢的方式定义您的目标结构,并通过 JPQL 表达式将 map 属性(getter)定义到实体 model。 由于属性名称用作默认映射,因此您通常不需要显式映射,因为 80% 的用例是拥有作为实体 model 子集的 DTO。

假设你有一个像这样的实体 model

@Entity
public class User {
    @Id
    Integer id;
    String username;
    @ONeToMany
    Set<Group> groups;
}

@Entity
public class Group {
    @Id
    Integer id;
    String name;
}

model 的 DTO 映射看起来很简单,如下所示

@EntityView(User.class)
interface UserDto {
    Integer getId();
    String getUsername();
    Set<GroupDto> getGroups();
}
@EntityView(Group.class)
interface GroupDto {
    Integer getId();
}

查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

UserDto dto = entityViewManager.find(entityManager, UserDto.class, id);

但是 Spring 数据集成允许您几乎像 Spring 数据投影一样使用它: https://persistence.blazebit.com/documentation/entity-view/mandata-features_html/index。

它只会获取您告诉它获取的映射,并且所有映射都在启动时进行验证,因此 go 在运行时不会出错。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM