我正在使用Hibernate OGM(5.2.0.Alpha1)和Mongodb(3.6)
@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;
getter()
setter()
}
@Entity
@Table(name = "purchase_order)
@JsonInclude(Include.NON_EMPTY)
public class PurchaseOrder {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonSerialize(using = ToStringSerializer.class)
@Column(name = "PURCHASE_ORDER_ID", unique = true, nullable = false)
private ObjectId id;
private String purchaseOrderNo;
private Double total;
@ManyToOne
@JsonIgnore
private CurrencyMaster currencyMaster;
getter()
setter()
}
DAO Layer:
@SuppressWarnings("unchecked")
@Override
public <T> void update(T t) {
try {
Field[] fields = t.getClass().getDeclaredFields();
Map<String, Object> mapUpdatedFields = new HashMap<String, Object>();
for (Field field : fields) {
field.setAccessible(true);
mapUpdatedFields.put(field.getName(), field.get(t));
}
T newT = this.getById(mapUpdatedFields.get("id").toString(), t);
mapUpdatedFields.remove("id");
mapUpdatedFields.forEach((k, v) -> {
if (!AccountingMethodUtils.isObjectisNullOrEmpty("update()", v)) {
AccountingMethodUtils.setValueToField(newT, k, v);
}
});
entityManager.merge(newT);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error(
"update() of DAO : (Error in outer try..catch) Error in updating record of {} and Error is {}.",
t.getClass(), e);
}
}
@Override
public <T> List<T> executeQuery(String query, Integer startPosition, Integer noOfRecords, T t) {
List<T> listOfT = new ArrayList<>();
if (AccountingMethodUtils.isObjectisNullOrEmpty(startPosition, noOfRecords)) {
listOfT = entityManager.createNativeQuery(query.toString(), t.getClass()).getResultList();
} else {
listOfT = entityManager.createNativeQuery(query.toString(), t.getClass()).setFirstResult(startPosition)
.setMaxResults(noOfRecords).getResultList();
}
return AccountingMethodUtils.isListIsNullOrEmpty(listOfT) ? new ArrayList<>() : listOfT;
}
服务层:
@Override
@Transactional
public String updatePurchaseOrder(AccountingRequestBody input) {
PurchaseOrder purchaseOrder = AccountingMethodUtils.getObjectMapper().convertValue(input.getJsonOfObject(),
PurchaseOrder.class);
// Query : db.purchase_order.find( {'_id' : ObjectId("5ab88323191bb91e78f9e33d") } , { 'purchaseOrderNo' : 1, 'currencyMaster_CURRENCY_ID' : 1 , 'total' : 1 })
StringBuilder sb = new StringBuilder().append("db.").append(AccountingVariableUtils.TABLE_NAME_FOR_PURCHASE_ORDER)
.append(".find( {'_id' : ObjectId('" + purchaseOrder.getId().toString()
+ "') } , { 'purchaseOrderNo' : 1, 'currencyMaster_CURRENCY_ID' : 1 , 'total' : 1 })");
List<PurchaseOrder> poFromDB = purchaseOrderDao.executeQuery(sb.toString(), null, null, new PurchaseOrder());
if (!AccountingMethodUtils.isListIsNullOrEmpty(poFromDB)) {
System.out.println("id before update : " + poFromDB.get(0).getCurrencyMaster().getId()); // Output: 5ab8830b191bb91e78f9e221
System.out.println("code before update : " + poFromDB.get(0).getCurrencyMaster().getCode()); // Output: INR
}
purchaseOrderDao.update(purchaseOrder);
poFromDB = purchaseOrderDao.executeQuery(sb.toString(), null, null, new PurchaseOrder());
if (!AccountingMethodUtils.isListIsNullOrEmpty(poFromDB)) {
System.out.println("id after update : " + poFromDB.get(0).getCurrencyMaster().getId()); // Output: 5ab8830b191bb91e78f9e221
System.out.println("code after update : " + poFromDB.get(0).getCurrencyMaster().getCode()); // Output: null //?????????????????????
}
}
输出:
id before update : 5ab8830b191bb91e78f9e221
code before update: INR
id after update : 5ab8830b191bb91e78f9e221
code afterupdate: null ?????????????????????
说明
Currency Master与采购订单有一对多的映射(双向)。
在服务层中,
首先我执行查询以从采购订单中获取“id,code,total”并成功获取所有字段。
然后我更新了采购订单。
然后我再次执行相同的查询(从购买订单中获取“id,代码,总数”),然后我可以获得货币主数据的ID但无法获得货币主数据的代码。
我是对的吗?
答案 0 :(得分:0)
我认为问题在于您在原生查询中使用投影并尝试创建实体而不检索所需的所有信息。我会从原生查询中删除投影部分,只使用:
db.purchase_order.find( {'_id' : ObjectId("5ab88323191bb91e78f9e33d") } );
这是因为Hibernate OGM缓存结果,因此您必须确保正确初始化实体。
或者,更好的是,为什么不尝试使用JPQL查询?
PurchaseOrder order = em.createQuery( "FROM PurchaseOrder po WHERE po.id = :id", PurchaseOrder.class )
.setParameter( "id", "5ab88323191bb91e78f9e33d" )
.getSingleResult();
顺便说一句,Hibernate OGM不应该让你做这类事情,并会在后续版本中抛出异常。
最后,我建议更新到Hibernate OGM 5.3.0.Final或至少更新到5.2.0.Final(如果你有任何理由坚持坚持5.2系列)。