Hazırda Bekleme - Toplu güncelleme, güncellemeden beklenmedik satır sayısı döndürdü: 0 gerçek satır sayısı: 0 bekleniyor: 1


141

Hazırda bekletme hatasını alıyorum. Soruna neden olan işlevi belirleyebiliyorum. Ne yazık ki işlevde birkaç DB çağrısı var. Hazırda bekletme, işlemin sonunda oturumu yıkamak beri soruna neden olan satırı bulamıyorum. Aşağıda belirtilen hazırda bekletme hatası genel bir hataya benzer. Hangi Bean'in soruna neden olduğunu bile söylemiyor. Bu hazırda bekletme hatasına aşina olan var mı?

org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
        at org.hibernate.jdbc.BatchingBatcher.checkRowCount(BatchingBatcher.java:93)
        at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:79)
        at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985)
        at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:333)
        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
        at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransacti
onManager.java:500)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManag
er.java:473)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(Transaction
AspectSupport.java:267)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)

Teşekkür ederim @ Peter Mortensen. E-postamı güncelledim.
Sujee

Aynı problemim var. Çok nadiren gerçekleştiği için bu büyük bir sorun değil. Show_sql kullanmak pratik değildir çünkü bu davranışı yeniden oluşturmak milyonlarca işlem gerektirir. Ancak, bu, bir sistem testi sırasında tekrar tekrar gerçekleştiği için (işlemlerin cenazeleri vardır) Belirli bir neden olduğundan şüpheleniyorum.
daniel_or_else

Ben güncelleme satırlar çalıştık ederken bu sorunla karşılaştı YOK değişiklikleri. Fark yoksa bir şey güncellemeyin.
fifman

Yanıtlar:


62

İşlemleriniz için kod ve eşlemeler olmadan, sorunu araştırmak imkansız olacaktır.

Ancak, soruna neyin neden olduğunu daha iyi ele almak için aşağıdakileri deneyin:

  • Hazırda bekletme yapılandırmanızda, hibernate.show_sql öğesini true olarak ayarlayın. Bu, çalıştırılan ve soruna neden olan SQL'i göstermelidir.
  • İlkbahar ve Hazırda Bekletme için günlük düzeylerini DEBUG olarak ayarlayın, yine bu da soruna hangi satırın neden olduğu hakkında daha iyi bir fikir verecektir.
  • İlkbaharda bir işlem yöneticisi yapılandırmadan sorunu çoğaltan bir birim sınama oluşturun. Bu size rahatsız edici kod satırı hakkında daha iyi bir fikir verecektir.

Umarım yardımcı olur.


21
hibernate.show_sql> Org.hibernate.SQL günlük kategorisini DEBUG olarak ayarlamanızı tavsiye ederim. Bu şekilde, yalnızca günlük kaydı için hazırda bekletme yapılandırmasını değiştirmeniz gerekmez.
Thierry

"Show_sql" kullanımı çok ayrıntılı olabilir ve üretimde uygulanamaz. Bunun için ben sadece sorunu olan bir ifadeye sahip bir ps.toString () ile ifade yazdırmak için BatchingBatcher sınıfının 74 satırında catch yan tümce değiştirdik.
Orden

71

Hiç mevcut olmayan bir id ile kayıt silerken aynı istisnayı yaşadım. Bu nedenle, güncellediğiniz / Sildiğiniz kaydın DB'de gerçekten var olup olmadığını kontrol edin


12
Bu sorunu, bir üst-alt ilişkisinden bir çocuğu kaldırdığımda, üst öğeyi kaydettiğimde (alt öğeyi siler) ve alt öğeyi el ile silmeye çalıştığımda bu sorunu yaşadım.
dave thieben

Bu benim sorunumu çözdü. Kayıt yoktu ve hizmetim aslında createOrUpdateAll () yöntemini çağırmak için gerekliyse updateAll () yöntemini çağırıyordu. Teşekkürler.
Mital Pritmani

