Lazy One-To-One Spring JPA and building “dynamic” JSON

后端 未结 3 1713
南笙
南笙 2020-12-11 16:19

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 pr

3条回答
  •  暖寄归人
    2020-12-11 17:03

    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.

    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.

    Solutions:

    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 = "", insertable = false, updatable = false)
      private Child child;

提交回复
热议问题