2015-06-09 13 views
8

pracuję na Java wniosku, że należy zrobić operacje CRUD (używając Hibernate 4.3.8) na dwóch różnych baz danych z tego samego schematu bazy danych. Istnieje baza danych MySQL (wersja 5.1.73) i Oracle (11g Express Edition wydanie 11.2.0.2.0 - 64bit).Hibernate auto generowania klucza z MySQL i Oracle

Klasy Java z Adnotacje JPA zostały wygenerowane z tabel bazy danych za pomocą generatora kodu hibernacji.

Problemem jest to, że teraz mamy potrzebę użycia automatycznego generowania klucza podstawowego i MySQL używa GenerationType.IDENTITY i Oracle wykorzystuje GenerationType.SEQUENCE. Ponadto w niektórych rzadkich przypadkach potrzebujemy możliwości ręcznego ustawienia klucza głównego.

Kod śledzenia w klasie z adnotacjami działa z automatycznym generowaniem kluczy 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 @SequenceGenerator @GeneratedValue i adnotacje możliwe jest ręczne ustawienie klucza podstawowego, ale generacji auto nie działa.

+0

Wypróbuj [ręcznie określić-the-value-of-a- primary-key-in-jpa-generatedvalue-column] [1]. Istnieje wiele rozwiązań. [1]: http://stackoverflow.com/questions/12002260/manually-specify-the-value-of-a-primary-key-in-jpa-generatedvalue-column – Volatile

+0

Baza zorientowane rozwiązanie w tym wątku nie działa dla mnie, ponieważ schemat bazy danych nie powinien być zmieniany. Są inni ludzie niż ja, którzy polegają na tym, że schemat bazy danych się nie zmienia. I nie wiem, czy jest to możliwe i jak napisać własny Custom Id Generator, który obsługuje obie bazy danych MySQL i Oracle (Tożsamość i Sequence). We wszystkich przykładach używają one IdentifierGenerator OR Sequencegenerator. –

+1

To pytanie nie jest jasne. Czy mówisz, że masz kilka klas, dla których Hibernate ma automatycznie generować identyfikatory i ręcznie przypisywać identyfikatory do innych klas; lub czy chcesz, aby Hibernate automatycznie przypisywał identyfikatory do wystąpień klasy przez większość czasu, ale w niektórych przypadkach chcesz ręcznie przypisywać identyfikatory do niektórych instancji tej samej klasy? – manish

Odpowiedz

9

Nawet jeśli użyto GenerationType.AUTO bez konkretnego parametru sekwencji, nie byłby w stanie uratować przypisanych identyfikatorów.

Istnieją pewne obejścia, jeśli jesteś skłonny do pewnych kompromisów:

  1. Jednym sposobem byłoby, aby przełączyć się do przydzielonych identyfikatorów. Możesz użyć identyfikatorów UUID, które działają zarówno dla MySQL, jak i Oracle, a także możesz je przypisać ręcznie.

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

    Najpierw trzeba zdefiniować identyfikację interfejs:

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

    Wtedy przedłużenia generator tabeli:

    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 jest w stanie mieszać przypisane identyfikatory z syntetycznych generowane nich:

    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 oświadczeń:

    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) 
    

Dla Oracle, można połączyć się z sekwencji i przypisane generatorów jak wyjaśniono w this article.

Krótko mówiąc, biorąc pod uwagę następujące 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żna mapować go do swoich jednostek, co następuje:

@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

spróbować 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") 

I to 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) 

To wszystko działa w Oracle i MS SQL Server, MySQL przy użyciu JBoss jako App Server.

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

Powiązane problemy