3
Peki sorunu nasıl çözebilirim? Bir kayıt alıp silersem; ancak sistem silmeden önce sistemi zaten silerse, başka bir uygulama, istisnamı atar.
Stony

@davethieben, tam da ihtiyacım olan bilgiydi. Ebeveyn-çocuk ilişkisinin silinmeye devam ettiğini fark etmedim.
snowe

Çözüm, satırı kilitlemek için kaydı getirirken select için kullanmaktır, böylece başka hiçbir şey bunu yapmadan önce silemez.
Matthew,

55

Çözüm: id özelliğinin Hazırda Bekleme eşleme dosyasında, herhangi bir jeneratör sınıfı kullanıyorsanız, bu özellik için değeri bir ayarlayıcı yöntemi kullanarak açıkça ayarlamamalısınız.

Id özelliğinin değerini açıkça ayarlarsanız, yukarıdaki hataya yol açar. Bu hatayı önlemek için bunu işaretleyin. veya Eşleme dosyasında alan üreteci = "yerel" veya "artımlı" olarak belirttiğinizde ve DATABASE'inizde eşlenen tablonun auto_incremented olmadığını gösteren hata hatası Çözüm: DATABASE'inize gidin ve auto_increment'ı ayarlamak için tablonuzu güncelleyin


2
Kesinlikle doğru. Bu doğru cevap olmalı. Thanks @ Rēda Biramanē
Verma

1
Ancak , ID değerini '0' olarak ayarlayabilir ve Hazırda Beklet, üzerine
yazmaktan

1
Teşekkürler! Bunun neden en yüksek cevap olmadığından emin değilim.
Stuart McIntyre

18

Bu, bazı nesnelere belirli kimlikler atarken (test) yanlışlıkla bir kez başıma geldi ve sonra bunları veritabanına kaydetmeye çalışıyordum. Sorun, veritabanında nesnelerin kimliklerini ayarlamak için belirli bir politika olmasıydı. Sadece yok sen hazırda düzeyinde bir politika varsa bir kimlik atayın.


15

Benim durumumda, iki benzer durumda bu istisnaya geldim:

  • Açıklamalı bir yöntemde @Transactional başka bir hizmete (uzun yanıt süreleriyle) çağrı yaptım. Yöntem, varlığın bazı özelliklerini günceller (yöntemden sonra varlık hala veritabanında bulunur). Kullanıcı işlem yönteminden ikinci kez çıkarken yöntemden iki kez (ilk kez çalışmadığını düşündüğü gibi) istekte bulunursa, Hazırda Beklet, işlemin başlangıcından durumunu zaten değiştirmiş olan bir varlığı güncellemeye çalışır. Bir durumdaki bir varlığı hazırda bekletme ve aynı varlığı bulma, ancak ilk istekle zaten değiştiğinden, varlığı güncelleyemediğinden bir istisna atar. GIT'de bir çatışma gibi.
  • Bir varlığı (ve birkaç saniye sonra manuel geri alma) güncelleyen otomatik istekler (platformu izlemek için) vardı. Ancak bu platform zaten bir test ekibi tarafından kullanılıyor. Bir test cihazı, otomatik isteklerle aynı varlıkta bir test gerçekleştirdiğinde (milisaniyenin yüzde biri içinde), istisnayı alıyorum. Önceki durumda olduğu gibi, ikinci işlemden çıkarken önceden getirilen varlık zaten değişmiştir.

Sonuç: benim durumumda, kodda bulunabilecek bir sorun değildi. Hibernate, veritabanından ilk getirilen varlığın geçerli işlem sırasında değiştiğini tespit ettiğinde bu istisna atılır , bu nedenle Hibernate varlığın doğru sürümünün hangisi olduğunu bilmediği için veritabanına aktaramaz: başlangıçta işlem getirme; veya veritabanında önceden depolanmış olanı.

Çözüm: Sorunu çözmek için gereksinimlerinize en uygun olanı bulmak için Hibernate LockMode ile oynamanız gerekecektir .


