style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Crear archivos txt a partir de otro archivo txt

Hola quisiera que alguien me ayude con este problema.

Tengo un archivo txt de mas de 505,000 lineas el cual debo introducir en una tabla en una base de datos. El problema es que a la hora de hacer el insert de cada linea a la base de datos el servidor no soporta muchas transacciones por la linea 100,000 se queda colgado. Lo que se me ha ocurrido es tratar de partir el archivo txt en partes de 90,000 lineas e ir cargando los archivo de txt uno por uno.

No he podido hacer de un archivo crear varios con las lineas restantes.

Gracias.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de rugi

No debería de haber problemas

No debería de haber problemas con repetir el insert N veces.
Probablemente existe alguna fuga de memoria que hace que en la ejecución N alcances un estado de error.

Como haces la insercion... usas un preparedStatement?

Saludos!!!
---
RuGI

Imagen de 00Erzengel

JPA

Utilizo un EntityManager.
Utilizo persistencia con JPA.

La cuestión es que con un archivo de 90,000 lineas todo bien, a la hora de querer probar con uno de mas de 500,000 lineas no funciona.

Configuración

Eso es más del tema de configuración que de que hacer. Digo un insert vendría siendo algo como:

Persona p = new Persona(nombre, apellido, edad);
entityManager.persist(p);

De modo que, o lo estás inicializando y cerrando a cada transacción. O te estás chupando la memoria
de la VM. ¿Es un requerimiento hacerlo con JPA?, creo que eso lo podrías hacer de manera fácil con
JDBC a pelo, aunque claro, también es más incómodo.

Podemos ver el traza de la pila solo para corroborar que está pasando. Porqué al aire podemos especular
de aquí a año nuevo, pero sin mucha información poco podemos ayudar.

Imagen de paranoid_android

Problema de cantidad o de disco

Hola, he visto herramientas en C que hacen eso a velocidades increibles dependiendo de la base de datos, asi que java no debería tener problemas. Yo checaria lo siguiente.
1. Una carga masiva no deberia ser transaccional, despues de cada registro un commit.
2. Suficiente espacio de swap tanto en el sistema operativo como en table spaces
3. Verificar que tu carga + Operacion + swap quepa en tu disco.
4. De ser muy grande deberia poder particionarse para poder recuperar desde un punto.

En pocas palabras apoyate en un dba.

Imagen de neko069

Coloca el código completo del

Coloca el código completo del código de tú método, por favor entre tags de <code> y </code>.

Ahora que recuerdo, me suena a algo como ésto.

Imagen de 00Erzengel

Codigo

 
public int insertTblPersona(String codPersona, String anexo, String tel, String detalle) {
//Para llevar un control de cuantos registros van registrados
                int result = 0;
               
                EntityManagerFactory factory = Persistence.createEntityManagerFactory("TblPersonaEJB");
                EntityManager em = factory.createEntityManager();
                TblPersona tblPersona=null;
                try {
                         em.getTransaction().begin();
                       
                         tblPersona=new TblPersona();
                         
                         tblPersona.setCodPersona(codPersona);
                         tblPersona.setAnexo(anexo);
                         tblPersona.setTel(tel);
                         tblPersona.setDetalle(detalle);

                         em.persist(tblPersona);

//                       em.flush();
                         em.getTransaction().commit();
                       
//                      em.clear();
                       
                        log.info("Registro... Ok");
                        result=1;
                       

                } catch (Exception e) {
                        logD.error(
                                        "Error ejecutando rutina de ingresar registros a Tbl_Persona",
                                        e);
                        em.getTransaction().rollback();
                } finally {
                        em.close();
                        factory.close();
                }

                return result;
        }

Este es el codigo del insert con persistencia he probado dandole em.flush() y em.clear() y comentando em.getTransaction().commit() y siempre igual.
Siempre se queda por la linea 90,000

Gracias.

Imagen de beto.bateria

Creo que el problema es que

