1

我正在使用 Spring MVC + Hibernate

//Class for Generic Methods for **save and update** 

@Service("PersistenceTemplate")
@Transactional
public class PersistenceTemplate {

@Resource(name = "sessionFactory")
private SessionFactory sessionFactory;

// SAVE 
public <T> long save(T entity) throws DataAccessException {
    Session session = sessionFactory.getCurrentSession();
    long getGenVal=(Long) session.save(entity);
    return getGenVal;
}
//UPDATE
public <T> void update(T entity) throws DataAccessException {
    sessionFactory.getCurrentSession().update(entity);
}

}

AT控制器

@Resource(name = "PersistenceTemplate")
private PersistenceTemplate pt;
long result=pt.save(receiveTrxObj1);
pt.Update(receiveTrxObj2);

问题陈述

如果更新无法更新数据库中的实体,如何回滚保存语句?

4

3 回答 3

0

为了在更新失败时能够回滚保存,保存和更新必须发生在同一个事务中。服务是放置需要在同一事务中执行的 DAO 调用的自然场所。

在控制器方法上放置 @Transactional 注释会由于代理控制器而产生复杂性,请参阅Spring MVC 文档,17.3.2:

当应用需要为控制器对象创建代理的功能(例如@Transactional 方法)时,使用带注释的控制器类时会发生一个常见的陷阱。通常您会为控制器引入一个接口,以便使用 JDK 动态代理。要完成这项工作,您必须将@RequestMapping 注释以及任何其他类型和方法级别的注释(例如@ModelAttribute、@InitBinder)移动到接口以及映射机制只能“看到”由代理人。或者,您可以在配置中为应用于控制器的功能激活 proxy-target-class="true"(在我们的事务场景中)。这样做表明应该使用基于 CGLIB 的子类代理而不是基于接口的 JDK 代理。

请参阅此问题以了解服务中的内容而不是控制器中的内容。

于 2013-08-26T15:36:22.087 回答
0

首先你的 @Service("PersistenceTemplate") 应该被标记为 @Repository 因为它做 DAO 层的工作。

从控制器中,您应该调用一个服务,该服务应该使用@service 和@Transactional 进行注释,并在此服务中创建一个将调用 DAO 层的方法。

如果 save 或 Update 未能更新数据库中的实体,则调用它的方法(即服务层中的方法)将不会完成,并且事务将自动取消,因为持久性对象在接近完成时与数据库同步一旦控制权回到它,服务层的方法。

请参见下面的示例。

@Service("authorLoadService")
@Transactional
@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS,value="request")
public class AuthorEntityLoadService implements EntitiesLoadService{

    private AuthorDAO authorDao;//this is my DAO





    @Autowired
    @Qualifier("authorDAO")
    public void setAuthorDao(AuthorDAO authorDao) {
        this.authorDao = authorDao;
    }

    @Override
    public void deleteEntities(Object o) {
        // TODO Auto-generated method stub

    }

    @Override
    public void loadEntities(Object o) {
        Set<author_pojo> author=(Set<author_pojo>)o;
        Iterator<author_pojo> itr=author.iterator();

        while (itr.hasNext()) {
            author_pojo authorPojo = (author_pojo) itr.next();
            authorDao.save(authorPojo);

        }


    }

    @Override
    @Transactional(readOnly=true)
    public List getEntities() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    @Transactional(readOnly=true)
    public Object getEntity(Object o) {
        String author=(String)o;
    author_pojo fetAuthor=authorDao.findOneByName(author);

        return fetAuthor;
    }

}

我的抽象通用 DAO

public abstract class AbstractHibernateDAO<T extends Serializable> {

    public Class<T> clazz;//class object reference

    protected SessionFactory mysessionFactory;


    @Autowired
    public void setMysessionFactory(SessionFactory mysessionFactory) {
        this.mysessionFactory = mysessionFactory;
    }

    public T findOneByName(final String name){

        return (T) getCurrentSession().createQuery("from "+clazz.getName()).uniqueResult();
    }


    public void setClazz(final Class<T> clazzToSet) {
        this.clazz = clazzToSet;
    }

    public T findOne(final Long id) {
        return (T) getCurrentSession().get(clazz, id);
    }

    @SuppressWarnings("unchecked")
    public List<T> findAll() {
        return getCurrentSession().createQuery("from " + clazz.getName()).list();
    }

    public void save(final T entity) {
        getCurrentSession().merge(entity);
    }

    public void update(final T entity) {
        getCurrentSession().update(entity);
    }

    public void delete(final T entity) {
        getCurrentSession().delete(entity);
    }

    public void deleteById(final Long entityId) {
        final T entity = findOne(entityId);
        delete(entity);
    }

    protected Session getCurrentSession() {

        return mysessionFactory.getCurrentSession();
    }
}

我具体的 DAO

@Repository("authorDAO")
@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS,value="request")
public class AuthorDAO extends AbstractHibernateDAO<author_pojo> {

    public AuthorDAO() {

        setClazz(author_pojo.class);
    }

    public author_pojo findOneByName(final String name){
        System.out.println(clazz);
        return (author_pojo) getCurrentSession().createQuery("from "+clazz.getName() +" where authorName=:name").setParameter("name", name).uniqueResult();
    }



}
于 2013-08-26T18:37:46.017 回答
0

您可以使用应用程序级异常来回滚您的实体操作。当这个自定义异常抛出相关操作回滚。请参阅以下文档以了解如何在 Spring中定义自定义回滚。

于 2013-08-26T15:27:26.737 回答