Spring JPA的@OneToOne实体懒加载不起作用。

huangapple go评论75阅读模式
英文:

Spring JPA Lazy loading @OneToOne entities doesn't work

问题

我在创建OrderEntity对象时遇到了让BillingAddress延迟加载的问题。我看到有很多关于这个问题的提问,并且按照指示进行了操作,包括添加了optional = false,但是每当我使用findById查找OrderEntity时,BillingAddress仍然被加载。

以下是我的实体类(为了简化问题而减少的代码):

OrderEntity

@Entity
@Table(name = "orders", schema = "glamitoms")
public class OrderEntity {

    @Id
    @Column(name = "id")
    private int id;

    @OneToOne(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
    private BillingAddressEntity billingAddress;

}

BillingAddressEntity

@Entity
@Table(name = "billing_address", schema = "glamitoms")
public class BillingAddressEntity {

    @Id
    @Column(name = "order_id")
    private int id;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    private OrderEntity order;
}

TestController

@RestController
public class TestController {

    private OrdersDAO ordersDAO;

    @Autowired
    public TestController(OrdersDAO ordersDAO) {
        this.ordersDAO = ordersDAO;
    }

    @GetMapping("/test")
    public void test() {
        OrderEntity orderEntity = ordersDAO.findById(1).get();
    }
}

OrdersDAO

@Repository
public interface OrdersDAO extends JpaRepository<OrderEntity, Integer> {
}

表格billing_address具有引用订单的外键。我已经阅读了关于是否应该添加optional = false以实现实体的延迟加载的矛盾答案,但对我来说似乎并不起作用。我在这些实体中是否遗漏了什么东西?

英文:

I'm having trouble making OrderEntity object load BillingAddress lazily. I've seen questions revolving around this asked a lot and followed instructions, including adding optional = false but BillingAddress still gets loaded whenever I findById an OrderEntity.

These are my entities (reduced for the sake of this question):

OrderEntity

@Entity
@Table(name = &quot;orders&quot;, schema = &quot;glamitoms&quot;)
public class OrderEntity {

    @Id
    @Column(name = &quot;id&quot;)
    private int id;

    @OneToOne(mappedBy = &quot;order&quot;, cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
    private BillingAddressEntity billingAddress;

}

BillingAddressEntity

@Entity
@Table(name = &quot;billing_address&quot;, schema = &quot;glamitoms&quot;)
public class BillingAddressEntity {

    @Id
    @Column(name = &quot;order_id&quot;)
    private int id;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId
    private OrderEntity order;
}

TestController

@RestController
public class TestController {

    private OrdersDAO ordersDAO;

    @Autowired
    public TestController(OrdersDAO ordersDAO) {
        this.ordersDAO = ordersDAO;
    }

    @GetMapping(&quot;/test&quot;)
    public void test() {
        OrderEntity orderEntity = ordersDAO.findById(1).get();
    }
}

OrdersDAO

@Repository
public interface OrdersDAO extends JpaRepository&lt;OrderEntity, Integer&gt; {
}

The table billing_address has a FK referencing orders. I've read contradicting answers saying adding optional = false should load entities lazily, but for me, that doesn't seem to work. Am I missing something in any of these entities?

答案1

得分: 1

请查看Vlad Mihalcea的文章使用JPA和Hibernate映射@OneToOne关系的最佳方法

正如文章中所述,其中一种解决方案是在父实体上删除关联...

@Transient
private BillingAddressEntity billingAddress;

然后使用共享的ID手动加载BillingAddressEntity

if (order.billingAddress == null) {
   order.billingAddress = entityManager.find(BillingAddressEntity.class, order.id);
}

另一种方法是删除共享键,使用外键字段并将关系标记为@ManyToOne。但这将牺牲OneToOne约束检查。

@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "billing_address_id")
private BillingAddressEntity billingAddress;

还有一种方法是使用字节码增强,使其成为@LazyToOne(LazyToOneOption.NO_PROXY)关系。不过,我无法帮助你实现这一点,因为我自己从未尝试过。

英文:

Have a look at Vlad Mihalceas article The best way to map a @OneToOne relationship with JPA and Hibernate

As described there, one of the solutions would be to drop the relation on the parentside...

@Transient
private BillingAddressEntity billingAddress;

and load the BillingAddressEntity manually using the shared id.

if (order.billingAddress == null) 
{
   order.billingAddress = entityManager.find(BillingAddressEntity.class, order.id);
}

<br>Another approach would be to drop the shared key, use a foreign key field instead and mark the relation as @ManyToOne. This will sacrifice the OneToOne constraint check though.

@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = &quot;billing_address_id&quot;)
private BillingAddressEntity billingAddress;

<br>Then there's also the byte code enhancement which would allow you to make this a @LazyToOne(LazyToOneOption.NO_PROXY)relation. I can't help you with that though, as I've never done that myself.

huangapple
  • 本文由 发表于 2020年8月11日 10:55:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/63350825.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定