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 / これにより、フロントエンドの非常に遅いエントリが反映されます。

私がどこで大失敗をしているのか、私を導いてください。

1回目の編集

私の場合、ユーザーは、@Async とマークされた上記のサービス メソッドに送信される操作要求を送信します。ユーザーは、操作がまだサービス メソッドで実行されている間に、要求が「SUBMITTED」と表示されているページを表示する必要があります。この場合、session.flush() を使用するか、コードを変更する必要がありますか?

4

1 に答える 1

3

saveおよびpersist、一般に、永続エンティティで行うすべての操作は、データベースへの不要なラウンドトリップを避けるために、本当に必要になるまで延期されます。

を使用して Hibernate にすべての保留中の変更をデータベースに書き込むようにさせることができsession.flush()ますが、フロントエンドでエンティティを使用できるようにはなりません。長い操作とエンティティの永続化。

また、トランザクションは分離して実行されるため (ほとんどの場合、デフォルトの分離は READ_COMMITTED になっています)、トランザクションは、別のトランザクションがデータベースにコミットするまで、別のトランザクションによって書き込まれたものを認識しません。

挿入されたエンティティをすぐに使用する場合は、実行時間の長い操作の残りの部分とは別のトランザクションに保存するか、分離レベルを READ_UNCOMMITTED に変更します。

于 2012-12-20T08:03:08.073 に答える