Reputation: 3612
I'm attaching the Spring service (problematic) code below :
@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 code
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;
}
}
}
My requirement is that an entry must go into a job table as soon as the processing initiates(/IMMEDIATE JOB ENTRY/ in the code). After /some time-consuming operation - 2/, I will update the same entry(with an appropriate status). While I read the difference between save() and persist(), my save() still defers the insert till /some time-consuming operation - 2/ which, in turn, reflects an entry very late in the front end.
Please guide me as to where I'm making a blunder.
1st EDIT
In my case, the user submits an operation request which comes to the above service method which is marked @Async - the user must see a page with his request showing 'SUBMITTED' while the operation is still going on in the service method. In this case, shall I use session.flush() or I need to make any code changes?
Upvotes: 3
Views: 8140
Reputation: 691625
save
and persist
, and generally, every operation you do with persistent entities, are deferred until really necessary, to avoid needless roundtrips to the database.
You can make Hibernate write every pending change to the database by using session.flush()
, but that won't make the entity available for the front-end, because the ront-end doesn't use the same transaction to read the data than the one doing the long operation and persisting the entities.
And since transactions run in isolation (with the default isolation being READ_COMMITTED, most of the time), a transaction won't see anything written by another transaction until this other transaction commits to the database.
If you want to se the inserted entity immediately, save it in a separate transaction from the rest of the long-running operation, or change the isolation level to READ_UNCOMMITTED.
Upvotes: 3