gpt4 book ai didi

java - 第二次触发更新时 OnetoOne 映射的延迟初始化

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:45:04 24 4
gpt4 key购买 nike

我想了解为什么当我第二次按下 Controller 时,我的 OnetoOne 映射正在初始化。下面是我的代码: Controller :

@RequestMapping(value="/updateOrderbyOrderid", method=RequestMethod.PUT,produces=MediaType.APPLICATION_JSON_VALUE)
public Order updateOrderbyOrderid (@RequestBody Order orderVO ) {

System.out.println(orderVO.getOrderId());
Order s1 = orderRepository.findByOrderId(orderVO.getOrderId());
if (orderVO.getCustomerId()!=null) {
orderVO.setCustomer(customerRepository.findByCustomerId(orderVO.getCustomerId()));
}

s1 = orderRepository.saveAndFlush(orderVO);

return s1;
}

订单实体:

@Entity
@Table(name="Ordertable", schema="cf_2583f365_c3c6_499a_a60d_138e7e7023eb")
public class Order {
@Id
@Column(name = "ORDER_ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int orderId;



@OneToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL)
@JoinColumn(name = "ORDER_CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID")
private Customer customer;

private transient Long customerId;


public int getOrderId() {
return orderId;
}

public void setOrderId(int orderId) {
this.orderId = orderId;
}

public Customer getCustomer() {
return customer;
}

public void setCustomer(Customer customer) {
this.customer = customer;
}


public Long getCustomerId() {
return customerId;
}

public void setCustomerId(Long customerId) {
this.customerId = customerId;
}

}

客户实体:

@Entity
@Table(name="Customer", schema="cf_2583f365_c3c6_499a_a60d_138e7e7023eb")
public class Customer {

@Id
@Column(name = "CUSTOMER_ID")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long customerId;

@Column(name = "CUSTOMER_NAME")
private String customer_name;


@Column(name = "CUSTOMER_address_id")
private int customer_address_id;


public Long getCustomerId() {
return customerId;
}


public void setCustomerId(Long customerId) {
this.customerId = customerId;
}


public String getCustomer_name() {
return customer_name;
}


public void setCustomer_name(String customer_name) {
this.customer_name = customer_name;
}


public int getCustomer_address_id() {
return customer_address_id;
}


public void setCustomer_address_id(int customer_address_id) {
this.customer_address_id = customer_address_id;
}


public Customer() {

}

}

Controller 的 Json 结构:

{
"orderId" :101,
"customerId" : 2
}

第一次命中的顺序表:

enter image description here

OnetoOne 带注释的实体屏幕截图。没有用于 customerRepository.findByCustomerId(orderVO.getCustomerId()) 的惰性初始化 bean:

enter image description here

第二次命中的顺序表:

enter image description here

当我第二次点击时,我为 customerRepository.findByCustomerId(orderVO.getCustomerId()) 获得了一个延迟加载的 bean。为什么会这样:

enter image description here

我的期望是,当我执行 orderVO.setCustomer(customerRepository.findByCustomerId(orderVO.getCustomerId())) 时,下一次 hibernate 也应该得到完全加载的 bean;而不是分配它从 Order s1 = orderRepository.findByOrderId(orderVO.getOrderId()); 获得的惰性初始化 bean;

一个重要的注意事项,如果我在 Controller 中评论下面的行:

Order s1 = orderRepository.findByOrderId(orderVO.getOrderId()); :

并将其替换为 Order s1 = null,我不再使用惰性初始化 bean。 hibernate 是否在内部缓存相同的惰性初始化 bean??

s1 未评论时的截图: enter image description here

注释 s1 并将其替换为 null 后的代码:

@RequestMapping(value="/updateOrderbyOrderid", method=RequestMethod.PUT,produces=MediaType.APPLICATION_JSON_VALUE)
public Order updateOrderbyOrderid (@RequestBody Order orderVO ) {
System.out.println(orderVO.getOrderId());
Order s1 = null;
//Order s1 = orderRepository.findByOrderId(orderVO.getOrderId());
if (orderVO.getCustomerId()!=null) {
orderVO.setCustomer(customerRepository.findByCustomerId(orderVO.getCustomerId()));
}

s1 = orderRepository.saveAndFlush(orderVO);

return s1;
}

最佳答案

Spring Data JPA - findBy() 方法由 EntityManager.find() 内部实现。 EntityManager.find() 首先检查缓存中的数据,如果没有在缓存中找到数据,则访问 DB 加载数据并放入缓存中进行管理。

如果我们再次执行 EntityManager.find()(再次针对相同的主键),它会再次检查缓存。现在,这次数据是从缓存中加载的,而不是从数据库中加载的。

我认为 Hibernate 正在缓存对象,当我第二次点击时它返回缓存项的代理对象。

以下是我阅读过的链接,以了解 findBy() 的工作原理。

When use getOne and findOne methods Spring Data JPA

similar load and get hibernate method on spring data

What is the difference between EntityManager.find() and EntityManger.getReference()?

现在为了测试我是否正确,我在下面的代码中使用了 em.detach()detach() 将使托管实体 --> 非托管实体并将其从缓存中删除。现在,当我执行代码时,我得到了新初始化的 bean。

@RequestMapping(value="/updateOrderbyOrderid", method=RequestMethod.PUT,produces=MediaType.APPLICATION_JSON_VALUE)
public Order updateOrderbyOrderid (@Valid @RequestBody Order orderVO ) {

System.out.println(orderVO.getOrderId());
Order s1 = orderRepository.findByOrderId(orderVO.getOrderId());
em.detach(s1.getCustomer());
s1= null;
if (orderVO.getCustomerId()!=null) {
Customer findByCustomerId = customerRepository.findByCustomerId(orderVO.getCustomerId());
orderVO.setCustomer(customerRepository.findByCustomerId(orderVO.getCustomerId()));
}

s1 = orderRepository.saveAndFlush(orderVO);

return s1;
}

关于java - 第二次触发更新时 OnetoOne 映射的延迟初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55843655/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com