Merhaba, yardımcı cevabınız için teşekkürler. Hatadan kurtulmak için en sonunda hangi LockMode'u kullandığınızı bildirir misiniz? Kullanıcı yanlışlıkla yanlışlıkla iki kez tıklaması nedeniyle bir API milisaniyede art arda vurulduğunda benzer bir sorunla karşılaşıyorum. Kötümser Kilitleme performansı incitir; bu yüzden sonunda ne istediğini bilmek ister misin?
Madhur Bhaiya

1
Sorunu yaşadığımdan beri uzun zaman oldu ve yerine koyduğum kesin çözümü iyi hatırlamıyorum, ama LockMode.READya da LockMode.OPTIMISTIC.
Sergio Lema

13

Bu sorunla yeni karşılaştım ve bir kaydı sildiğimi ve daha sonra Hazırda Bekletme işleminde güncellemeye çalıştığımı öğrendim.


9

Bu, tetikleyicilerin satır sayısını etkileyen ek DML (veri değiştirme) sorguları yürütmesi durumunda ortaya çıkabilir. Benim çözümüm, tetikleyicimin üstüne aşağıdakileri eklemekti:

SET NOCOUNT ON;

1
Bu cevap beni doğru yönde gönderdi. Üzerinde bir tetikleyici olan eski bir veritabanı ile çalışıyordum - Neyse ki tetikleyicinin kod ile ne yaptığını değiştiriyordum, bu yüzden sadece silebilirdim.
S. Baghee

2
+1 Benim sorunum da buydu. Postgresql kullanıyordum, bu yüzden satır sayısı kontrolünü kapatmak için @SQLInsert ek açıklamasını kullanmak gerekiyordu: technology-ebay.de/the-teams/mobile-de/blog/…
s1mm0t


7

Aynı sorunla karşı karşıyaydım. Kod test ortamında çalışıyordu. Ancak evreleme ortamında çalışmıyordu.

org.hibernate.jdbc.BatchedTooManyRowsAffectedException: Batch update returned unexpected row count from update [0]; actual row count: 3; expected: 1

Sorun tablo DB tablo test her birincil anahtar için tek giriş vardı. Ancak DB hazırlamada aynı birincil anahtar için birden fazla giriş vardı. (DB evrelemede sorun, tablonun herhangi bir birincil anahtar kısıtlaması yoktu, ayrıca çoklu giriş vardı.)

Bu yüzden güncelleme işleminde her seferinde başarısız olur. Tek kaydı güncellemeye çalışır ve güncelleme sayısını 1 olarak almayı bekler. Ancak aynı birincil anahtarın tablosunda 3 kayıt olduğundan, sonuç güncelleme sayısı 3'ü bulur. Beklenen güncelleme sayısı ve gerçek sonuç güncelleme sayısı eşleşmediğinden , İstisna atar ve geri alır.

Sonra birincil anahtar yinelenen ve birincil anahtar kısıtlamaları eklenen tüm kayıtları kaldırıldı. İyi çalışıyor.

Hibernate - Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1

gerçek satır sayısı: 0 // güncelleme
güncellenecek kayıt bulunamadı anlamına gelir: 0 // kayıt bulunamadı anlamına gelir, bu nedenle güncelleme
beklenmez: 1 // db tablosundaki anahtarla en az 1 kayıt beklendiği anlamına gelir.

Burada sorun, bazı anahtarlar için bir kaydı güncellemeye çalışan sorgudur, ancak hazırda bekletme anahtarla herhangi bir kayıt bulamadı.


Merhaba @ParagFlume, ben aynı hatayı aldım "Toplu güncelleme güncelleme gelen beklenmedik satır sayısını döndürdü: 0 gerçek satır sayısı: 0 beklenen: 1" benim veritabanından bir nesne seçmeye çalıştığınızda sorun sadece herhangi bir üretim var mı, herhangi bir var mı Bu sorunun nasıl çözüleceğine dair fikir, kritik bir durumdayım. Saygılarımızla !
James

Sorgu db herhangi bir kayıt bulamadığını düşünüyorum, o güncelleştirmeye çalıştığı db bir kayıt bulmayı bekliyor. db'de kayıt gerçekten varsa manuel olarak / sorgu tarayıcısını kontrol edebilirsiniz.
ParagFlume

Evet kayıt var, ama benim sorunum hazırda bekleme neden güncelleştirmek deneyin, ben sadece veritabanından nesneyi almak için bir seçme hizmeti kullanıyorum!
James

belki nesnelerin durumunu değiştirmeye çalışıyorsunuzdur. ve oturum hala açık.
ParagFlume

Bu davranışı nasıl kontrol edebilirim, çünkü hizmeti geliştiren kişi değilim ...
James

5

Julius'un dediği gibi , çocuklarının silinmesini sağlayan bir Nesnede bir güncelleme gerçekleşir. (Muhtemelen tüm Baba Nesnesi için bir güncelleme gerektiğinden ve bazen çocukları silmeyi ve onları babanın herhangi bir güncellemesinde yapabileceği diğer güncellemelerle birlikte yeniden Baba'ya (yeni, eski önemli değil) yerleştirmeyi tercih ederiz. Diğer düz alanlar) Yani ... bunun çalışması için (İşlem dahilinde) çocukları silin (Çocuklar arasında childrenList.clear()döngü yapmayın ve her birini bir miktar childDAO.delete(childrenList.get(i).delete()))ve ayar ile silin)@OneToMany(cascade = CascadeType.XXX ,orphanRemoval=true)Baba Nesnesi tarafında. Sonra babayı güncelleyin (fatherDAO.update (father)). (Her baba nesnesi için tekrarlayın) Sonuç, çocukların babalarıyla olan bağlantılarının kaldırılması ve daha sonra çerçeve tarafından yetim olarak kaldırılmasıdır.


5

Bir-çok ilişkimizin olduğu bu problemle karşılaştım.

Master için hazırda bekleme hbm eşleme dosyasına, küme tipi düzenlemesi olan nesne için, eklendi cascade="save-update" ve iyi çalıştı.

Bu olmadan, varsayılan olarak hazırda bekletme özelliği varolmayan bir kaydı güncellemeye çalışır ve bunu yaparak ekler.


4

UPDATEBir PRIMARY KEY'e çalıştığınızda da olabilir .


3

Aynı sorunu var ve bu Otomatik artış birincil anahtar nedeniyle oluşabileceğini doğruladı. Bu sorunu çözmek için, veri kümesi ile otomatik artış değerini girmeyin. Birincil anahtar olmadan veri ekleyin.


3

Bu hatayı almanın başka bir yolu, koleksiyonda boş bir öğeniz varsa.


2

aynı nesneyi silmeye çalıştığınızda ve aynı nesneyi yeniden güncelleştirmeye çalıştığınızda silin

session.clear ();


2

Bu benim de oldu, çünkü Long olarak kimliğimi aldım ve görünümden 0 değerini alıyordum ve veritabanına kaydetmeye çalıştığımda bu hatayı aldım, sonra kimliği null olarak ayarlayarak düzelttim.


1

Manuel olarak başlarken ve açıklamalı yöntem içinde işlemleri gerçekleştirirken bu sorunla karşılaştım @Transactional. Aktif bir işlemin olup olmadığını tespit ederek sorunu çözdüm.

//Detect underlying transaction
if (session.getTransaction() != null && session.getTransaction().isActive()) {
    myTransaction = session.getTransaction();
    preExistingTransaction = true;
} else {
    myTransaction = session.beginTransaction();
}

Sonra Spring'in işlemi yapmasına izin verdim.

private void finishTransaction() {
    if (!preExistingTransaction) {
        try {
            tx.commit();
        } catch (HibernateException he) {
            if (tx != null) {
                tx.rollback();
            }
            log.error(he);
        } finally {
            if (newSessionOpened) {
                SessionFactoryUtils.closeSession(session);
                newSessionOpened = false;
                maxResults = 0;
            }
        }
    }
}

1

