2011-12-27 44 views
0

我的应用程序遇到一个奇怪的问题。我已经实现了优惠券评级功能。根据申请,我必须搜索优惠券,并点击它会显示一个描述页面,并有一个评级选项,用于对用户进行优先评级。我正在测试的是以下场景:我搜索优惠券“测试”,点击它并转到描述页面,并对它进行评分,并检查它是否反映在数据库中。最新的额定值和总评分将反映在说明页面中。然后我再次返回主页,搜索相同的优惠券,点击它进入其描述页面并再次评分。会发生什么是,数据库得到正确更新4-6次,之后,当我搜索该优惠券,并进入说明页面,它显示了评级和总评价的前值可能是它的价值时,它被评为几次之前(该值已在db中被覆盖)。然后,如果我对它进行评分,则数值不会在数据库中更新。从那里开始,这个功能就打破了。我尝试了几个选项,禁用缓存,设置一些点击eclipselink等,但没有解决问题。请分享你的建议。Spring/Eclipselink/MySQL应用程序数据问题

的persistence.xml:从我的代码的一些重要部分

<shared-cache-mode>NONE</shared-cache-mode> 
<property name="eclipselink.cache.shared.default" value="false"/> 
<property name="eclipselink.query-results-cache" value="false"/> 

优惠券和CouponRating具有单向一到一个映射:(此前我使用的双向映射,然后也同样的问题在那里。)

在CouponRating.java:

@Cacheable(false) 
@Entity 
@Table(name = "Coupon_Rating") 
public class CouponsRatings { 
.... 
.... 
.... 
@OneToOne 
@JoinColumn(name="coupon_id", unique=true, nullable=false, updatable=false) 
private Coupon coupon; 

@Version 
@Column(name="version") 
private long version; 

@Column(name="uuid") 
private String uuid; 
.... 
.... 
.... 

@Override 
public int hashCode() { 
    int hash = 3; 
    hash = 89 * hash + (this.uuid != null ? this.uuid.hashCode() : 0); 
    hash = 89 * hash + Long.valueOf(this.version).intValue(); 
    return hash; 
} 

    @Override 
public boolean equals(Object obj) { 
    if((obj == null) || (this.getClass() != obj.getClass())) 
     return false; 

    CouponsRatings couponsRatings = (CouponsRatings)obj; 
    return (this.version == couponsRatings.getVersion() && 
    this.uuid.equalsIgnoreCase(couponsRatings.getUuid())); 
} 
.... 
.... 

RatingManagerImpl.java

.... 
.... 

@Transactional 
public CouponsRatings saveRating(CouponsRatings rating) throws AppException{ 
    return ratingDAO.saveRating(rating); 
} 

@Transactional 
public CouponsRatings updateRating(CouponsRatings rating) 
     throws AppException { 
    return ratingDAO.updateRating(rating); 
} 

public CouponsRatings findRatingById(Long id) { 
    return ratingDAO.findRatingById(id); 
} 

public CouponsRatings refreshObject(CouponsRatings rating) { 
    return ratingDAO.refreshObject(rating); 
} 

.... 
.... 

在RatingDao:

.... 
.... 
private EntityManager entityManager; 

@PersistenceContext 
public void setEntityManager(EntityManager entityManager) { 
this.entityManager = entityManager; 
} 

@Override 
public CouponsRatings saveRating(CouponsRatings rating) throws AppException { 
try { 
     entityManager.persist(rating); 
} catch (Exception e) { 
    logger.debug("Error in saving coupon. Reason: " + e.getMessage()); 
    throw new CouponzleAppException(e.getMessage()); 
} 
return rating; 
} 

@Override 
public CouponsRatings findRatingByCouponId(Long id) { 
    CouponsRatings couponsRatings = null; 
    try { 
    couponsRatings = (CouponsRatings) entityManager 
      .createNamedQuery("findRatingByCouponId") 
      .setHint(QueryHints.CACHE_USAGE, 
          CacheUsage.DoNotCheckCache) 
      .setParameter(1, id).getSingleResult(); 
     } catch (NoResultException exception) { 
     logger.error("No active couponsRatings available for coupon id : " 
        + id); 
     } 
    return couponsRatings; 
} 

@Override 
public CouponsRatings updateRating(CouponsRatings rating) 
     throws AppException { 
    CouponsRatings updatedRating = null; 
    try { 
     updatedRating = entityManager.merge(rating); 
    } catch (Exception e) { 
     logger.debug("Error in updating coupon. Reason: " + .getMessage()); 
     throw new AppException(e.getMessage()); 
    } 
    return updatedRating; 
} 

@Override 
public CouponsRatings refreshObject(CouponsRatings rating) { 
    CouponsRatings updatedRating = null; 
    updatedRating = entityManager.merge(rating); 
    entityManager.refresh(updatedRating); 
    return rating; 
    } 

从Action类:(只有retreiving和更新塞纳里奥)

// this sometimes loads old date as i have described 
couponsRating = ratingsManager.findRatingByCouponId(Long.valueOf(
       couponId).longValue()); 

cupnsRating.setCurrentRating(currentRating); 
cupnsRating.setLastRatingDate(new Date()); 
cupnsRating.setRatingSum(ratingSum); 
cupnsRating.setTotalRatings(totalRatings); 
couponsRating = ratingsManager.updateRating(cupnsRating); 
// I tried to refresh updated object after i get the issue, but still no luck: 
// couponsRating = ratingsManager.refreshObject(couponsRating); 

请让我知道,如果我做错了什么。谢谢。

+0

您的refreshObject正在返回传入方法而不是刷新版本的未刷新评分。这可能是为什么更新后没有进行更改。此外,虽然看起来比获取主键和调用find更简单,但该方法中的合并会增加确定更改并将其合并的额外开销。 – Chris 2012-01-03 17:57:04

回答

0

检查ratingsManager是如何存储和重用的。我的猜测是有多个实例,并且每个都存储自己的EntityManager实例。 EntityManager具有一个类似于事务的缓存,所以除非它的实体副本被刷新,否则它不会看到在其他EntityManagers范围内所做的更改。如果是这种情况,您可以尝试调用刷新(修复refreshObject方法以返回刷新的对象,然后重新应用更改),或者在适当的时间从EntityManager中清除/清除实体,以便实体重新加载来自数据库。