Spring + JPA: object does not get fetched from the database

余生颓废 提交于 2019-12-08 05:18:40

问题


I am implementing an online shop. I have the following code for saving an order:

@Service
@Transactional
public class OrderServiceImpl extends GenericServiceImpl<Order, Integer> implements OrderService {

    @Inject
    private ItemRepository itemRepository;

    @Override
    public void saveOrder(Order order) {
        this.updateItemsAccordingToOrderedQuantities(order);
        repository.save(order);
    }

    private void updateItemsAccordingToOrderedQuantities(Order order) {
        List<OrderedItem> orderedItems = order.getOrderedItems();
        for (OrderedItem orderedItem : orderedItems) {
            // fetch from database
            Item item = itemRepository.findOne(orderedItem.getItem().getId()); 

            item.reduceWeightInColdStoreBy(orderedItem.getWeight());
            itemRepository.update(item);
        }
    }
}

Before actually saving the order I update the "weight" property of each item (some quantity gets sold with this order, so there is less left).

OrderedItem objects hold the reference to Item, but I want to fetch the fresh Item from the database (to additionally check there is enough on sale, in case Item table in database changed and UI didn't update before user submitted order). findOne method I am calling for this purpose is implemented as follows:

@Repository
public class GenericRepositoryImpl<T, ID extends Serializable> implements GenericRepository<T, ID> {
    @PersistenceContext
    EntityManager em;

    protected Class<T> entityClass;

    public GenericRepositoryImpl(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    @Override
    public T findOne(ID id) {
        return em.find(entityClass, id);
    }
}

After the call item is not null, but it is not fetched from the database: I have EclipseLink logging turned on, at "FINEST" level, and there is no SELECT query.

I thought that it is because EclipseLink has this item in its persistence context, so it doesn't execute the query. So I've tried adding em.clear() before return in findOne method implementation, but it didn't help.

How do I actually get the fresh item from the database?

Thank you in advance.

P.S. I've tried querying explicitly in my findOne method, like so:

    @Override
    public T findOne(ID id) {
        T result = null;
        try {
            TypedQuery<T> query = em.createQuery("SELECT e FROM " + entityClass.getName() + " e", entityClass);
            result = query.getSingleResult();
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        return result;
    }

This way I get the exception: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: ftcApp.model.Order@cf616dce. I have no idea why, because I'm not doing persist.


回答1:


The find method will return the copy that exists in the persistence context rather than querying the database a second time. You can call the refresh method of the entity manager in order to ensure the copy in the persistence context has the latest values from the database:



来源:https://stackoverflow.com/questions/27347799/spring-jpa-object-does-not-get-fetched-from-the-database

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!