1919import org .hibernate .Session ;
2020import org .springframework .beans .factory .annotation .Qualifier ;
2121import org .springframework .util .ReflectionUtils ;
22+ import tools .dynamia .commons .StopWatch ;
2223import tools .dynamia .commons .logger .LoggingService ;
2324import tools .dynamia .domain .jpa .JpaUtils ;
2425import tools .dynamia .domain .services .CrudService ;
@@ -280,15 +281,13 @@ private void exportEntitiesInParallel(Path tempDir,
280281 semaphore .acquire ();
281282 try {
282283 if (token != null && token .isCancelled ()) return 0L ;
283- long count = exportEntityToFile (tempDir , entityClass , accountId , options , token );
284+ long count = exportEntityToFile (tempDir , entityClass , accountId , options , token , listener );
284285
285286 // Report progress immediately upon completion, not waiting for topological order
286287 long processed = processedTypes .incrementAndGet ();
287288 long records = totalRecords .addAndGet (count );
288289 if (listener != null ) {
289- listener .onProgress (new MigrationProgress (processed , totalTypes ,
290- "Exported " + entityClass .getSimpleName () + " (" + count + " records)" ,
291- records ));
290+ listener .onProgress (MigrationProgress .of (processed , totalTypes , "Exported " + entityClass .getSimpleName (), records ));
292291 }
293292 return count ;
294293 } finally {
@@ -334,7 +333,8 @@ private void exportEntitiesInParallel(Path tempDir,
334333 */
335334 private long exportEntityToFile (Path tempDir , Class <?> entityClass ,
336335 Serializable accountId , AccountExportOptions options ,
337- CancellationToken token ) throws IOException {
336+ CancellationToken token ,
337+ MigrationProgressListener listener ) throws IOException {
338338
339339 Path filePath = tempDir .resolve (entityFileName (accountId , entityClass ));
340340 EntityManager localEm = emf .createEntityManager ();
@@ -353,6 +353,8 @@ private long exportEntityToFile(Path tempDir, Class<?> entityClass,
353353 localEm .clear ();
354354 localEm .close ();
355355
356+
357+ logger .info ("[Migration/Export] {} with {} columns" , entityClass .getSimpleName (), columns .size ());
356358 try (OutputStream out = new BufferedOutputStream (Files .newOutputStream (filePath ), ENTITY_BUFFER_SIZE );
357359 JsonGenerator gen = objectMapper .createGenerator (out )) {
358360
@@ -368,12 +370,14 @@ private long exportEntityToFile(Path tempDir, Class<?> entityClass,
368370
369371 gen .writeName (ExportConstants .FIELD_ROWS );
370372 gen .writeStartArray ();
371- long processed = writeEntityRows (gen , entityClass , accountId , options , token , columns );
373+ long startTime = System .currentTimeMillis ();
374+ long processed = writeEntityRows (gen , entityClass , accountId , options , token , columns , listener );
375+ long endTime = System .currentTimeMillis ();
372376 gen .writeEndArray ();
373377
374378 gen .writeEndObject ();
375379
376- logger .info ("[Migration/Export] {} → {} records written" , entityClass .getSimpleName (), processed );
380+ logger .info ("[Migration/Export] {} → {} records written in {}ms " , entityClass .getSimpleName (), processed , ( endTime - startTime ) );
377381 return processed ;
378382 }
379383 } finally {
@@ -411,7 +415,8 @@ private long writeEntityRows(JsonGenerator gen,
411415 Serializable accountId ,
412416 AccountExportOptions options ,
413417 CancellationToken token ,
414- List <ColumnDef > columns ) throws IOException {
418+ List <ColumnDef > columns ,
419+ MigrationProgressListener listener ) throws IOException {
415420 if (Account .class .equals (entityClass )) {
416421 return 0 ;
417422 }
@@ -424,10 +429,12 @@ private long writeEntityRows(JsonGenerator gen,
424429
425430
426431 do {
432+ long qStartTime = System .currentTimeMillis ();
427433 List <Object > page = queryEntityDataPage (entityClass , accountId , lastId , simpleName , chunkSize );
428- logger . info ( "[Migration/Export] {} - page {} with {} records. Rows processed {}" , simpleName , pageNum , page . size (), processed );
434+ long qEndTime = System . currentTimeMillis ( );
429435 pageNum ++;
430436
437+ long startTime = System .currentTimeMillis ();
431438 for (Object entity : page ) {
432439 if (token != null && token .isCancelled ()) break ;
433440 if (entity != null ) {
@@ -439,6 +446,14 @@ private long writeEntityRows(JsonGenerator gen,
439446 }
440447 processed ++;
441448 }
449+ long endTime = System .currentTimeMillis ();
450+
451+ logger .info ("[Migration/Export] {} - page {} with {} records. Query={}ms Write={}ms. Rows={} " ,
452+ simpleName , pageNum , page .size (), (qEndTime - qStartTime ), (endTime - startTime ), processed );
453+
454+ if (listener != null ) {
455+ listener .onProgress (MigrationProgress .partial (processed ));
456+ }
442457 if (page .size () < chunkSize || (token != null && token .isCancelled ())) break ;
443458
444459 } while (true );
@@ -560,32 +575,30 @@ private List<ColumnDef> buildColumns(EntityType<?> entityType) {
560575
561576 private void writeEntityRow (JsonGenerator gen , Object entity , List <ColumnDef > columns )
562577 throws IOException {
563- gen .writeStartArray ();
564- for (ColumnDef col : columns ) {
578+
579+
580+ Object [] row = new Object [columns .size ()];
581+
582+ for (int i = 0 ; i < columns .size (); i ++) {
583+ ColumnDef col = columns .get (i );
584+
565585 try {
566586 Object value = col .field ().get (entity );
567587
568588 if (col .type () == PersistentAttributeType .MANY_TO_ONE
569589 || col .type () == PersistentAttributeType .ONE_TO_ONE ) {
570- if (value != null ) {
571- gen .writePOJO (JpaUtils .getJPAIdValue (value ));
572- } else {
573- gen .writeNull ();
574- }
590+ row [i ] = value != null
591+ ? JpaUtils .getJPAIdValue (value )
592+ : null ;
575593 } else {
576- objectMapper . writeValue ( gen , value ) ;
594+ row [ i ] = value ;
577595 }
578- } catch (IllegalAccessException e ) {
579- logger .debug ("[Migration/Export] Cannot access field {} on {}: {}" ,
580- col .field ().getName (), entity .getClass ().getSimpleName (), e .getMessage ());
581- gen .writeNull ();
582596 } catch (Exception e ) {
583- logger .debug ("[Migration/Export] Skipping field {} due to: {}" ,
584- col .field ().getName (), e .getMessage ());
585- gen .writeNull ();
597+ row [i ] = null ;
586598 }
587599 }
588- gen .writeEndArray ();
600+
601+ gen .writePOJO (row );
589602 }
590603
591604 // ─────────────────────────────────────────────────────────────────────────
0 commit comments