true transaction transacciones transaccional manager framework example driven con annotation java spring hibernate spring-mvc annotations

java - transacciones - Algunas aclaraciones sobre Spring @Transactional anotación en un método



transacciones con spring framework (2)

En primer lugar, no debe hacer que los métodos DAO sean transaccionales, sino métodos de servicio.

En segundo lugar, usar Transactional es una forma de permitir que Spring comience y comprometa / retrotraiga las transacciones por usted. Por lo tanto, no debe comenzar y realizar transacciones usted mismo.

Tercero: esto solo funcionará si usa un administrador de transacciones que sabe cómo asociar una sesión de Hibernate con la transacción (generalmente, un HibernateTransactionManager ). La fábrica de sesiones también debería ser manejada por Spring e inyectada por Spring en sus DAO. El código del DAO debería verse así:

Cuarto: no debe abrir una sesión nueva, sino obtener la actual, asociada a la transacción actual por Spring.

public class PersonDAOImpl implements PersonDAO { @Autowired private SessionFactory sessionFactory; public Integer addPerson(Person p) { Session session = sessionFactory.getCurrentSession(); Integer personID = (Integer) session.save(p); return personID; } public Person getById(int id) { Session session = sessionFactory.getCurrentSession(); Person retrievedPerson = (Person) session.get(Person.class, id); return retrievedPerson; } @SuppressWarnings("unchecked") public List<Person> getPersonsList() { Session session = sessionFactory.getCurrentSession(); Criteria criteria = session.createCriteria(Person.class); return criteria.list(); } public void delete(int id) { Session session = sessionFactory.getCurrentSession(); Person personToDelete = getById(id); session.delete(personToDelete); } public void update(Person personToUpdate) { Session session = sessionFactory.getCurrentSession(); session.update(personToUpdate); } }

Lea la documentación para más información.

Soy bastante nuevo en el mundo de la primavera y he desarrollado un proyecto simple que utiliza Spring 3.2.1 e Hibernate 4.1.9 para implementar un DAO. El proyecto funciona correctamente, pero tengo algunas dudas sobre el uso de la anotación @Transactional Spring en el método CRUD de este DAO.

Este es el código completo de la clase que implementa la operación CRUD de mi proyecto:

package org.andrea.myexample.HibernateOnSpring.dao; import java.util.List; import org.andrea.myexample.HibernateOnSpring.entity.Person; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.springframework.transaction.annotation.Transactional; public class PersonDAOImpl implements PersonDAO { // Factory per la creazione delle sessioni di Hibernate: private static SessionFactory sessionFactory; // Metodo Setter per l''iniezione della dipendenza della SessionFactory: public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } /** CREATE CRUD Operation: * Aggiunge un nuovo record rappresentato nella tabella rappresentato * da un oggetto Person */ @Transactional(readOnly = false) public Integer addPerson(Person p) { System.out.println("Inside addPerson()"); Session session = sessionFactory.openSession(); Transaction tx = null; Integer personID = null; try { tx = session.beginTransaction(); personID = (Integer) session.save(p); tx.commit(); } catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } return personID; } // READ CRUD Operation (legge un singolo record avente uno specifico id): public Person getById(int id) { System.out.println("Inside getById()"); Session session = sessionFactory.openSession(); Transaction tx = null; Person retrievedPerson = null; try { tx = session.beginTransaction(); retrievedPerson = (Person) session.get(Person.class, id); tx.commit(); }catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } return retrievedPerson; } // READ CRUD Operation (recupera la lista di tutti i record nella tabella): @SuppressWarnings("unchecked") public List<Person> getPersonsList() { System.out.println("Inside getPersonsList()"); Session session = sessionFactory.openSession(); Transaction tx = null; List<Person> personList = null; try { tx = session.beginTransaction(); Criteria criteria = session.createCriteria(Person.class); personList = criteria.list(); System.out.println("personList: " + personList); tx.commit(); }catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } return personList; } // DELETE CRUD Operation (elimina un singolo record avente uno specifico id): public void delete(int id) { System.out.println("Inside delete()"); Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Person personToDelete = getById(id); session.delete(personToDelete); tx.commit(); }catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } @Transactional public void update(Person personToUpdate) { System.out.println("Inside update()"); Session session = sessionFactory.openSession(); Transaction tx = null; try { System.out.println("Insite update() method try"); tx = session.beginTransaction(); session.update(personToUpdate); tx.commit(); }catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } }

Ok, como puedes ver, algunos métodos se anotan usando la anotación @Transactional.

Estoy leyendo la documentación oficial aquí http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html sobre el uso de esta anotación en los métodos y se ve que: A El método anotado utilizando @Transactional debe tener semántica transaccional, pero ¿qué significa con la semántica transaccional?

¿Significa que la ejecución de Methos debe considerarse como la ejecución de una transacción? Por lo tanto, significa que las operaciones del método deben considerarse como una sola operación que puede conducir a un éxito o una falla, si tiene éxito, los resultados de las operaciones deben ser permanentes, mientras que en caso de no volver al estado anterior a el comienzo de la transacción.

¿Es este el significado del uso de la anotación @Transactional en un método?

¿Y qué significa exactamente el atributo readOnly = false en la anotación @Transactional del método addPerson () ? significa que también puedo escribir un registro en la base de datos (y no solo leerlo) o qué? La duda está relacionada porque he entendido que, de forma predeterminada, una transacción definida utilizando @Transactional annotaion es de lectura / escritura y no solo de lectura ... También he intentado eliminar el atributo (readOnly = false) y todavía funciona bien (inserte el nuevo registro en la tabla de la base de datos)

La siguiente pregunta es: "¿por qué algunos métodos son anotados usando la anotación @Transactional y algunos otros métodos no? ¿Es una buena práctica anotar TODO el método CRUD retirado @Transactional?"

Tnx

Andrea


@Transactional se usa con el método.

Declaramos en el nivel de método primero que abre la transacción, realiza la operación y cierra la transacción.

Si una operación falla, se revertirá; si una operación es exitosa, se comprometerá automáticamente.

Esto se trata de la anotación @Transactional y breve.

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd "> <!-- Scans the classpath for annotated components that will be auto-registered as Spring beans --> <context:component-scan base-package="hu.daniel.hari.learn.spring" /> <!-- Activates various annotations to be detected in bean classes e.g: @Autowired --> <context:annotation-config /> <!-- creating the internal datasource object --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:mem://productDb" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:packagesToScan="hu.daniel.hari.learn.spring.orm.model" p:dataSource-ref="dataSource" > <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="generateDdl" value="true" /> <property name="showSql" value="true" /> </bean> </property> </bean> <!-- Transactions --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>

package hu.daniel.hari.learn.spring.orm.main; import hu.daniel.hari.learn.spring.orm.model.Product; import hu.daniel.hari.learn.spring.orm.service.ProductService; import java.util.Arrays; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.dao.DataAccessException; public class SpringOrmMain { public static void main(String[] args) { //Create Spring application context ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/spring.xml"); //Get service from context. (service''s dependency (ProductDAO) is autowired in ProductService) ProductService productService = ctx.getBean(ProductService.class); //Do some data operation productService.add(new Product(1, "Bulb")); productService.add(new Product(2, "Dijone mustard")); System.out.println("listAll: " + productService.listAll()); //Test transaction rollback (duplicated key) try { productService.addAll(Arrays.asList(new Product(3, "Book"), new Product(4, "Soap"), new Product(1, "Computer"))); } catch (DataAccessException dataAccessException) { } //Test element list after rollback System.out.println("listAll: " + productService.listAll()); ctx.close(); } }