懒惰的One-To-One Spring JPA并构建"动态"JSON

aug*_*sar 9 java spring jpa jackson spring-boot

我正在使用Spring Boot开发一个相对较大的项目,一般来说我很满意它,但是我遇到了一些问题,在我看来应该不是问题.

  1. 首先,一对一的关系.令人沮丧的是它不能正常工作(至少在我看来).

    我有两个实体,User并且UserProfile,例如.他们有一对一的关系,但大部分时间我只需要User数据,但它取而代之(无论我尝试什么,哦,男孩,我在5页Google的每篇文章中尝试了世界建议).

    所以我的第一个问题是,有没有办法能够在JPA和Spring中实现懒惰的一对一关系?(因为大部分帖子都超过2 - 3年).

  2. 我遇到的另一个问题是以"动态"方式构建JSON响应.我使用Rails做了一些事情并且非常满意,JBuilder甚至to_json这让我能够根据控制器和我目前的需求构建json响应.

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

    • Jackson @JsonView (这并不完全解决我的问题,因为响应不是静态的,并且属性不能分配给多个视图(据我理解的概念));
    • 设置为null我不想要的响应属性(使用这个,但我太丑了,看起来像一个错误的演练);
    • 或者HashMap像我.json.jbuilder在Rails上构建的那样(但是这会破坏我的表现,因为它有很多关系for来构建json,这看起来像是一个丑陋的演练).

我正在寻找某人的某些指示,有朝一日可能会遇到其中一个问题,因为它让我无法解决问题,而在我看来这不应该是这么难.

编辑1

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

@OneToOne(optional=false, fetch = FetchType.LAZY)
public UserProfile getUserProfile(){ ... }
Run Code Online (Sandbox Code Playgroud)

Dra*_*vic 7

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

即使关联不是可选的,JPA提供者也必须确定关联实体实例的id以将其存储在代理中.因此,无论如何它必须转到相关的表.

解决方案:

  1. 字节代码检测.虽然没有广泛采用的方法.
  2. 使用一对多并处理空列表null,否则使用list.get(0).您当然可以将其封装在实体类中(getter返回列表的唯一元素或null).缺点是您必须将其视为JPQL查询中的集合.
  3. 使用@PrimaryKeyJoinColumn而不是外键.如果关联不是optional(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;
    Run Code Online (Sandbox Code Playgroud)