2014-12-07 58 views
1

我正在實施一個在線商店。我有保存命令下面的代碼:Spring + JPA:對象不會從數據庫中獲取

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

通話完後itemnull,但它不是從數據庫中獲取:我的EclipseLink日誌功能,在「最美好」的水平,並且沒有SELECT查詢。

我認爲這是因爲EclipseLink在其持久性上下文中有這item,所以它不執行查詢。所以我已經嘗試在return之前在findOne方法實現中加入em.clear(),但它沒有幫助。

我該如何從數據庫中實際獲得新的item

預先感謝您。

P.S.我試着明確查詢我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: [email protected]。我不知道爲什麼,因爲我沒有做persist

+0

使用Spring構建在線商店是個不錯的主意。我也想這樣做。你能推薦任何有用的資料來源嗎? – burseaner 2014-12-16 18:45:17

回答

2

find方法將返回存在於持久性上下文中的副本,而不是第二次查詢數據庫。您可以調用實體管理器的refresh方法,以確保持久性上下文中的副本具有數據庫中的最新值:

+0

剛試過這個。拋出'IllegalArgumentException':「無法刷新不受管理的對象:[email protected]。」 – 2014-12-07 21:35:47

+1

你試過em.refresh(em.find(entityClass,id))嗎?只有當對象沒有從持久化上下文中分離出來時(如果你調用em.clear()),刷新纔會起作用。但是,首先執行em.find將爲您提供持久性上下文中的對象副本,然後您可以刷新該副本。或者,您可以使用em.merge()重新連接分離的實體。 – djmorton 2014-12-07 21:59:38

+0

它的工作!非常感謝你。 – 2014-12-07 22:24:36