example - transactional java spring
¿Necesita una transacción de base de datos para leer datos? (2)
Cuando intento leer datos de la base de datos, al menos usando
((Session)em.getDelegate()).createCriteria()
se produce una excepción que indica que una transacción no está presente.
Cuando agrego la anotación:
@Transactional(
value = SomeClass.TRANSACTIONAL_MANAGER,
propagation = Propagation.SUPPORTS,
readOnly = true
)
funciona bien.
Sin embargo, dado que la lectura sucederá millones de veces por segundo para acceder y leer datos, quiero asegurarme de que nuestro entorno no esté obstruido innecesariamente.
Si no, ¿cuál es el costo de crear una transacción de Propagation.Supports
solo lectura?
¿No puedo crear una consulta de criterios de hibernación sin una transacción, en combinación con Spring?
De acuerdo con mi experiencia con la implementación de JPA en J2EE , siempre se necesita un administrador de transacciones para poder llevar a cabo la seguridad operativa de CRUD , garantizando una reversión para preservar la integridad de los datos.
Las aplicaciones empresariales utilizan diferentes recursos para guardar datos y enviar mensajes como una base de datos o una cola de mensajes. Si queremos consultar estos recursos de forma secuencial y cancelar toda la operación una vez que se produce un problema, tenemos que poner esta consulta en una unidad de trabajo para que se ejecute como un todo.
Podrías definirlo:
mediante el uso de anotaciones relacionadas (como se muestra en las preguntas); de esta manera, el contenedor carga automáticamente el administrador de transacciones para un contexto de persistencia dado;
inyectando manualmente el administrador de transacciones, de la siguiente manera:
public class sample { @PersistenceContext EntityManager em; // Injected transaction manager @Inject UserTransaction utx; private static final String[] GAME_TITLES = { "Super Mario Brothers", "Mario Kart", "F-Zero" }; private void clearData() throws Exception { utx.begin(); em.joinTransaction(); System.out.println("Dumping old records..."); em.createQuery("delete from Game").executeUpdate(); utx.commit(); } private void insertData() throws Exception { utx.begin(); em.joinTransaction(); System.out.println("Inserting records..."); for (String title : GAME_TITLES) { Game game = new Game(title); em.persist(game); } utx.commit(); // clear the persistence context (first-level cache) em.clear(); } // ... }
Los datos de primavera , como implementación de especificaciones JPA, pueden seguir el mismo enfoque.
Puede encontrar más información leyendo el siguiente artículo: Java_Persistence/Transactions .
Todas las declaraciones de la base de datos se ejecutan dentro del contexto de una transacción física, incluso cuando no declaramos explícitamente los límites de la transacción (BEGIN / COMMIT / ROLLBACK).
Si no declara los límites de la transacción, entonces cada declaración deberá ejecutarse en una transacción separada (modo de autocommit
). Esto puede incluso provocar la apertura y el cierre de una conexión por instrucción, a menos que su entorno pueda lidiar con el enlace de conexión por hilo.
Declarar un servicio como @Transactional
le dará una conexión para toda la duración de la transacción, y todas las declaraciones usarán esa única conexión de aislamiento. Esto es mucho mejor que no usar transacciones explícitas en primer lugar.
En aplicaciones grandes, es posible que tenga muchas solicitudes simultáneas, y reducir la tasa de solicitud de adquisición de conexión de base de datos definitivamente mejorará el rendimiento general de la aplicación.
JPA no impone transacciones en operaciones de lectura. Solo las escrituras terminan lanzando una excepción de transacción requerida en caso de que olvide iniciar un contexto transaccional. Sin embargo, siempre es mejor declarar los límites de las transacciones incluso para transacciones de solo lectura (en Spring @Transactional
permite marcar transacciones de solo lectura, lo que tiene un gran beneficio de rendimiento).
Ahora, si usa límites declarativos de transacciones (por ejemplo, @Transactional
), debe asegurarse de que la adquisición de la conexión de la base de datos se retrase hasta que haya una instrucción JDBC para ejecutar. En JTA, este es el comportamiento por defecto. Al usar RESOURCE_LOCAL, debe establecer la propiedad de configuración hibernate.connection.provider_disables_autocommit
y asegurarse de que el grupo de conexiones subyacente esté configurado para deshabilitar el modo de confirmación automática.