【问题标题】:Spring + JPA: object does not get fetched from the databaseSpring + JPA:没有从数据库中获取对象
【发布时间】:2015-02-05 12:09:43
【问题描述】:

我正在实施一个在线商店。我有以下代码用于保存订单:

@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);
        }
    }
}

在实际保存订单之前,我更新了每件商品的“重量”属性(此订单出售了一些数量,因此剩下的数量较少)。

OrderedItem 对象持有对Item 的引用,但我想从数据库中获取新的Item(另外检查是否有足够的待售商品,以防数据库中的Item 表发生更改并且UI 没有'在用户提交订单之前不更新)。我为此目的调用的findOne方法实现如下:

@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);
    }
}

在调用item 之后不是null,但它没有从数据库中获取:我在“FINEST”级别打开了EclipseLink 日志记录,并且没有SELECT 查询。

我认为这是因为 EclipseLink 在其持久性上下文中有这个 item,所以它不执行查询。所以我尝试在findOne方法实现中在return之前添加em.clear(),但没有帮助。

我实际上如何从数据库中获取新的item

提前谢谢你。

附:我尝试在我的 findOne 方法中显式查询,如下所示:

    @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;
    }

这样我得到了异常:java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: ftcApp.model.Order@cf616dce。我不知道为什么,因为我没有在做persist

【问题讨论】:

  • 使用 Spring 建立在线商店是个好主意。我也想做。你能推荐任何有用的资源作为它的起点吗?

标签: java mysql spring jpa eclipselink


【解决方案1】:

find 方法将返回存在于持久化上下文中的副本,而不是再次查询数据库。您可以调用实体管理器的refresh 方法,以确保持久化上下文中的副本具有数据库中的最新值:

【讨论】:

  • 刚试过这个。抛出IllegalArgumentException:“无法刷新非托管对象:ftcApp.model.Item@5dadd2e0。”
  • 你试过 em.refresh(em.find(entityClass, id)) 吗?仅当对象未从持久性上下文中分离时,刷新才会起作用(如果您调用 em.clear(),则会发生这种情况)。但是,首先执行 em.find 将为您提供持久性上下文中的对象副本,然后您可以刷新该副本。或者,您可以使用 em.merge() 重新附加分离的实体。
猜你喜欢
  • 1970-01-01
  • 2021-08-23
  • 2012-01-29
  • 1970-01-01
  • 2019-10-03
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
  • 2018-07-19
相关资源
最近更新 更多