You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Data JPA一对一共享主键关联报错求助

Hey there, let's figure out why you're hitting that detached entity passed to persist error with your Spring Boot Data JPA one-to-one shared primary key setup.

First, let's break down the root causes and fix them step by step:

1. Fix the Entity Mapping Mistake

Looking at your Customer entity, you've added @PrimaryKeyJoinColumn alongside mappedBy = "customer" on the @OneToOne annotation—and that's a problem.

When you use mappedBy, you're telling JPA that the Phone entity is the owner of this relationship (it maintains the foreign key mapping). The @PrimaryKeyJoinColumn annotation is redundant here (and conflicting) because the relationship's primary key mapping is already defined in the Phone entity with @MapsId and @JoinColumn(name = "id").

Update your Customer entity to remove the extra annotation and add cascade support (this will make saving related entities smoother):

@Entity
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;
    // Remove @PrimaryKeyJoinColumn, add cascade for easier related entity handling
    @OneToOne(mappedBy = "customer", cascade = CascadeType.ALL)
    private Phone phone;
    // Constructors, getters, and setters
}

Your Phone entity is already correctly mapped, so leave it as is:

@Entity
public class Phone {
    @Id
    private Long id;
    private String number;
    @OneToOne
    @MapsId
    @JoinColumn(name = "id")
    private Customer customer;
    // Constructors, getters, and setters
}

2. Adjust Your Test Code (Two Valid Approaches)

Now that the mapping is fixed, let's fix the test logic to avoid the detached entity issue.

Approach 1: Use Cascade Save (Recommended)

Since we added cascade = CascadeType.ALL to the Customer's phone association, we can save just the Customer, and JPA will automatically save the associated Phone. This is cleaner and follows JPA best practices for bidirectional relationships:

@Test
public void test() {
    customerRepository.deleteAll();
    phoneRepository.deleteAll();
    
    final Customer customer = new Customer();
    customer.setFirstName("John");
    customer.setLastName("Doe");
    
    final Phone phone = new Phone();
    phone.setNumber("1234567890");
    phone.setCustomer(customer); // Link phone to customer (owner side)
    customer.setPhone(phone); // Link customer to phone (inverse side)
    
    customerRepository.save(customer); // Saves both customer and phone via cascade
}

Approach 2: Ensure You're Using a Managed Customer Instance

If you prefer not to use cascading, make sure the Customer instance you link to the Phone is managed (i.e., part of Hibernate's persistence context). Even though customerRepository.save() returns a managed instance, explicitly using the saved instance guarantees it's in the correct state:

@Test
public void test() {
    customerRepository.deleteAll();
    phoneRepository.deleteAll();
    
    final Customer customer = new Customer();
    customer.setFirstName("John");
    customer.setLastName("Doe");
    // Save and retain the managed customer instance
    Customer savedCustomer = customerRepository.save(customer);
    
    final Phone phone = new Phone();
    phone.setNumber("1234567890");
    phone.setCustomer(savedCustomer); // Use the managed instance here
    phoneRepository.save(phone);
}

Why Did the Original Error Happen?

  • The conflicting mapping annotations (mappedBy + @PrimaryKeyJoinColumn) confused JPA, making it unable to correctly recognize that the Customer instance was already persisted and managed.
  • Even without mapping issues, if the Customer instance becomes detached (for example, if the batch deleteAll() operations cleared the persistence context), saving the Phone would trigger an error because JPA tries to persist the detached Customer again.

内容的提问来源于stack exchange,提问作者user12091373

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:47:13