java - Hibernate concurrency(?) issue when reading/updating -


situation:

we have webapp (java ee-spring-hibernate) generates pdf barcode. barcode contains id generated @ runtime. have java service uses hibernate check if there's id current date, if none exists, entry created. if 1 exists incremented , updated. there 1 row per day containing following fields: id, coverpageid, date

so when user creates first barcode of day, row added current date coverpageid=1. subsequent barcodes last id database, increment , save row incremented value.

problem:

when multiple users creating pdf's @ same time, hibernate fetch same value both users resulting in same barcode on pdfs.

tried solution:

the code fetches current id, increments , updates row executed in same method. method inside spring bean. since spring beans singletons tried making method synchronized. did not help.

method:

@transactional(isolation=isolation.serializable) public synchronized long getnextid(date date) {     list<coverpageid> allcoverpageids = this.getallcurrentids(date);      if(allcoverpageids.size() == 0)     {         loggingservice.warn(string.format("found no existing id date '%td', creating new record", date));         system.out.println(string.format("found no existing id date '%td', creating new record", date));         return this.createnewcoverpageidrecord(new date());     }     else if(allcoverpageids.size() == 1)     {         coverpageid coverpageid = allcoverpageids.get(0);         loggingservice.debug(string.format("found existing id date '%td': %d, incrementing , persisting", date, coverpageid.getcoverpageid()));         system.out.println(string.format("found existing id date '%td': %d, incrementing , persisting", date, coverpageid.getcoverpageid()));         coverpageid.setcoverpageid(coverpageid.getcoverpageid() + 1);         dao.save(coverpageid);         loggingservice.debug(string.format("saved existing id date '%td' incremented id: %d", date, coverpageid.getcoverpageid()));         return coverpageid.getcoverpageid();     }     else     {         loggingservice.warn(string.format("found multiple records date '%td'", date));         return -1;     } }  private list<coverpageid> getallcurrentids(date date) {     string exclause = "where date = :date";     map<string, object> values = new hashmap<string, object>();     values.put("date", date);     return dao.getallex(coverpageid.class, exclause, values); }  private long createnewcoverpageidrecord(date date) {     dao.save(new coverpageid(new date(), new long(1)));     return 1; } 

coverpageid.class (entity barcode):

@namedqueries({ @namedquery(     name = "getcoverpageidfordate",     query = "from coverpageid c c.date = :date",     readonly = true )}) @entity public class coverpageid { private long id; private date date; private long coverpageid;  public coverpageid() {}  public coverpageid(date date, long coverpageid) {     this.date = date;     this.coverpageid = coverpageid; }  public void setid(long id) {     this.id = id; }  @id @generatedvalue(strategy=generationtype.auto) public long getid() {     return id; }  @temporal(temporaltype.date) public date getdate() {     return date; }  public void setdate(date date) {     this.date = date; }  public long getcoverpageid() {     return coverpageid; }  public void setcoverpageid(long coverpageid) {     this.coverpageid = coverpageid; } } 

does have other idea how can prevent concurrency issue happening?

i believe has nothing hibernate. not using hibernate still face such problem.

there choices you:

consider not using hibernate related parts. many db has facilities atomic "insert-if-absent-update-if-exists" kind of logic.

or

if want use hibernate, here need:

  1. make sure have unique constraint in db avoid duplicated records
  2. in program logic, if found there no record , try insert, prepare catch exception of duplicated data/constraint violation. in such case, don't treat logic failed. subsequent update instead.

with respect tried solution using object instance handling insert/update action, way not going work.

first, if keep ids state of bean, , if application have process, going work. code going db check everytime, , insert/update accordingly. piece of code synchronized, not going work. please remember among different db sessions, changes of 1 session visible other when transaction committed. have situation this

thread 1                    thread 2 ------------------------------------------------- enter method check db, no record found   enter method (wait coz synchronized) insert record exit method                             check db, no record found (coz prev txn not commited yet)                             insert record                             exit method commit                             commit 

see? still facing same issue.

there other way solve apart mine, @ least, way using not going help.


Comments

Popular posts from this blog

ruby - Trying to change last to "x"s to 23 -

jquery - Clone last and append item to closest class -

c - Unrecognised emulation mode: elf_i386 on MinGW32 -