简体   繁体   中英

Spring JPA Lazy loading @OneToOne entities doesn't work

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 = "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> {
}

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?

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);
}


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 = "billing_address_id")
private BillingAddressEntity billingAddress;


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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM