2013-07-25 8 views
5

Ich brauche Ruhezustand, um sql wie diese INSERT INTO table_a (a_id, a_name) VALUES (5, 'a5'),(6, 'a6'); zu generieren.Wie macht man HQL, das SQL erzeugt, um mehrere Werte in eine Anweisung einzufügen?

Mit sql wie das können Sie 2 Zeile mit 1 Anweisung hinzufügen. Ich kann

a_id, a_name 

------------------ 
5  a5 
6  a6 

Wenn in Hibernate erhalten, wenn Sie von one to many Beziehung Save Set, Hibernate werde mit mehr Insert-Anweisung einzufügen. Dies führt dazu, wenn Sie 1000 Zeilen einfügen zu 1 Tisch mit HQL wird in etwa wie folgt geführt:

INSERT INTO scoring.table_a (`a_id`, `a_name`) VALUES (1, 'a'); 
INSERT INTO scoring.table_a (`a_id`, `a_name`) VALUES (2, 'a'); 
.... 
... 
.. 
INSERT INTO scoring.table_a (`a_id`, `a_name`) VALUES (1000, 'a'); 

Und die verstrichene Zeit:

Executed 1,000 queries; elapsed time (seconds) - Total: 0.78, SQL query: 0.78, Building output: 0 

Und wenn ich teste, mit den gleichen Werten, Verwendung SQL INSERT INTO table_a (a_id, a_name) VALUES (5, 'a'),(6, 'a'),(),...,...,(1000, 'a'); wird in verstrichene Zeit wie diese Folge:

Query 1 of 1, Rows read: 0, Elapsed time (seconds) - Total: 0.02, SQL query: 0.02, Building output: 0 

Das Ergebnis meines Tests, 1 Erklärung von 1000 Wert (0,02 s) wird etwa 39-mal schneller als 1000 Insert-Anweisung mit jeweils 1 Wert (0,78s) wie Hibernate tun. Also gibt es eine Möglichkeit, HQL so zu machen, dass SQL wie das zum Einfügen erzeugt oder vielleicht auch aktualisiert wird. Oder heißt das, wir müssen den Winterschlaf-Dialekt außer Kraft setzen?

Vielen Dank für die jeden Hinweis

Antwort

0

Sie hibernate.jdbc.batch_size Eigenschaft auf einen Wert ungleich Null gesetzt werden. Es ermöglicht Hibernate, Batch-INSERT zu verwenden. Werfen Sie einen Blick auf a official documentation.

Der folgende Code ist ein Beispiel, wie JDBC Batch-Einsätze durch Hibernate verwenden:

Session session = sessionFactory.openSession(); 
Transaction tx = session.beginTransaction(); 
for (int i=0; i < 10000; i++) { 
    RecordA record = new RecordA(.....); 
    session.save(record); 
    if (i % BATCH_SIZE == 0) { // BATCH_SIZE is your choice, but equal to property 
     //flush a batch of inserts and release memory: 
     session.flush(); 
     session.clear(); 
    } 
} 
tx.commit(); 
session.close(); 

Es wird auch hier diskutiert: Hibernate batch size confusion

+1

Soweit ich weiß, ist Batch_Size Einstellung eine Sache der Speicheroptimierung, um Roundtrip ohne Speicherleck zu minimieren. ** Der Einsatz ist immer noch in mehreren Anweisungen in einer Transaktion **. also ist die batch_size hier nicht die lösung. Aber danke trotzdem .. – Angga

+0

Wie in [Hibernate Batch Size Confusion] (http://stackoverflow.com/questions/6687422/hibernate-batch-size-confusion) erwähnt, erlaubt die 'hibernate.jdbc.batch_size' die Verwendung der JDBC2 API Feature, das die ** aufeinander folgenden ** INSERT-Anweisungen mit ** identische Signatur ** (Tabelle & Spalten) in eine Anweisung mit mehreren ** zusammenführt, wenn der Primärschlüssel nicht ** "GenerationType.Identity" ist. –

+0

Ja, und ** aufeinander folgende INSERT-Anweisungen ** ist anders als ** einzelne INSERT-Anweisung **. und wie ich vorher in meinem Kommentar gesagt habe, ** ist die Einfügung immer noch in mehreren Anweisungen in einer Transaktion **. – Angga

0

HQL unterstützt nur die INSERT INTO ......... SELECT .........; Es gibt keine Chance zu schreiben INSERT INTO ......... WERTE, ich meine, beim Schreiben der Einfügeabfrage müssen wir Werte aus anderen Tabellen auswählen, wir können nicht unsere eigenen Werte manuell einfügen. (see documentation und this)