Creo que el problema es que estas haciendo una transaccion por persona(es muy tardado asi), me imagino que debes de tener un for que llamas a este codigo, trata de agregar mas objetos a la transaccion y despues ejecuta el commit (el commit es algo parecido al flush respecto a la base de datos).

Otra obsevacion, estas haciendo mal uso de los objetos, despues de leer una linea del txt debes de pasar la informacion al objeto, los metodos deben de recibir los objetos, no los atributos. Tu metodo deberia de ser algo asi como:

public int insertTblPersona(TblPersona tblPersona);

Re: Codigo

Creo que tu problema principal es que estás creando un EntityManager cada vez. Has de tener seguro un ciclo en donde cada vez llamas a ese EntityManager, por tanto lo creas cada vez, a eso súmale que cada vez creas una transacción y cierras. Lo mejor podría ser algo como:

//Obtienes las personas desde tu fichero
List<Persona> personas = getPersonasFromFile();
//Ahora creas el entityManager y la transacción
EntityManagerFactory emf = Persistence.createEntityManagerFactory("TBLPersonaEJB");
EntityManager em = emf.createEntityManager();
Transaction t = em.getTransaction();
try{
--//Inicias la transacción
--t.begin();
--//Iteras la lista de personas y guardas
--//cada persona.
--for(Persona p:personas){
----em.persist(p);
--}
--t.commit();
}catch(Exception e){ //De preferencia atrapa el tipo de exception
--logD.error("Hemos encontrado un error ", e);
--t.rollback();
}finally{
--//Y los liberas de memoria con flush, clear, etc.
}

¿No has intentado de esa manera?

Imagen de neko069

Coincido con @wishmaster,

Coincido con @wishmaster, sólo una pequeña observación, si usas Spring, o CDI, mejor transfiere la transacción por medio de anotación a la capa de servicio, y en el dao no caches la excepción, súbela de capa, para que por medio del framework que uses, ya le des tratamiento a la excepción.

Re: Coincido con @wishmaster

Me quedó en duda algo:

[...]y en el dao no caches la excepción, súbela de capa[...]

¿A qué capa la subirías o más bien para qué la subirías?, por mi parte creo que atraparla ahí está bien y por algún método (regreso de booleans, por ejemplo) decirle a las capas de arriba que se falló, ya tu revisas la bitácora y los usuarios ven un sencillo: "Oops, hubo un error al procesar la petición, nuestro equipo ya está trabajando en ello". Digo, a las capas superiores no les importa porqué falló o cual fue la excepción, simplemente deben enterarse si todo está bien o no. Pero igual y estoy mal o quizás lo que comentas es una buena práctica, no sé, ¿podrías explicar las ventajas que traería tu planteamiento?

Imagen de neko069

Ok, con un

Ok, con un ejemplo.

Supongamos que tenemos que hacer inserciones en un par de tablas. tienes tus daos para hacer las inserciones.

 ElDaoUno elDaoUno
 ElDaoDos elDaoDos

Cada dao tiene su método para insertar:

 insertaEnTablaUno throws ExcepcionIndicadaOPersonalizada();
 insertaEnTablaDos throws ExcepcionIndicadaOPersonalizada();

Ésos dos daos los vas a usar en tu capa de servicio, para hacer las inserciones.

 ElServicioQueUsaMuchosDaos elServicioQueUsaMuchosDaos

Ahora, la transacción, yo no la colocaría en la capa de dao, sino en la capa de servicio, en el método que va a hacer las inserciones.

// en CDI creo que es TransactionalAttribute ... o la heredó/tomó de EJB3 no recuerdo bien.
@Transactional(readOnly = false /*no puede ser true, porque es insercion*/, propagation = NIVEL_DE_PROPAGACION , rollbackFor=ExcepcionIndicadaOPersonalizada.class)
 public ObjetoDeRetorno insertaEnMuchasTablas( Parametro ...parametro ){
    try{
        elDaoUno.insertaEnTablaUno();
        elDaoDos.insertaEnTablaDos();
    }
    catch( ExcepcionIndicadaOPersonalizada e ){
        //aquí haces otra cosa o regresas otro resultado, o le das System.exit(0) y tiras el servidor ...o algo.
    }
}

