Java 第二次触发更新时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

我试图理解为什么当我第二次点击控制器时,我的OneTONE映射正在初始化。下面是我的代码: 控制器:

@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是“渴望”。