且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

懒惰的一对一春天JPA和建立“动态”的JSON

更新时间:2023-01-17 08:08:38

如果连接列不在一对一关联中的父级映射到的表,然后关联不能懒。原因是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;