一尘不染

一对一Spring JPA和构建“动态” JSON

spring-boot

我正在使用Spring Boot开发一个相对较大的项目,总的来说,我对此很满意,但是我遇到了一些我认为不应该成为问题的问题。

  1. 首先,一对一关系。令人沮丧的是,它无法正常运行(至少在我看来)。

我有两个实体,User并且UserProfile,例如。他们之间存在一对一的关系,但是大多数时候我只需要User数据,但是数据却可以获取(无论我尝试什么,天哪,我都尝试过每5条Google页面上的世界建议)。

因此,我的第一个问题是,是否有一种方法可以在JPA和Spring中延迟获取一对一关系?(因为大多数职位超过2-3年)。

  1. 我遇到的另一个问题是要以“动态”方式构建JSON响应。我使用Rails做了一些事情,对此感到非常满意,JBuilder甚至to_json使我能够根据控制器和当前的需求构建json响应。

在Spring,我看到了以下解决方案:

* `Jackson @JsonView` (这不能完全解决我的问题,因为响应不是静态的,并且不能将属性分配给多个视图(据我了解的概念));
* 设置为我不想在响应中使用的空属性(使用此属性,但是我太丑陋,看起来像一个错误的演练);
* 或`HashMap`像`.json.jbuilder`在Rails上构建那样进行构建(但是这有时会影响我的性能,因为有时它`for`与构建json的关系如此之多,而且看起来像是一个丑陋的演练)。

我正在寻找某人的某个方向,以至于某天可能遇到了其中一个问题,因为这使我无法解决这个问题,这使我丧命,这在我看来不应该那么难。

编辑1

已经尝试添加optional = false@OneToOne注释来解决的OneToOne关系的渴望负荷@snovelli建议。例:

@OneToOne(optional=false, fetch = FetchType.LAZY)
public UserProfile getUserProfile(){ ... }

阅读 317

收藏
2020-05-30

共1个答案

一尘不染

如果连接列不在一对一关联中的父级映射到的表中,则关联不能是lazy。原因是JPA提供程序无法确定是否创建代理,以便它可以在以后访问时加载对象或保留null值。

即使关联不是可选的,JPA提供程序也必须确定关联实体实例的ID才能将其存储在代理中。因此,它无论如何都必须转到关联的表。

解决方案:

  1. 字节码检测。虽然没有被广泛采用。
  2. 使用一对多并以处理空列表null,否则使用list.get(0)。您当然可以将其封装在实体类中(getter返回list或的唯一元素null)。缺点是您必须将其视为JPQL查询中的集合。
  3. 使用@PrimaryKeyJoinColumn代替外键。如果关联不是可选的(optional = false),则JPA提供程序知道存在一个具有相同PK的关联子项,因此它将仅将父项的PK作为子项的ID存储在代理中。显然,您不能为两个实体使用两个独立的ID生成器,否则PK可能会有所不同。如果满足您的要求,这是最好的方法。
  4. 还要在父表中添加外键(在数据库中也使关系成为双向的)。缺点是您现在基本上必须维护两个独立的关联。同样,更新两个表而不是更新一个表也会带来性能成本(并且外键必须为空)。
  5. 将父实体映射到一个数据库视图,该数据库视图将父表与子表连接在一起,并且包含所有父列以及子表的ID:
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "<child id in the view>", insertable = false, updatable = false)
private Child child;
2020-05-30