3

我在下面附上了 Spring 服务(有问题的)代码:

@Async
    public void performSeismicOperations(Integer sessionUserId,
            int seismicFileId, String seismicFileName, ShClstr targetCluster,
            Collection<String> listOperations, String processedFolderName,
            Map<String, Object[]> args, String userNotes) throws IOException {

            .
            .
            .
            /*some code*/
            .
            .
        Date currentDate = new Date(System.currentTimeMillis());

            /*IMMEDIATE JOB ENTRY*/    
        log.info("Start : Inserting in sh_job to assure user");
        ShJob shJob = new ShJob(user, ClusterConstants.JOB_SUBMITTED,
                currentDate, null, null, null);
        shJobDAO.save(shJob);
        log.info("End : Inserting in sh_job to assure user");

        /*some time-consuming operation - 1*/

        SeismicFiles processedSeismicFile = new SeismicFiles(user,
                processedFolderName, 0, HDFSConstants.PROCESSED, currentDate);
        seismicFilesDAO.persist(processedSeismicFile);

        /*some time-consuming operation - 2*/

        log.info("Start : Updating the Hadoop job id");
        shJob.setShjHadoopJobId(hadoopJobId);
        shJobDAO.attachDirty(shJob);
        log.info("End : Updating the Hadoop job id");

            .
            .
            .
            /*some code*/
            .
            .

        log.info("Returning from SeismicHadoopServiceImpl.performSeismicOperations()");
    }

DAO 代码

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.lnt.seismichadoop.pojo.ShJob;

@Repository
public class ShJobDAO {

    private static final Log log = LogFactory.getLog(ShJobDAO.class);

    @Autowired
    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void persist(ShJob transientInstance) {
        log.debug("persisting ShJob instance");
        try {
            sessionFactory.getCurrentSession().persist(transientInstance);
            log.debug("persist successful");
        } catch (RuntimeException re) {
            log.error("persist failed", re);
            throw re;
        }
    }

    public void save(ShJob transientInstance) {
        log.debug("SAVING ShJob instance");
        try {
            sessionFactory.getCurrentSession().save(transientInstance);
            log.debug("save successful");
        } catch (RuntimeException re) {
            log.error("save failed", re);
            throw re;
        }
    }

    public void attachDirty(ShJob instance) {
        log.debug("attaching dirty ShJob instance");
        try {
            sessionFactory.getCurrentSession().saveOrUpdate(instance);
            log.debug("attach successful");
        } catch (RuntimeException re) {
            log.error("attach failed", re);
            throw re;
        }
    }

    public void attachClean(ShJob instance) {
        log.debug("attaching clean ShJob instance");
        try {
            sessionFactory.getCurrentSession().lock(instance, LockMode.NONE);
            log.debug("attach successful");
        } catch (RuntimeException re) {
            log.error("attach failed", re);
            throw re;
        }
    }

    public void delete(ShJob persistentInstance) {
        log.debug("deleting ShJob instance");
        try {
            sessionFactory.getCurrentSession().delete(persistentInstance);
            log.debug("delete successful");
        } catch (RuntimeException re) {
            log.error("delete failed", re);
            throw re;
        }
    }

    public ShJob merge(ShJob detachedInstance) {
        log.debug("merging ShJob instance");
        try {
            ShJob result = (ShJob) sessionFactory.getCurrentSession().merge(
                    detachedInstance);
            log.debug("merge successful");
            return result;
        } catch (RuntimeException re) {
            log.error("merge failed", re);
            throw re;
        }
    }

    public ShJob findById(java.lang.Integer id) {
        log.debug("getting ShJob instance with id: " + id);
        try {
            ShJob instance = (ShJob) sessionFactory.getCurrentSession().get(
                    "com.lnt.seismic.dao.ShJob", id);
            if (instance == null) {
                log.debug("get successful, no instance found");
            } else {
                log.debug("get successful, instance found");
            }
            return instance;
        } catch (RuntimeException re) {
            log.error("get failed", re);
            throw re;
        }
    }

    public List findByExample(ShJob instance) {
        log.debug("finding ShJob instance by example");
        try {
            List results = sessionFactory.getCurrentSession()
                    .createCriteria("com.lnt.seismic.dao.ShJob")
                    .add(Example.create(instance)).list();
            log.debug("find by example successful, result size: "
                    + results.size());
            return results;
        } catch (RuntimeException re) {
            log.error("find by example failed", re);
            throw re;
        }
    }

    public List<ShJob> findAll() {
        log.debug("finding JobStatus instance by findAll");
        try {
            Query query = sessionFactory.getCurrentSession().createQuery(
                    "from ShJob");
            List<ShJob> results = query.list();
            log.debug("find by findAll successful, result size: "
                    + results.size());
            return results;
        } catch (RuntimeException re) {
            log.error("find by example failed", re);
            throw re;
        }
    }
}

我的要求是,一旦处理开始(/ IMMEDIATE JOB ENTRY /在代码中),条目必须立即进入作业表。在 /一些耗时的操作 - 2 / 之后,我将更新相同的条目(具有适当的状态)。虽然我阅读了 save() 和 persist() 之间的区别,但我的 save() 仍然将插入推迟到 /一些耗时的操作 - 2 / 反过来,这反映了前端很晚的条目。

请指导我在哪里犯了错误。

第一次编辑

在我的例子中,用户提交了一个操作请求,该操作请求来自上述标记为@Async 的服务方法——用户必须看到一个页面,其请求显示为“已提交”,而操作仍在服务方法中进行。在这种情况下,我应该使用 session.flush() 还是需要进行任何代码更改?

4

1 回答 1

3

savepersist,通常情况下,您对持久实体执行的每个操作都会延迟到真正需要时,以避免不必要的数据库往返。

您可以使用 让 Hibernate 将每个挂起的更改写入数据库session.flush(),但这不会使实体可用于前端,因为 ront-end 不使用与执行相同的事务来读取数据长时间操作和持久化实体。

并且由于事务是独立运行的(大多数情况下默认隔离为 READ_COMMITTED),因此在另一个事务提交到数据库之前,一个事务不会看到另一个事务写入的任何内容。

如果您想立即设置插入的实体,请将其保存在与其他长时间运行的操作不同的事务中,或者将隔离级别更改为 READ_UNCOMMITTED。

于 2012-12-20T08:03:08.073 回答