JPA复用主键问题:EntityA关联EntityB的操作咨询
listOfB in Your JPA Entity Setup Alright, let's break down how to properly handle the listOfB collection in your EntityA instance, given this JPA setup where EntityB uses a composite key that reuses EntityA's ID. I'll walk through the most common operations you'll need:
Adding a New EntityB to the List
Since EntityB's composite key includes entityAId (tied directly to EntityA's ID), you must set this value explicitly before adding the new EntityB to the list. Thanks to cascade=CascadeType.ALL, the new EntityB will be automatically persisted when you save or merge EntityA.
// Assume myEntityA was retrieved via entityManager.find(EntityA.class, 1) EntityB newEntityB = new EntityB(); newEntityB.setEntityAId(myEntityA.getId()); // Critical: set the composite key part newEntityB.setName("config_key"); newEntityB.setValue("config_value"); // Add to the list myEntityA.getListOfB().add(newEntityB); // If myEntityA is in managed state (which it is right after find), just commit the transaction // If it's detached, use merge: // entityManager.merge(myEntityA);
Modifying an Existing EntityB in the List
If myEntityA is in a managed state (i.e., it's still attached to the EntityManager context), you can directly modify the EntityB's properties—JPA will automatically sync these changes to the database when the transaction commits.
for (EntityB b : myEntityA.getListOfB()) { if ("config_key".equals(b.getName())) { b.setValue("updated_config_value"); // No need to call merge() here—managed entities track changes automatically } } // Commit the transaction to persist the updates
Removing an EntityB from the List
You've set orphanRemoval = true on the @OneToMany annotation, which makes this straightforward: simply remove the EntityB from the list, and JPA will automatically delete the corresponding database record when the transaction commits. Use an iterator to avoid ConcurrentModificationException:
Iterator<EntityB> iterator = myEntityA.getListOfB().iterator(); while (iterator.hasNext()) { EntityB b = iterator.next(); if ("config_key".equals(b.getName())) { iterator.remove(); // Remove from the list // orphanRemoval=true ensures the record is deleted from the DB } } // Commit the transaction to finalize the deletion
Key Things to Remember
- Avoid Null Collections: You already initialized
listOfBwithnew ArrayList<>()inEntityA—great call, this preventsNullPointerExceptionwhen adding/removing items. - Composite Key Integrity: Never skip setting
entityAIdonEntityB—it's part of the primary key, so JPA can't persist or locate the entity without it. - Lazy Loading Caveats: Since
fetch=FetchType.LAZY, accessinglistOfBafter the EntityManager is closed will throw aLazyInitializationException. If you need to access the list outside a transaction, either initialize it within the transaction (e.g.,Hibernate.initialize(myEntityA.getListOfB())) or adjust the fetch type (though eager fetching isn't recommended for performance reasons). - Transaction Boundaries: All modify/add/remove operations must happen within an active transaction—otherwise, the changes won't be saved to the database.
内容的提问来源于stack exchange,提问作者user2660369