Bu, JSF Yönetilen Fasulye olarak

@RequestScoped;

ne zaman ilan etmelisin

@SessionScoped;

Saygılarımızla;


1

Veritabanında olmayan bir kimliği olan bir nesneyi güncellemeye çalıştığımda bu hatayı aldım. Hatamın nedeni, nesnenin istemci tarafı JSON-temsiline manuel olarak 'id' adında bir özellik atamıştım ve sonra sunucu tarafında nesneyi serileştirirken bu 'id' özelliği örnek değişkeninin üzerine yazacaktı ( Hibernate'in oluşturması gereken "id" de denir). Tanımlayıcılar oluşturmak için Hazırda Bekletme modunu kullanıyorsanız, çarpışmaları adlandırırken dikkatli olun.


1

Ben de aynı zorlukla karşılaştım. Benim durumumda, var olmayan bir nesneyi bilehibernateTemplate .

Aslında benim uygulama güncellemek için bir DB nesnesi alıyordu. Ve değerlerini güncellerken, kimliğini yanlışlıkla güncelledim ve güncellemeye devam ettim ve bahsedilen hatayla karşılaştım.

hibernateTemplateCRUD operasyonları için kullanıyorum .


1

Tüm cevapları okuduktan sonra, kış uykusunun ters özelliği hakkında konuşacak kimse bulamadı.

Benim düşünceme göre, ilişkiler eşlemenizde ayrıca ters anahtar kelimenin uygun şekilde ayarlanıp ayarlanmadığını . Ters sürdürmek için hangi tarafın sahibi olduğunu tanımlamak için anahtar kelime oluşturulur. Güncelleme ve ekleme prosedürü, bu özelliğe göre değişir.

Diyelim ki iki masamız var:

principal_table , middle_table

bir-çok ilişkisi var . Hazırda bekleme haritalama sınıfları Asıl ve Orta sırasıyla.

Yani asıl sınıfın bir orta seti var nesneler . XML eşleme dosyası aşağıdaki gibi olmalıdır:

<hibernate-mapping>
    <class name="path.to.class.Principal" table="principal_table" ...>
    ...
    <set name="middleObjects" table="middle_table" inverse="true" fetch="select">
        <key>
            <column name="PRINCIPAL_ID" not-null="true" />
        </key>
        <one-to-many class="path.to.class.Middel" />
    </set>
    ...

Ters "true" olarak ayarlandığından, "Middle" sınıfı ilişki sahibi demektir, bu nedenle Principal sınıfı ilişkiyi GÜNCELLEMEZ .

Dolayısıyla güncelleme prosedürü şu şekilde uygulanabilir:

session.beginTransaction();

Principal principal = new Principal();
principal.setSomething("1");
principal.setSomethingElse("2");


Middle middleObject = new Middle();
middleObject.setSomething("1");

middleObject.setPrincipal(principal);
principal.getMiddleObjects().add(middleObject);

session.saveOrUpdate(principal);
session.saveOrUpdate(middleObject); // NOTICE: you will need to save it manually

session.getTransaction().commit();

Bu benim için çalıştı, ancak çözümü geliştirmek için bazı sürümler önerebilirsiniz. Bu şekilde hepimiz öğreneceğiz.


1

Bizim durumumuzda sonunda StaleStateException'ın temel nedenini bulduk.

Aslında tek bir hazırda bekletme oturumunda satırı iki kez siliyorduk. Daha önce ojdbc6 lib kullanıyorduk ve bu sürümde bu iyiydi.

Ancak odjc7 veya ojdbc8'e yükselttiğimizde, kayıtların iki kez silinmesi istisna oluşturuyordu. Kodumuzda iki kez sildiğimiz bir hata vardı, ancak ojdbc6'da belirgin değildi.

Bu kod parçasıyla çoğaltabildik:

Detail detail = getDetail(Long.valueOf(1396451));
session.delete(detail);
session.flush();
session.delete(detail);
session.flush();

İlk floş hibernate gider ve veritabanında değişiklikler yapar. 2. yıkama sırasında, oturumun nesnesini gerçek tablonun kaydıyla karşılaştırır, ancak bir tane bulamadı, bu nedenle istisna.


1

Bu sorun, daha çok çalışan bir oturum tarafından belleğe zaten getirilmiş olan nesneyi kaydetmeye veya güncellemeye çalıştığımızda oluşur. Oturumdan nesne getirdiyseniz ve veritabanında güncelleme yapmaya çalışıyorsanız, bu istisna atılabilir.

Session.evict () yöntemini kullandım; Hazırda bekletme modunda saklanan önbelleği kaldırmak için veya veri kaybetme riskini almak istemiyorsanız, veri sıcaklığını depolamak için başka bir nesne daha iyi yaparsınız.

     try
    {
        if(!session.isOpen())
        {
            session=EmployeyDao.getSessionFactory().openSession();
        }
            tx=session.beginTransaction();

        session.evict(e);
        session.saveOrUpdate(e);
        tx.commit();;
        EmployeyDao.shutDown(session);
    }
    catch(HibernateException exc)
    {
        exc.printStackTrace();
        tx.rollback();
    }

1

Hazırda Bekletme 5.4.1 ve HHH-12878 sorunu

Hazırda Bekletme 5.4.1'den önce, iyimser kilitleme hatası istisnaları (örneğin StaleStateExceptionveya OptimisticLockException) başarısız ifadesini içermiyordu.

HHH-12878 iyimser bir kilitleme durum atma sırasında, JDBC, böylece sorunu Hibernate iyileştirmek için oluşturuldu PreparedStatementuygulaması sıra günlüğe kaydedilir:

if ( expectedRowCount > rowCount ) {
    throw new StaleStateException(
            "Batch update returned unexpected row count from update ["
                    + batchPosition + "]; actual row count: " + rowCount
                    + "; expected: " + expectedRowCount + "; statement executed: "
                    + statement
    );
}

Test Süresi

BatchingOptimisticLockingTestYeni davranışın nasıl çalıştığını göstermek için Yüksek Performanslı Java Kalıcılığı GitHub veri havuzumda oluşturdum .

İlk olarak, Postbir @Versionmülkü tanımlayan bir varlık tanımlayacağız , böylece örtük iyimser kilitleme mekanizmasını etkinleştireceğiz :

@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    private String title;

    @Version
    private short version;

    public Long getId() {
        return id;
    }

    public Post setId(Long id) {
        this.id = id;
        return this;
    }

    public String getTitle() {
        return title;
    }

    public Post setTitle(String title) {
        this.title = title;
        return this;
    }

    public short getVersion() {
        return version;
    }
}

