<union-subclass> (TABLE_PER_CLASS) ile kimlik sütunu anahtarı oluşturma kullanılamaz


97

com.something.SuperClass:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class SuperClass implements Serializable {
    private static final long serialVersionUID = -695503064509648117L;

    long confirmationCode;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) // Causes exception!!!
    public long getConfirmationCode() {
        return confirmationCode;
    }

    public void setConfirmationCode(long confirmationCode) {
        this.confirmationCode = confirmationCode;
    }
}

com.something.SubClass:

@Entity
public abstract class Subclass extends SuperClass {
    private static final long serialVersionUID = 8623159397061057722L;

    String name;

    @Column(nullable = false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Bana bu istisnayı veriyor:

Caused by: org.hibernate.MappingException: Cannot use identity column key
generation with <union-subclass> mapping for: com.something.SuperClass

Kimlikleri oluşturmanın en iyi ve en uygun yolu nedir? Miras stratejimi değiştirmek istemiyorum.

Yanıtlar:


233

Buradaki sorun, "sınıf başına tablo" kalıtımını ve GenerationType.Auto. MsSQL'de bir kimlik sütunu düşünün. Sütun tabanlıdır. "Sınıf başına tablo" stratejisinde, sınıf başına bir tablo kullanırsınız ve her birinin bir kimliği vardır.

Deneyin:

@GeneratedValue(strategy = GenerationType.TABLE)


2
Mükemmel çözüm. Hibernate forumları bile bu çözüme sahip görünmüyordu ve forum.hibernate.org/…
Spring Monkey

1
Bu sorun yalnızca MySql ile mi yoksa sınıf başına Tablo yaklaşımı için bir videodan birini izlediğim için normal mi ve postgres kullanıldığı için iyi çalışıyordu
Prashant

1
Yakın zamanda bir Dropwizard uygulamasını test ederken bununla karşılaştım. Benim durumumda, oturum fabrikasını oluşturmak için DW tarafından kullanılan aynı yapılandırma seçeneklerini kullandığınızdan emin olarak ele aldım. Bunu düzelten şeyin "hibernate.id.new_generator_mappings" özelliğini true olarak ayarladığından oldukça eminim. Bu DW 0.7.0, Hibernate 4.3.1, DB H2 idi.
sfitts

1
Mükemmel çalışıyor. Ancak, çok sayıda sorguyu tetiklediği (seçme, ekleme ve güncelleme) ve birincil anahtar için benzersiz değerler oluşturmak üzere kilitleri koruduğu için 'TABLE' kimlik oluşturma stratejisinin kullanılmasının tercih edilmemesi şiddetle önerilir. Öyleyse, biraz büyük bir Miras senaryomuz varsa, buna alternatif bir çözüm ne olabilir? Kesinlikle performansı büyük ölçüde etkileyecektir.
MAC

8

Bunun veritabanı diyalektine özgü bir sorun olup olmadığını merak ediyorum, çünkü altta yatan veritabanı olarak PostgreSQL ile bir youtube eğitimini izlerken, videoyu oluşturan kişinin varsayılan @GeneratedValue ile başarılı bir şekilde bir uygulama çalıştırdığını gördüm. Benim durumumda (temeldeki veritabanı MySQL'dir) @GeneratedValue stratejisini tam olarak zoidbeck'in önerdiği gibi GenerationType.TABLE olarak değiştirmek zorunda kaldım.

İşte video: https://www.youtube.com/watch?v=qIdM4KQOtH8


Postgres kalıtım yapabilir, bu nedenle bunun veritabanına özgü olduğu konusunda haklı olabilirsiniz: postgresql.org/docs/8.1/static/ddl-inherit.html Video, şemanın nasıl oluşturulduğunu açıklamıyor (veya kaçırdım). Belki de NHibernate postgres lehçesi bunu kendi başına yapabilir veya bunun yerine 'INHERITS'i manuel olarak eklemeniz gerekir. Aslında söyleyemem.
zoidbeck

6
PostgreSQL'de, Hibernate varsayılan olarak kullanılır GenerationType.SEQUENCE. Bu yüzden orada otomatik olarak çalışır. PostgreSQL'ler ile kesinlikle ilgisi yoktur INHERITS.
Henning

i zaman bir sürü hata ayıklama ben bu yazıyı görene kadar aynı öğretici kullanarak & i MySql.Spent kullanıyorum olarak @Generated soruna neden oldu kullanıyoruz
Deen John

5

Zoidbeck'in cevabına katılıyorum. Stratejiyi şu şekilde değiştirmeniz gerekir:

@GeneratedValue(strategy = GenerationType.TABLE)

Ancak hepsi bu kadar değil, özetinizin tablo birincil anahtar sırasını tutacak yeni bir tablo oluşturmanız gerekir. Eşlemenizi şu şekilde değiştirin:

@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ConfirmationCodeGenerator")
@TableGenerator(table = "SEQUENCES", name = "ConfirmationCodeGenerator")
public long getConfirmationCode() {
   return confirmationCode;
}

Ve veritabanındaki yeni bir tablo aşağıdaki gibi görünmelidir: görüntü açıklamasını buraya girin

Uygulamanızı çalıştırdığınızda, Hibernate sequence_name, varlık adının ( SuperClassbu örnekte) olacağı bir satır ekler ve sequence_next_hi_valuedeğer otomatik olarak artırılır ve tüm alt sınıfların tablolarının yeni kayıtları için kullanılır.


2

Bizim durumumuzda, geliştirme ve üretim için bir PostreSQL veritabanı ve testler için bir bellek içi hsqldb veritabanı kullanıyoruz. Her iki durumda da bir id oluşturmak için bir dizi kullanıyoruz. Görünüşe göre GenerationType.AUTOvarsayılan olarak SEQUENCEpostgres için ayarlanıyor, ancak yerel testlerimizde başarısız oldu (hsqldb için varsayılan olarak başka bir şeye ayarlanması gerekir).

Yani bizim için işe yarayan çözümü açıkça kullanın GenerationType.SEQUENCE.



0

MySQL ve PostgreSQL arasında bir SQL standardı Uyumluluğu vardır. PostgreSQL Postgres, SQL92 / 99'un iyi bir alt kümesini ve bu alt kümelerin bazı nesne yönelimli özelliklerini anlar. Postgres, bildirime dayalı SQL sorguları, alt sorgular, görünümler, çoklu kullanıcı desteği, işlemler, sorgu optimizasyonu, kalıtım ve diziler gibi karmaşık rutinleri ve kuralları yönetebilir. Farklı veritabanlarında veri seçmeyi desteklemez.

MySQL MySQL, temel olarak SQL92'yi kullanır. Sayısız platformda çalışır. Mysql, farklı veritabanlarından tabloları birleştirebilen sorgular oluşturabilir. Hem ANSI hem de ODBC sözdizimini kullanarak hem sol hem de sağ dış birleştirmeleri destekler. Bu sürümden itibaren MySQL 4.1 itibariyle, MySQL alt sorguları işleyecektir. Sürüm 5'ten itibaren desteklenen görünümler.

Ayrıntılı bir açıklama için lütfen ziyaret edin. http://www-css.fnal.gov/dsg/external/freeware/pgsql-vs-mysql.html


Lütfen bu konuda kendinizi kötü hissetmeyin, ancak MySQL ve PostgreSQL karşılaştırmasının konuyla alakasız olduğunu düşünüyorum (Hazırda Bekletme varsayılanları onlar için farklı olsa da).
mrts
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.