Así usaría la misma transacción para hacer ambas inserciones, ya sea que la cree o que reutilice una existente, y a su vez, si truena la inserción en la tabla UNO, ya no se sigue con la inserción de la tabla DOS. Además, aprovechas la posibilidad de crear una excepción personalizada, si lo necesitas, y ya puedes regresar también un mensaje personalizado, o hacer otra acción.

Creo que es un ejemplo bastante escueto y le faltan cosas, pero estaría mejor checar ejemplos, y la documentación del framework, pero espero que se haya entendido.

Con relación a lo que haces @wishmaster, no lo veo mal, de hecho así lo hacía yo hace algún tiempo, pero desde hace un rato, me habitué más a hacerlo como lo ejemplifico (bueno, no tan feo). Si alguien tiene observaciones, o correcciones, bienvenidas.

Por cierto, que me encontré éste par de tutoriales: tutorial 1 y tutorial 2
En el primero declaran las anotaciones, en clases de servicio ( o de negocio ) y en el segundo están declaradas en los daos, así que me supongo que no hay reglas como tal...si alguien tiene comentarios, venga!

Imagen de 00Erzengel

Gracias

Hola a todos los del foro
Gracias por la ayuda que me brindaron.
Ya solucione el problema lo hice de la forma que lo tenia y de la forma en que wishmaster77 explico y las dos formas corren de lo mejor. El problema era con la cantidad de memoria asignada a la JVM que era muy bajo hoy tiene asignada 2G de memoria y todo bien.

Gracias.

Re: Ok, con un

Me sonaste muy "es que en aplicaciones enterprise"... No sé, pero simplemente eso que comentas se me hace agregar capas de complejidad e incluso para debugging se me hace más difícil. Porqué digamos, al hacer el insert falló, aventó la excepción, la recibo en una de las siguientes capas. A la hora de ver el stack trace de primera vista veo que falla en una capa, voy a la capa, veo el comportamiento y resulta que no falla ahí, sino en el DAO, de ahí ya perdiste tiempo en ver el comportamiento en la capa superior y luego ir bajando capas.

Del modo en que yo lo hago, atrapas la excepción en el DAO, la etiquetas en la bitácora y listo, de primera vista te diste cuenta que falló en el DAO, por tanto a corregir ahí. Uno como programador debe saber hacer llegar de la manera más directa los problemas, porqué pasarlos de capa en capa solo atrae que te tienes que aventar toda la pila de trazas de manera minuciosa.

Y como yo lo hago, pues regreso un boolean, si se completa devuelve true; si no se completa doy rollback, regreso false y en la capa superior un simple: "Oops, experimentamos problemas técnicos".

¿Si me doy a entender?... Yo de hecho estaba como tu estás ahora, y después de verme abocado a tener que liarla con que tenía que ir capa a capa, mejor me di por vencido y así se exactamente en donde fue el error de un solo vistazo :D.

Imagen de neko069

Qué no leyendo el stack trace

Qué no leyendo el stack trace ya te das cuenta desde dónde surge el error?

Como sea, nada es determinante a la hora de declarar las transacciones, depende (siempre depende) del proyecto donde te desenvuelvas, por éso al último coloqué dos links ejemplificando ambas formas de declarar la transacción, de ahí ya uno se puede hacer una idea del cómo y dónde generarla.

Distintas perspectivas enriquecen el tema, por mi parte es todo, saludos.

Re: Qué no leyendo el stack trace

Por eso, yo trato de leer lo menos posible la traza... Si desde las primeras líneas del error te sale en donde está el error te ahorras tiempo en dar scroll y ya sabes de un sólo vistazo en donde está el error. De la otra forma ves que falla en un método de una clase y más abajo que falló en otra clase ejecutando X método y más abajo aparece que en realidad era un método de otra clase. De mi forma de un solo vistazo revisas el stack y sin scroll ya ves que es lo que falla.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">