懒惰一对一Spring JPA与构建“动态"JSON [英] Lazy One-To-One Spring JPA and building "dynamic" JSON

查看:28
本文介绍了懒惰一对一Spring JPA与构建“动态"JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm developing a relatively large project using Spring Boot, and in a general way I'm pretty happy with it, but I'm having some problems that in my mind should't be a problem.

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

  1. First of all, One-To-One Relationship. It's frustrating that it doesn't work as it should (at least in my mind).

例如,我有两个实体,UserUserProfile.他们有一对一的关系,但大多数时候我只需要 User 数据,但它会获取(无论我尝试什么,哦,天哪,我在每个帖子上都尝试了世界建议Google 的 5 页).

I have two entities, User and UserProfile, for example. They have One-To-One relationship, but most of the time I only need the User data, but it fetches (no matter what I try, and oh boy, I tried the world suggestions on every post for 5 pages of Google).

所以我的第一个问题是,有没有办法可以在 JPA 和 Spring 中延迟获取一对一的关系?(因为大部分帖子都是2-3岁以上的).

So there is my first question, is there a way to be able to lazy fetch One-To-One relationship in JPA and Spring? (Because most of the posts are more than 2-3 years old).

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

The other problem I have is about to build a JSON response in a "dynamic" way. I did some stuff using Rails and was very happy with JBuilder or even the to_json that gave me the ability to build the json response depending on the controller and my needs at the moment.

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

In Spring I saw the following solutions:

  • Jackson @JsonView(这并不能完全解决我的问题,因为响应不是那么静态的,并且一个属性不能分配给多个视图(就我理解的概念而言));
  • 在响应中设置我不想要的空属性(使用这个,但我太丑了,看起来像一个错误的演练);
  • 或构建 HashMap 就像我在 Rails 上构建 .json.jbuilder 一样(但这会降低我的性能,因为有时它有很多关系,所以 forcode> 来构建 json,而且这看起来像一个丑陋的演练).
  • Jackson @JsonView (which doesn't solve entirely my problem because the responses are not that static and a attribute can't be assigned to multiple views (as far as I understood the concept));
  • setting to null attributes that I don't want on the response (using this, but I's just too ugly and looks like a wrong walkthrough);
  • or building HashMap like I build .json.jbuilder on Rails (but this kills my performance as sometimes it has relationships so a lot of for to build the json, and also this looks like a ugly walkthrough).

我正在寻找某天可能遇到此类问题之一的人的一些指导,因为它让我无法解决在我看来不应该如此困难的问题.

I'm looking for some directions from someone that someday may have encountered one of this problems because it's killing me not being able so solve problems that in my mind should not be this hard.

编辑 1

已经尝试在 @OneToOne 注释上添加 optional = false 以解决 @snovelli 建议的 OneToOne 关系的 Eager load.示例:

Already tried to add optional = false on the @OneToOne annotation to solve the Eager load of OneToOne relationship as @snovelli suggested. Example:

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

推荐答案

如果连接列不在一对一关联中的父项映射到的表中,则该关联 不能偷懒.原因是JPA提供者无法确定是否创建代理,以便稍后访问时加载对象,或者保留null值.

If the join column is not in the table to which a parent in a one-to-one association is mapped, then the association cannot be lazy. The reason is that JPA provider cannot determine whether to create the proxy, so that it can load the object when accessed later, or leave the null value.

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

Even if the association is not optional, JPA provider has to determine the id of the associated entity instance to store it in the proxy. Thus it has to go to the associated table anyway.

解决方案:

  1. 字节码仪器.虽然没有被广泛采用.
  2. 使用一对多并将空列表作为null处理,否则使用list.get(0).您当然可以将其封装在实体类中(getter 返回列表的唯一元素或 null).缺点是您必须在 JPQL 查询中将其视为集合.
  3. 使用@PrimaryKeyJoinColumn 而不是外键.如果关联不是可选的(optional = false),那么JPA提供者知道有一个关联的具有相同PK的子项,因此它只会将父项的PK存储为子项的id在代理中.显然,您不能为两个实体使用两个独立的 id 生成器,否则 PK 可能不同.如果它满足您的要求,这是最好的方法.
  4. 还要在父表中添加外键(也使数据库中的关系是双向的).缺点是您现在基本上有两个必须维护的独立关联.此外,更新两个表而不是一个表会产生性能成本(并且外键必须可以为空).
  5. 将父实体映射到一个数据库视图,该视图将父表与子表连接起来,并包含所有父列和子表的 id:

  1. Byte code instrumentation. Not widely adopted approach though.
  2. Use one-to-many and handle empty list as null, otherwise use list.get(0). You can of course encapsulate this in the entity class (getter returns the only element of the list or null). The drawback is that you will have to treat this as collection in JPQL queries.
  3. Use @PrimaryKeyJoinColumn instead of a foreign key. If the association is not optional (optional = false), then JPA provider knows that there is an associated child with the same PK, so it will just store the PK of the parent as the id of the child in the proxy. Obviously, you can't use two independent id generators for both of the entities, otherwise PKs may be different. This is the best approach if it meets your requirements.
  4. Add the foreign key in the parent table also (making the relationship bidirectional in the database as well). The drawback is that you now basically have two independent associations which you have to maintain. Also, there is the performance cost of updating two tables instead of one (and the foreign keys have to be nullable).
  5. Map parent entity to a database view that joins parent table with the child table and contains all parent columns plus id of child table:

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "<child id in the view>", insertable = false, updatable = false)
private Child child;

这篇关于懒惰一对一Spring JPA与构建“动态"JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