0
votes

i am using Hibernate OGM (5.2.0.Alpha1) with 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;
    }

Service Layer:

@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    //?????????????????????
    }
}

output:

id before update : 5ab8830b191bb91e78f9e221
code before update: INR

id after update : 5ab8830b191bb91e78f9e221
code afterupdate: null ?????????????????????

Description:

Currency Master has one to many mapping(bidirectional) with purchase order.

In Service Layer,

  1. first i executed query to get "id,code,total" from purchase order and successfully got all the fields.

  2. then i updated purchase order.

  3. then i again executed same query ( to get "id,code,total" from purchase order) after update then i can get id of currency master but can't get code of currency master.

Is Am i Right???

1

1 Answers

0
votes

I think the problem is that you are using projection in your native query and trying to create the entity without retrieving all the information needed. I would remove the projection part from the native query and only use:

db.purchase_order.find( {'_id' : ObjectId("5ab88323191bb91e78f9e33d") } );

This happens because Hibernate OGM caches results, so you have to make sure to initialize entities correctly.

Or, even better, why don't you try using a JPQL query?

PurchaseOrder order = em.createQuery( "FROM PurchaseOrder po WHERE po.id = :id", PurchaseOrder.class )
                    .setParameter( "id", "5ab88323191bb91e78f9e33d" )
                    .getSingleResult();

By the way, Hibernate OGM shouldn't let you do this kind of things and will throw an exception in follow-up versions.

Last, I would recommend to update to Hibernate OGM 5.3.0.Final or at least to 5.2.0.Final (if there is any reason for you to stick to stick to the 5.2 family).