tutorial example java hibernate

java - example - hibernate wikipedia



el programa que usa hibernaciĆ³n no termina (11)

Creé un programa usando Hibernate.

El programa llega al final de la función principal, sin embargo, el programa se está ejecutando.

Me pregunto si esto sucede cuando SessionFactory se configura con la versión 4.x de Hibernate.

¿Es la forma de configurar mal?

manual1_1_first_hibernate_apps.java

public static void main(String[] args) { args[0] ="list"; if (args.length <= 0) { System.err.println("argement was not given"); return; } manual1_1_first_hibernate_apps mgr = new manual1_1_first_hibernate_apps(); if (args[0].equals("store")) { mgr.createAndStoreEvent("My Event", new Date()); } else if (args[0].equals("list")) { mgr.<Event>listEvents().stream() .map(e -> "Event: " + e.getTitle() + " Time: " + e.getDate()) .forEach(System.out::println); } Util.getSessionFactory().close(); } private <T> List<T> listEvents() { Session session = Util.getSessionFactory().getCurrentSession(); session.beginTransaction(); List<T> events = Util.autoCast(session.createQuery("from Event").list()); session.getTransaction().commit(); return events; }

Util.java

private static final SessionFactory sessionFactory; /** * build a SessionFactory */ static { try { // Create the SessionFactory from hibernate.cfg.xml // hibernate version lower than 4.x are as follows // # it successful termination. but buildSessionFactory method is deprecated. // sessionFactory = new Configuration().configure().buildSessionFactory(); // version 4.3 and later // # it does not terminate. I manually terminated. Configuration configuration = new Configuration().configure(); StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } /** * @return built SessionFactory */ public static SessionFactory getSessionFactory() { return sessionFactory; }

Los siguientes fragmentos de registro de la consola cuando finaliza el programa y usan el método buildSessionFactory.

2 08, 2014 8:42:25 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop INFO: HHH000030: Cleaning up connection pool [jdbc:derby:D:/Java/jdk1.7.0_03(x86)/db/bin/testdb]

pero si no utiliza el método buildSessionFactory en desuso y finaliza (el programa se está ejecutando), las dos líneas anteriores no aparecen.

AMBIENTE:

Hibernate 4.3.1 DERBY JRE 1.8 IntelliJ IDEA 13


Acabo de tener el mismo problema. Estaba usando Hibernate 4.1.1 y todo estaba funcionando bien. Hoy me actualicé a Hibernate 4.3.1 y de repente mi aplicación no terminó más. Investigué un poco más y noté que la versión 4.1.1 no tenía ningún problema con una EntityManagerFactory abierta. Es por eso que mi aplicación siempre termina. Ese no es el caso con la versión 4.3.1 nunca más. Así que revisé mi aplicación y me aseguré de que EntityManagerFactory se cerró al final (de hecho, realmente no estaba cerrando). Problema resuelto para mí. ¿Estás realmente seguro de que no queda nada abierto en tu aplicación? Espero que esto ayude.

Marcos


Conocí este problema también hoy, y encontré que la solución es, al final de su método principal (o hilo), debe cerrar su fábrica de sesiones, como:

sessionFactory.close();

Y luego, su programa terminará normalmente.

Si usa JavaFX 8 en el método principal, agregue:

@Override public void stop() throws Exception { sessionFactory.close(); }

Este método cerrará la sesión de fábrica y destruirá el hilo al salir del programa.


Encontré este problema también hoy, y encontré que la solución como:

sessionFactory.close();

funcionará si tiene

<property name="connection.pool_size">1</property>


Estoy usando hibenate 5.2.12 con sqlite 3.20.1, gestionando la conexión manualmente. En mi caso, el problema era que no solo se tenía que cerrar el administrador de la entidad sino también la fábrica del administrador de la entidad.

Con estos atributos:

EntityManager entityManager; EntityTransaction entityTransaction;

Este fragmento se usa al abrir la base de datos y comenzar una transacción:

EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, map); entityManager = emf.createEntityManager(map); entityTransaction = entityManager.getTransaction(); entityTransaction.begin();

Este recorte se utiliza para confirmar la transacción y cerrar la base de datos:

entityTransaction.commit(); if ( entityManager.isOpen() ) { entityManager.close(); } EntityManagerFactory emf = entityManager.getEntityManagerFactory(); if ( emf.isOpen() ) { emf.close(); }

Ahora con emf.close(); mi aplicación termina como debería ser.


Mi respuesta es para la versión Hibernate 4.3+, y la uso en mi camino.

Un ejemplo de Spring Annotation configurado con Hibernate:

//Using AutoCloseable 1.7 feature here to close context and //suppress warning Resource leak: ''context'' is never closed //Creating AutoClosebale AbstractApplicationContext Object context try (AbstractApplicationContext context = new AnnotationConfigApplicationContext(SpringAppConfig.class)) { SnacksMenu snacks = context.getBean(SnacksMenu.class); System.out.println(snacks.toString()); //Creating AutoClosebale SessionFactory Object factory try (SessionFactory factory = getStandardServiceEnabledSessionFactory()){ //Creating AutoClosebale Session Object session try (Session session = factory.openSession()) { SessionCounter.analysisSession(session); System.out.println("1: Opened Sessions under factory : " + SessionCounter.getOpenSessionsCount()); Transaction transaction = session.beginTransaction(); session.persist(snacks); transaction.commit(); System.out.println(session.isConnected()); }//Session Object session resource auto closed }//SessionFactory Object factory resource auto closed System.out.println("2: Opened Sessions under factory : " + SessionCounter.getOpenSessionsCount()); }//AbstractApplicationContext Object context resource auto closed


Mismo problema en 4.3.4.Final.

Ahora después de agregar el siguiente código, el problema se ha ido.

public class Service { private SessionFactory factory; private ServiceRegistry serviceRegistry; public void initialize() throws Exception{ Configuration configuration = new Configuration(); configuration.configure("com/jeecourse/config/hibernate.cfg.xml"); serviceRegistry = new StandardServiceRegistryBuilder().applySettings( configuration.getProperties()).build(); factory = configuration.buildSessionFactory(serviceRegistry); } public void close() throws Exception{ if(serviceRegistry!= null) { StandardServiceRegistryBuilder.destroy(serviceRegistry); } }

.....


Parece que Hibernate 4.3.1 introdujo un error. Creo la conexión en mi aplicación con:

EntityManagerFactory connection = Persistence.createEntityManagerFactory(...)

pero incluso si el método createEntityManagerFactory falla con una excepción, el registro del servicio permanece abierto. Sin embargo, como se puede ver en el código anterior, no puedo finalizar mi aplicación porque como el método no tuvo éxito, la connection variable no se asignó (es nula ), así que no puedo llamar a connection.close() que destruiría el registro de servicio. Parece que esto es realmente un error, porque ¿cómo podré liberar recursos sin recurrir a un hack, como usar API específicas de Hibernate desde una aplicación JPA?


Tenemos múltiples conexiones a la base de datos.

class ConnectionProviderFactory implements DataBaseConnectionProvider { private EnumMap<SystemInstance, Properties> connectionsConfigs = new EnumMap<>(SystemInstance.class); private Map<SystemInstance, EntityManager> entityManagers = new HashMap<>(); private Map<SystemInstance, ConnectionPerSystemInstance> connections = new HashMap<>(); @Getter private static class ConnectionPerSystemInstance { private String uuid = UUID.randomUUID().toString(); private final SessionFactory sessionFactory; private final SystemInstance systemInstance; private ConnectionPerSystemInstance(final SessionFactory sessionFactory, SystemInstance systemInstance){ this.sessionFactory = sessionFactory; this.systemInstance = systemInstance; } static ConnectionPerSystemInstance createConnection(Properties properties, SystemInstance systemInstance) { StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder(); registryBuilder.applySettings(toMap(properties)); StandardServiceRegistry registry = registryBuilder.build(); MetadataSources sources = new MetadataSources(registry); Metadata metadata = sources.getMetadataBuilder().build(); SessionFactory sessionFactory = metadata.getSessionFactoryBuilder().build(); return new ConnectionPerSystemInstance(sessionFactory, systemInstance); } private static Map<String, String> toMap(Properties properties) { Map<String, String> map = new HashMap<>(); for (String name : properties.stringPropertyNames()) { map.put(name, properties.getProperty(name)); } return map; } EntityManager getEntityManager() { if(sessionFactory == null) { throw new IllegalStateException("Connection not initialized!"); } return sessionFactory.createEntityManager(); } void close() { if(sessionFactory == null) { throw new IllegalStateException("Connection not initialized!"); } sessionFactory.close(); } @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final ConnectionPerSystemInstance that = (ConnectionPerSystemInstance) o; return uuid.equals(that.uuid); } @Override public int hashCode() { return uuid.hashCode(); } } @PostConstruct private void init() { String testQuery = "select sysdate from dual"; EntityManager e1TEST = connect(SystemInstance.TEST); EntityManager e1PROD = connect(SystemInstance.PROD); log.info("" + e1TEST.createNativeQuery(testQuery).getSingleResult()); log.info("" + e1PROD.createNativeQuery(testQuery).getSingleResult()); } @PreDestroy private void clean() { entityManagers.forEach((key, value) -> value.close()); connections.forEach((systemInstance, connectionPerSystemInstance) -> { connectionPerSystemInstance.close(); }); } @Override public EntityManager connect(final SystemInstance systemInstance) { if (Optional.ofNullable(entityManagers.get(systemInstance)).isPresent()) { entityManagers.get(systemInstance); } Properties properties = loadConnectionProperties(systemInstance); ConnectionPerSystemInstance connection = ConnectionPerSystemInstance.createConnection(properties, systemInstance); connections.put(systemInstance, connection); entityManagers.put(systemInstance, connection.getEntityManager()); return entityManagers.get(systemInstance); } @Override public void closeAllConnection() { clean(); } private Properties loadConnectionProperties(SystemInstance systemInstance) { if (Optional.ofNullable(connectionsConfigs.get(systemInstance)).isPresent()) { return connectionsConfigs.get(systemInstance); } return tryLoadConnectionProperties(systemInstance); } private Properties tryLoadConnectionProperties(final SystemInstance systemInstance) { final String nameOfPropertyFile = getNameOfPropertyFile(systemInstance); ClassPathResource classPathResource = new ClassPathResource(nameOfPropertyFile); Properties properties = new Properties(); try { properties.load(classPathResource.getInputStream()); addAdditionalConnectionSettings(properties); connectionsConfigs.put(systemInstance, properties); } catch (IOException e) { log.error(e.getMessage(), e); throw new RuntimeException(e.getMessage()); //TODO chanfe exception } return properties; } private String getNameOfPropertyFile(SystemInstance systemInstance) { if (systemInstance == SystemInstance.TEST) return "db/db-test.properties"; if (systemInstance == SystemInstance.PROD) return "db/db-prod.properties"; throw new IllegalArgumentException("Incorrect configuration"); } private void addAdditionalConnectionSettings(Properties properties) { properties.putIfAbsent("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect"); properties.putIfAbsent("hibernate.c3p0.timeout", "0"); }

}

En este ejemplo, tenemos múltiples bases de datos para que podamos cerrar todas las conexiones fácilmente.


Tuve el mismo problema hoy, pero encontré otra solución similar:

Inserté al final de mi código la siguiente línea:

StandardServiceRegistryBuilder.destroy(serviceRegistry);

¡Y Ta-dah! el programa termina.


tal vez, he resuelto este problema.

Vi el volcado del hilo después de llamar a Util.getSessionFactory (). Close (), un hilo llamado estado "pool-2-thread-1" fue TIMED_WAITING (estacionamiento).

El siguiente volcado de fragmentos

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.0-b69 mixed mode): "DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x00000000020b9000 nid=0x3684 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "pool-2-thread-1" #15 prio=5 os_prio=0 tid=0x000000001bc27000 nid=0x3f0 waiting on condition [0x000000001ce6f000] java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x0000000080be30a0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:744) "derby.rawStoreDaemon" #14 daemon prio=5 os_prio=0 tid=0x000000001b059000 nid=0xa3c in Object.wait() [0x000000001ba1f000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000805f6190> (a org.apache.derby.impl.services.daemon.BasicDaemon) at org.apache.derby.impl.services.daemon.BasicDaemon.rest(Unknown Source) - locked <0x00000000805f6190> (a org.apache.derby.impl.services.daemon.BasicDaemon) at org.apache.derby.impl.services.daemon.BasicDaemon.run(Unknown Source) at java.lang.Thread.run(Thread.java:744) "Timer-0" #13 daemon prio=5 os_prio=0 tid=0x000000001b08e800 nid=0x2160 in Object.wait() [0x000000001b6af000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000080608118> (a java.util.TaskQueue) at java.lang.Object.wait(Object.java:502) at java.util.TimerThread.mainLoop(Timer.java:526) - locked <0x0000000080608118> (a java.util.TaskQueue) at java.util.TimerThread.run(Timer.java:505)

Pensé que la causa es el hilo llamado "pool-2-thread-1" creado por el método buildSessionFactory.

Como resultado de comparar los dos métodos buildSessionFactory, noté que los recursos de ServiceRegistry no se han liberado.

El programa finalizó exitosamente al liberarlo.

El siguiente código, agrego.

Util.java

configuration.setSessionFactoryObserver( new SessionFactoryObserver() { @Override public void sessionFactoryCreated(SessionFactory factory) {} @Override public void sessionFactoryClosed(SessionFactory factory) { ((StandardServiceRegistryImpl) serviceRegistry).destroy(); } } );

Gracias.


tuve el mismo problema, la solución es muy simple, debe agregar esta propiedad al archivo de configuración

<property name="hibernate.c3p0.timeout">0</property>