Grails/Hibernate: Versiyalashda null Pointer istisnosi

Grails-da eski kodlar bazasi bilan ishlash. Ba'zi sharoitlarda (aniq nimasi noma'lum) biz findBy ni bajarayotganda sirli NPE, quyida ko'rsatilgan stek iziga ega bo'lamiz.

Hozircha biz qandaydir tiqilib qolganmiz; Bu Kutish rejimi uchun bir nechta forumlarda paydo bo'ladi, ammo javoblar "sizning sxemangizda nimadir noto'g'ri" deganga o'xshaydi. Muammoni kuzatishimizga yordam beradigan qo'shimcha tafsilotlarni topsangiz ajoyib bo'lardi.

Yangilanish

Javobingiz uchun rahmat. Ha, bu NPE sodir bo'lganda, version null bo'lishi aniq. Muammo shundaki, biz uni kodda ko'rib chiqsak, u yo'q null.

Biz ip bilan bog'liq muammo borligiga shubha qila boshladik.

Caused by: java.lang.NullPointerException
    at org.hibernate.type.LongType.next(LongType.java:79)
    at org.hibernate.engine.Versioning.increment(Versioning.java:131)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.getNextVersion(DefaultFlushEntityEventListener.java:387)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:279)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:151)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
    at org.codehaus.groovy.grails.plugins.quartz.listeners.SessionBinderJobListener.jobWasExecuted(SessionBinderJobListener.java:58)
    at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1910)

person Charlie Martin    schedule 09.09.2010    source manba
comment
Albatta, menda barcha tafsilotlar yo'q, lekin ... qanday qilib ip bilan bog'liq muammo biror narsani bekor qilishi mumkin? Null versiya ustuniga ega yozuv butunlay chiqarib tashlandimi?   -  person Pascal Thivent    schedule 11.09.2010
comment
Oh, yo'q, aksincha: o'sha paytda versiya ustuni null ekanligi aniq. nima uchunni tushunish qiyin, chunki atrofdagi kodda bu ko'rinmaydi. Bizda ip bilan bog'liq muammo borligini tasdiqladik, chunki biz uni bitta ipga majbur qildik va NPE ni olishni to'xtatdik. Haligacha ildiz sababini tushunmayapman, 'tho.   -  person Charlie Martin    schedule 11.09.2010


Javoblar (4)


Mana mening iz haqidagi tushuncham:

  • siz yoki biror narsa findBy qilasiz
  • bu tetiklaydi flush
  • seans yangilanishi kerak bo'lgan versiya maydoniga ega (Long turdagi) iflos ob'ektni o'z ichiga oladi
  • Hibernate yangilanish uchun versiya maydoni uchun keyingi qiymatni olishga harakat qiladi
  • va bu erda siz NPE olasiz

org.hibernate.engine.Versioning.increment(Versioning.java:131) ning tanasi:

public static Object increment(Object version, VersionType versionType, SessionImplementor session) {
    Object next = versionType.next( version, session ); // line 131
    if ( log.isTraceEnabled() ) {
        log.trace(
                "Incrementing: " +
                versionType.toLoggableString( version, session.getFactory() ) +
                " to " +
                versionType.toLoggableString( next, session.getFactory() )
        );
    }
    return next;
}

Va org.hibernate.type.LongType.next(LongType.java:79) tanasi (yuqoridagi versionType.next bajarilishini ta'minlaydi):

public Object next(Object current, SessionImplementor session) {
    return new Long( ( (Long) current ).longValue() + 1 ); // line 79
}

increment ga o'tkazilgan version null ekanligi aniq ko'rinadi.

Shunday qilib, ma'lumotlar bazasida uning versiya ustunida NULL qiymati bo'lgan yozuvni qidiraman. SQL jurnalini faollashtirish qidiruvni qisqartirishga yordam beradi.

person Pascal Thivent    schedule 10.09.2010

Menda ham xuddi shunday muammo bor edi. Bu eski ma'lumotlar bazasi yozuvlari bilan bog'liq muammo. Siz maʼlumotlar bazasi jadvaliga versiya ustunini va VOʼda @Version izohini qoʻshdingiz va u oʻsha oʻzgarishlardan soʻng yaratilgan yangi obʼyektlar uchun yaxshi ishlaydi, biroq eski obyektlar uchun u bajarilmaydi – bu ustundagi qiymat null. Yechim barcha eski ob'ektlarni yangilashdir - ularning versiya ustuni 0 (yoki ma'lumotlar turiga qarab boshqa qiymat). Umid qilamanki, bu yordam beradi.

person BlueLettuce16    schedule 12.01.2012
comment
Bu men uchun ishladi. Men allaqachon mavjud ob'ektlar uchun @Version qo'shdim, ularning hammasini yangilashim va versiya = 0 o'rnatishim kerak edi. Hozir yaxshi ishlaydi. - person kospol; 30.07.2013

@Version
@Column(name = "xxx")
private Integer xxx;

VO'ngizda @Version izohini toping va ushbu ustunni ma'lumotlar bazasida standart qiymatga o'rnating;

person qiulvelu    schedule 27.02.2018
comment
Ma'lum bo'ldiki (uzoq vaqt o'tdi) bu aslida parallellik muammosi bo'lib, ikkita ip bir xil yozuv bilan aralashib ketgan. - person Charlie Martin; 28.02.2018

<version name="versionID" type="java.lang.Long" unsaved-value="null">
  <column name="version" precision="10" scale="0"/>
</version>

unsaved-value="null" ni olib tashlang yoki unsved-value="null" ni qo'shing.

person Ravi Parekh    schedule 26.02.2011