Spring Boot 2一对多关联问题:子实体外键保存为Null
Let's break down why your foreign keys (car_component_id and car_service_id) are ending up null, even though you thought you set the associations, and fix this step by step:
1. Critical Setter Method Errors in Your Service Code
Looking at your service layer code, two obvious syntax/method name mistakes are directly causing the null foreign keys:
- Wrong setter for
carComponent: You calledcco.setCarComponentOccurrences(optCarComponents.get());, but yourCarComponentOccurrencesentity has a field namedcarComponent— the correct setter iscco.setCarComponent(optCarComponents.get());. This mistake means thecarComponentfield was never populated, socar_component_idstays null in the database. - Invalid method call for
carService:cco.CarServices(cs);is not a valid setter call. You need to use the proper setter method:cco.setCarServices(cs);. Without this, thecarServicefield remains unset, leading to a nullcar_service_id.
2. Bidirectional Association Maintenance
Your CarServices and CarComponentOccurrences form a bidirectional one-to-many relationship, with mappedBy = "carService" on the @OneToMany annotation. This means the CarComponentOccurrences entity is the owning/maintaining side of the relationship. Hibernate only looks at the owning side to determine foreign key values, so even if you set the list on CarServices, if the carService field on CarComponentOccurrences isn't set correctly, the foreign key won't be populated.
3. Potential ID Generation Strategy Issue
From your Hibernate logs:
Hibernate: select nextval ('public.car_component_occurrences_id_seq') Hibernate: insert into public.car_component_occurrences ( car_component_id, car_service_id, name, id) values (?, ?, ?, ?) Hibernate: update public.car_services set name=?, where id=?
Notice that car_component_occurrences is inserted before car_services is updated. This suggests your CarServices entity might not have a proper ID generation strategy (like @GeneratedValue). If CarServices doesn't get its ID assigned before the child entity is saved, even if you set the association, the foreign key would be null (though your immediate issue is the setter mistakes above).
Corrected Service Layer Code
Here's the fixed version of your save method with the setter errors resolved:
@Autowired private CarServicesRepository repository; @Autowired private CarComponentsRepository carComponentsRepository; public void save(){ CarServices cs = new CarServices(); cs.setName("name"); List<CarComponentOccurrences> carComponentOccurrences = new ArrayList<>(); CarComponentOccurrences cco = new CarComponentOccurrences(); Optional<CarComponents> optCarComponents = carComponentsRepository.findById(1); if (optCarComponents.isPresent()) { // Fixed setter for carComponent cco.setCarComponent(optCarComponents.get()); } // Fixed setter for carService cco.setCarServices(cs); carComponentOccurrences.add(cco); cs.setCarComponentOccurrences(carComponentOccurrences); repository.save(cs); }
Additional Recommendations
- Ensure Proper ID Generation: Make sure all your entity classes have annotated ID fields with the correct generation strategy for Postgres (usually
IDENTITYorSEQUENCE):@Entity public class CarServices{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToMany(mappedBy = "carService", cascade = CascadeType.PERSIST) private List<CarComponentOccurrences> carComponentOccurrences; // Getters and Setters } @Entity public class CarComponentOccurrences { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private CarComponents carComponent; @ManyToOne private CarServices carService; // Getters and Setters } - Verify Cascade Settings: If you need more than just persist operations to cascade (like update, delete), consider using
CascadeType.ALLinstead ofCascadeType.PERSIST. - Use SQL Logs: You're already doing this, but keep leveraging Hibernate's SQL logs to inspect the actual parameters being passed to insert/update statements — it's invaluable for debugging association issues.
内容的提问来源于stack exchange,提问作者robert trudel

