/ / Automatyczne generowanie kluczy Hibernacja za pomocą MySQL i Oracle - Java, MySQL, Oracle, Hibernacja, JPA

Automatyczne generowanie klucza Hibernate z MySQL i Oracle - java, mysql, oracle, hibernate, jpa

Pracuję nad Jawa aplikacja, która powinna wykonywać operacje CRUD (przy użyciu Hibernować 4.3.8) w dwóch różnych bazach danych z tym samym schematem bazy danych. Tam jest MySQL (wersja 5.1.73) i an Wyrocznia (11g Express Edition Release 11.2.0.2.0 - 64bit) baza danych.

Klasy Java z Adnotacje WZP zostały wygenerowane z tabel bazy danych z generowaniem kodu hibernacji.

Problem polega na tym, że musimy teraz korzystać z automatycznego generowania klucza podstawowego, a MySQL używa GenerationType.IDENTITY i Oracle używa GenerationType.SEQUENCE. Ponadto w rzadkich przypadkach potrzebujemy możliwości samodzielnego ręcznego ustawienia klucza podstawowego.

Kod followig w klasie z adnotacjami działa z automatycznym generowaniem klucza dla obu baz danych, ale kończy się niepowodzeniem, jeśli klucz podstawowy jest ustawiony samodzielnie.

@GeneratedValue(strategy=GenerationType.AUTO, generator="sequence_generator")
@SequenceGenerator(name="sequence_generator", sequenceName="SEQUENCE1")
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}

Bez @GeneratedValue i @SequenceGenerator adnotacje można ustawić klucz podstawowy ręcznie, ale automatyczne generowanie nie działa.

Odpowiedzi:

9 dla odpowiedzi № 1

Nawet jeśli używałeś GenerationType.AUTO bez żadnego parametru specyficznego dla SEKWENCJI nie można zapisać przypisanych identyfikatorów.

Istnieją pewne obejścia, jeśli chcesz dokonać kompromisu:

  1. Jednym ze sposobów byłoby przejście na przypisane identyfikatory. Możesz użyć UUID identyfikatory, które działają zarówno dla MySQL, jak i Oracle, a także można przypisywać wartości ręcznie.

  2. Innym sposobem jest użycie niestandardowego generatora tabel.

    Najpierw zdefiniuj interfejs umożliwiający identyfikację:

    public interface Identifiable<T extends Serializable> {
    T getId();
    }
    

    Następnie rozszerzasz generator tabel:

    public class AssignedTableGenerator extends TableGenerator {
    
    @Override
    public Serializable generate(SessionImplementor session, Object obj) {
    if(obj instanceof Identifiable) {
    Identifiable identifiable = (Identifiable) obj;
    Serializable id = identifiable.getId();
    if(id != null) {
    return id;
    }
    }
    return super.generate(session, obj);
    }
    }
    

    Ten generator może mieszać przypisane identyfikatory z wygenerowanymi syntetycznie:

    doInTransaction(session -> {
    for (int i = 0; i < 5; i++) {
    session.persist(new AssignTableSequenceIdentifier());
    }
    AssignTableSequenceIdentifier tableSequenceIdentifier = new AssignTableSequenceIdentifier();
    tableSequenceIdentifier.id = -1L;
    session.merge(tableSequenceIdentifier);
    session.flush();
    });
    

    generowanie następujących instrukcji:

    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    insert into sequence_table (sequence_name, next_val)  values (default,1)
    update sequence_table set next_val=2  where next_val=1 and sequence_name=default
    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    update sequence_table set next_val=3  where next_val=2 and sequence_name=default
    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    update sequence_table set next_val=4  where next_val=3 and sequence_name=default
    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    update sequence_table set next_val=5  where next_val=4 and sequence_name=default
    select tbl.next_val from sequence_table tbl where tbl.sequence_name=default for update
    update sequence_table set next_val=6  where next_val=5 and sequence_name=default
    select identityvs0_.id as id1_0_0_ from assigneTableIdentifier identityvs0_ where identityvs0_.id=-1
    insert into assigneTableIdentifier (id) values (1, 2)
    insert into assigneTableIdentifier (id) values (2, 4)
    insert into assigneTableIdentifier (id) values (5, -1)
    

W przypadku Oracle można łączyć SEKWENCJĘ i przypisane generatory, jak wyjaśniono w Ten artykuł.

W skrócie, biorąc pod uwagę następujący generator:

public class AssignedSequenceStyleGenerator
extends SequenceStyleGenerator {

@Override
public Serializable generate(SessionImplementor session,
Object obj) {
if(obj instanceof Identifiable) {
Identifiable identifiable = (Identifiable) obj;
Serializable id = identifiable.getId();
if(id != null) {
return id;
}
}
return super.generate(session, obj);
}
}

Możesz zamapować go na swoje podmioty w następujący sposób:

@Id
@GenericGenerator(
name = "assigned-sequence",
strategy = "com.vladmihalcea.book.hpjp.hibernate.identifier.AssignedSequenceStyleGenerator",
parameters = @org.hibernate.annotations.Parameter(
name = "sequence_name",
value = "post_sequence"
)
)
@GeneratedValue(
generator = "assigned-sequence",
strategy = GenerationType.SEQUENCE
)
private Long id;

2 dla odpowiedzi nr 2

Spróbuj czegoś takiego:

@Id
@Column( name = "ID" )
@TableGenerator(
name = "AppSeqStore",
table = "APP_SEQ_STORE",
pkColumnName = "APP_SEQ_NAME",
pkColumnValue = "LISTENER_PK",
valueColumnName = "APP_SEQ_VALUE",
initialValue = 1,
allocationSize = 1 )
@GeneratedValue( strategy = GenerationType.TABLE, generator = "AppSeqStore" )

A ta tabela w bazie danych:

CREATE TABLE APP_SEQ_STORE (
APP_SEQ_NAME VARCHAR(255) NOT NULL,
APP_SEQ_VALUE NUMBER(10) NOT NULL,
PRIMARY KEY(APP_SEQ_NAME)
)

INSERT INTO APP_SEQ_STORE VALUES ("LISTENER_PK", 0)

Wszystko to działa w Oracle, MS Sql Server i MySql przy użyciu JBoss jako serwera aplikacji.

Więcej informacji tutaj: http://www.developerscrappad.com/408/java/java-ee/ejb3-jpa-3-ways-of-generating-primary-key-through-generatedvalue/