JDBC toplu işini aşağıdaki 3 yapılandırma özelliğini kullanarak etkinleştireceğiz:

properties.put("hibernate.jdbc.batch_size", "5");
properties.put("hibernate.order_inserts", "true");
properties.put("hibernate.order_updates", "true");

3 Postvarlık oluşturacağız :

doInJPA(entityManager -> {
    for (int i = 1; i <= 3; i++) {
        entityManager.persist(
            new Post()
                .setTitle(String.format("Post no. %d", i))
        );
    }
});

Hazırda Bekletme, bir JDBC toplu ekini yürütür:

SELECT nextval ('hibernate_sequence')
SELECT nextval ('hibernate_sequence')
SELECT nextval ('hibernate_sequence')

Query: [
    INSERT INTO post (title, version, id) 
    VALUES (?, ?, ?)
], 
Params:[
    (Post no. 1, 0, 1), 
    (Post no. 2, 0, 2), 
    (Post no. 3, 0, 3)
]

Yani, JDBC harmanlamanın gayet iyi çalıştığını biliyoruz.

Şimdi iyimser kilitleme sorununu çoğaltalım:

doInJPA(entityManager -> {
    List<Post> posts = entityManager.createQuery("""
        select p 
        from Post p
        """, Post.class)
    .getResultList();

    posts.forEach(
        post -> post.setTitle(
            post.getTitle() + " - 2nd edition"
        )
    );

    executeSync(
        () -> doInJPA(_entityManager -> {
            Post post = _entityManager.createQuery("""
                select p 
                from Post p
                order by p.id
                """, Post.class)
            .setMaxResults(1)
            .getSingleResult();

            post.setTitle(post.getTitle() + " - corrected");
        })
    );
});

