请考虑 Spring 中的以下情况(我正在使用 Spring 4.0.0 GA 和 Hibernate 4.3.5 final)。
@Service
@Transactional(readOnly = true, propagation=Propagation.REQUIRED)
public final class ChangePasswordDAO implements ChangePasswordService
{
@PersistenceContext
private EntityManager entityManager;
public void setEntityManager(EntityManager entityManager)
{
this.entityManager = entityManager;
}
@Override
@SuppressWarnings("unchecked")
public String getOldPassword(UserTable userTable)
{
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<String>criteriaQuery=criteriaBuilder.createQuery(String.class);
Root<UserTable> root = criteriaQuery.from(entityManager.getMetamodel().entity(UserTable.class));
criteriaQuery.multiselect(root.get(UserTable_.password));
criteriaQuery.where(criteriaBuilder.equal(root, userTable));
List<String> list = entityManager.createQuery(criteriaQuery).getResultList();
return list!=null&&!list.isEmpty()?list.get(0):null;
}
@Override
@SuppressWarnings("unchecked")
public boolean changePassword(String password, UserTable userTable)
{
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaUpdate<UserTable> criteriaUpdate=criteriaBuilder.createCriteriaUpdate(UserTable.class);
Root<UserTable> root = criteriaUpdate.from(entityManager.getMetamodel().entity(UserTable.class));
criteriaUpdate.set(root.get(UserTable_.password), password);
criteriaUpdate.set(root.get(UserTable_.lastModified), DateTime.now(DateTimeZone.UTC));
criteriaUpdate.where(criteriaBuilder.equal(root, userTable));
return entityManager.createQuery(criteriaUpdate).executeUpdate()>0;
}
}
在这种情况下,我期望以下行
@Transactional(readOnly = false, propagation=Propagation.REQUIRED)
在changePassword()
方法之前,以便@Transactional
可以覆盖类级别的注释。否则,类级别注释使用readOnly = true
也适用于此方法。因此,更新操作不应该发生,因为事务是只读的。
那么在这种情况下 Spring 是如何进行更新操作的呢?