Hibernate OGM+MongoDB问题:二次查询失效及更新后非ID字段无法获取
Troubleshooting Hibernate OGM 5.2.0.Alpha1 + MongoDB 3.6 Issues
Hey there, let's break down and solve the two issues you're running into with Hibernate OGM and MongoDB:
Issue 1: Can't execute a second query based on the first query's result
Possible Causes
- Lazy Loading & Session Closure: Your
CurrencyMasterhas a@OneToManyassociation withPurchaseOrder, which defaults to lazy loading. If your first query runs in a Session that gets closed before the second query, accessing the lazy-loadedsetOfPurchaseOrder(or using the entity in a new query) will fail because the entity is now detached. - Detached Entity in New Session: If you're trying to use the entity retrieved from the first query in a new Session without reattaching it, Hibernate OGM won't recognize it as a managed entity, leading to errors when executing the second query.
Solutions
- Keep Entities in the Same Session: Ensure both queries run within the same Hibernate Session. For example:
try (Session session = sessionFactory.openSession()) { // First query CurrencyMaster currency = session.find(CurrencyMaster.class, currencyId); // Second query using the result Query<PurchaseOrder> query = session.createQuery("FROM PurchaseOrder p WHERE p.currencyMaster = :currency", PurchaseOrder.class); query.setParameter("currency", currency); List<PurchaseOrder> orders = query.getResultList(); } - Eagerly Fetch Associations: If you need to use the entity outside the initial Session, modify your first query to fetch the association upfront with
JOIN FETCH:Query<CurrencyMaster> query = session.createQuery("SELECT c FROM CurrencyMaster c JOIN FETCH c.setOfPurchaseOrder WHERE c.id = :id", CurrencyMaster.class); query.setParameter("id", currencyId); CurrencyMaster currency = query.getSingleResult(); - Reattach Detached Entities: If you must use a new Session, reattach the entity with
session.merge()before running the second query:try (Session session1 = sessionFactory.openSession()) { currency = session1.find(CurrencyMaster.class, currencyId); } try (Session session2 = sessionFactory.openSession()) { CurrencyMaster managedCurrency = session2.merge(currency); // Now run the second query with managedCurrency }
Issue 2: Can't get fields other than ID after update operation
Possible Causes
- Detached Entity After Update: After performing an update, if you're working with a detached entity instance, Hibernate won't automatically refresh its state from the database.
- Missing Session Refresh: The update operation might modify the database, but the in-memory entity object isn't synced unless you explicitly refresh it.
- Transaction Boundary Issues: If the update isn't committed within a transaction, the changes might not be persisted to MongoDB, leading to stale data when you retrieve the entity.
Solutions
- Refresh the Entity After Update: After executing the update, call
session.refresh(entity)to reload its state from the database:try (Session session = sessionFactory.openSession()) { Transaction tx = session.beginTransaction(); CurrencyMaster currency = session.find(CurrencyMaster.class, currencyId); currency.setCode("USD"); // Update field session.update(currency); tx.commit(); session.refresh(currency); // Now all fields will be up-to-date } - Use
merge()to Get Updated Entity: Instead ofupdate(), usesession.merge()which returns the managed, updated entity:try (Session session = sessionFactory.openSession()) { Transaction tx = session.beginTransaction(); CurrencyMaster detachedCurrency = ...; // Your detached entity with updates CurrencyMaster updatedCurrency = session.merge(detachedCurrency); tx.commit(); // updatedCurrency has all the latest fields from the database } - Ensure Transactions Are Committed: Always wrap update operations in a transaction and commit it before accessing the entity. Without a committed transaction, MongoDB might not persist the changes immediately.
Your Entity Class Reference
Here's the formatted version of your provided entity code for reference:
@Entity @Table(name = "currency_master") @JsonInclude(Include.NON_EMPTY) public class CurrencyMaster{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @JsonSerialize(using = ToStringSerializer.class) @Column(name = "CURRENCY_ID", unique = true, nullable = false) private ObjectId id; private String code; @OneToMany(mappedBy = "currencyMaster") private Set<PurchaseOrder> setOfPurchaseOrder; // Getters and Setters } @Entity @Table(name = "...") // Your PurchaseOrder table name public class PurchaseOrder { // Your PurchaseOrder fields, including @ManyToOne to CurrencyMaster @ManyToOne private CurrencyMaster currencyMaster; // Other fields, getters and setters }
内容的提问来源于stack exchange,提问作者vishvas4u
相关产品推荐
相关产品推荐