İlk işlem tüm Postvarlıkları seçer ve titleözellikleri değiştirir .

Bununla birlikte, birincisi EntityManageryıkanmadan önce , executeSyncyöntemi kullanarak ikinci bir geçiş gerçekleştireceğiz .

İkinci işlem ilk işlemi değiştirir Post, bu nedenle versionartırılacaktır:

Query:[
    UPDATE 
        post 
    SET 
        title = ?, 
        version = ? 
    WHERE 
        id = ? AND 
        version = ?
], 
Params:[
    ('Post no. 1 - corrected', 1, 1, 0)
]

İlk işlem temizlemek çalıştığında Şimdi, EntityManagerbiz alacak OptimisticLockException:

Query:[
    UPDATE 
        post 
    SET 
        title = ?, 
        version = ? 
    WHERE 
        id = ? AND 
        version = ?
], 
Params:[
    ('Post no. 1 - 2nd edition', 1, 1, 0), 
    ('Post no. 2 - 2nd edition', 1, 2, 0), 
    ('Post no. 3 - 2nd edition', 1, 3, 0)
]

o.h.e.j.b.i.AbstractBatchImpl - HHH000010: On release of batch it still contained JDBC statements

o.h.e.j.b.i.BatchingBatch - HHH000315: Exception executing batch [
    org.hibernate.StaleStateException: 
    Batch update returned unexpected row count from update [0]; 
    actual row count: 0; 
    expected: 1; 
    statement executed: 
        PgPreparedStatement [
            update post set title='Post no. 3 - 2nd edition', version=1 where id=3 and version=0
        ]
], 
SQL: update post set title=?, version=? where id=? and version=?

Bu nedenle, bu geliştirmeden yararlanmak için Hazırda Bekletme 5.4.1 veya daha yeni bir sürüme geçmeniz gerekir.


0

Bu, yerel sql sorgusu kullanarak veri kümesindeki bir şeyi değiştirirseniz, ancak aynı veri kümesi için kalıcı nesne oturum önbelleğinde varsa oluşur. Session.evict (yourObject) kullanın;



0

Davalardan biri

SessionFactory sf=new Configuration().configure().buildSessionFactory();
Session session=sf.openSession();

UserDetails user=new UserDetails();

session.beginTransaction();
user.setUserName("update user agian");
user.setUserId(12);
session.saveOrUpdate(user);
session.getTransaction().commit();
System.out.println("user::"+user.getUserName());

sf.close();

0

Bu istisnayla karşı karşıyaydım ve hazırda bekletme iyi çalışıyordu. PgAdmin kullanarak manuel olarak bir kayıt eklemeye çalıştım, burada sorun netleşti. SQL ekleme sorgusu 0 ekleme döndürür. ve null döndürdüğü için bu soruna neden olan bir tetikleyici işlevi vardır. bu yüzden sadece yeni dönecek şekilde ayarlamam gerekiyor. ve sonunda sorunu çözdüm.

herhangi bir vücuda yardımcı olacağını umuyoruz.


0

Yanlışlıkla IDsütunu kullanarak eşledim çünkü bu hatayı aldımId(x => x.Id, "id").GeneratedBy.**Assigned**();

Sorun, kullanılarak çözüldü Id(x => x.Id, "id").GeneratedBy.**Identity**();


0

Bu benim başıma geliyor çünkü fasulye sınıfında kimlik beyanını kaçırıyorum.


0

Benim durumumda, Depolanan Procs'tan biri yüksek DB yanıt sürelerine neden olan tüm CPU'yu tüketirken Veritabanı ile ilgili bir sorun vardı. Bu öldürüldüğünde sorun çözüldü.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.