Java 第二次触发更新时OneTONE映射的延迟初始化
我试图理解为什么当我第二次点击控制器时,我的OneTONE映射正在初始化。下面是我的代码: 控制器:Java 第二次触发更新时OneTONE映射的延迟初始化,java,spring,hibernate,spring-boot,spring-data-jpa,Java,Spring,Hibernate,Spring Boot,Spring Data Jpa,我试图理解为什么当我第二次点击控制器时,我的OneTONE映射正在初始化。下面是我的代码: 控制器: @RequestMapping(value="/updateOrderbyOrderid", method=RequestMethod.PUT,produces=MediaType.APPLICATION_JSON_VALUE) public Order updateOrderbyOrderid (@RequestBody Order orderVO ) { System.out.printl
@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;
}
{
"orderId" :101,
"customerId" : 2
}
Order s1 = orderRepository.findByOrderId(orderVO.getOrderId()); :
订单实体:
@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() {
}
}
客户实体:
@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() {
}
}
控制器的Json结构:
@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;
}
{
"orderId" :101,
"customerId" : 2
}
Order s1 = orderRepository.findByOrderId(orderVO.getOrderId()); :
首次点击的订单表:
OneTONE注释实体屏幕截图,第一次点击。customerRepository.findByCustomerId(orderVO.getCustomerId())没有惰性初始化bean:
第二次点击的订单表:
当我第二次点击时,我得到了customerRepository.findByCustomerId(orderVO.getCustomerId())的一个延迟加载bean。为什么会这样:
我期望hibernate在下一次执行orderVO.setCustomer(customerRepository.findByCustomerId(orderVO.getCustomerId())时也能得到完全加载的bean;而不是对从Order s1=orderRepository.findByOrderId(orderVO.getOrderId())获得的惰性初始化bean进行分配 一个重要的注意事项是,如果我在控制器的下面一行进行评论:
@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;
}
{
"orderId" :101,
"customerId" : 2
}
Order s1 = orderRepository.findByOrderId(orderVO.getOrderId()); :
并将其替换为顺序s1=null,我不再得到懒惰的初始化bean。hibernate缓存与之前在内部初始化的同一个懒惰bean吗
s1的截图,当我没有评论它时:
注释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;
}
我认为必须使用fetch=FetchType.EAGER进行OneToOne映射
@OneToOne(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@JoinColumn(name = "ORDER_CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID")
private Customer customer;
希望它能有所帮助。您的映射看起来非常像许多。试试这个:
// OrderTable
@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "CUSTOMER_ID", nullable = false)
private Customer customer;
// constructors
public OrderTable() {}
public OrderTable(Customer customer) { this.customer = customer; }
// Customer
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "customer")
private OrderTable orderTable;
Spring数据JPA-
findBy()
方法由EntityManager.find()内部实现EntityManager.find()
首先检查缓存中的数据,如果在缓存中找不到数据,则点击DB加载数据并放入缓存以进行管理
如果我们再次执行EntityManager.find()
(同样针对同一主键),它将再次检查缓存。现在,这一次数据是从缓存加载的,而不是命中数据库
我认为Hibernate正在缓存对象,当我第二次点击时,它返回缓存项的代理对象
下面是我为理解findBy()
工作而阅读的链接
现在,为了测试我是否正确,我在下面的代码中使用了em.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;
}
您的期望是什么?我的期望是hibernate在下一次执行orderVO.setCustomer(customerRepository.findByCustomerId(orderVO.getCustomerId())时也会得到完全加载的bean;而不是对从Order s1=orderRepository.findByOrderId(orderVO.getOrderId())获得的惰性初始化bean进行分配;尝试创建一个
OrderVO
类作为一个简单的POJO(没有Hibernate注释),其中只包含customerId
和orderId
字段,并使用它来收集JSON值。然后使用此值从存储库中获取订单
和客户
。我认为使用托管实体收集JSON值不是一个好主意,托管实体只能用于持久性。@JMSilla我也尝试过这个,但得到了相同的结果。你也可以在你的电脑上试试这个东西。我使用SpringDataJPA来获取数据,而不是直接使用HibernateEntityManager。如此渴望对它没有任何影响。请参阅此URL:。也可以在你的电脑上试用。默认情况下,1:1是“渴望”。