Some clarification about Spring @Transactional annotation on a method

前端 未结 2 1089
抹茶落季
抹茶落季 2020-12-08 00:20

I am quite new in Spring world and I have developed a simple project that use Spring 3.2.1 and Hibernate 4.1.9 to implement a DAO. The project work correctly but I have some

相关标签:
2条回答
  • 2020-12-08 00:58

    First of all, you shouldn't make DAO methods transactional, but service methods.

    Second, using Transactional is a way to let Spring start and commit/rollback transactions for you. So you shouldn't start and commit transactions yourself.

    Third: this will only work if you use a transaction manager that knows how to associate a Hibernate session with the transaction (typically, a HibernateTransactionManager). The session factory should also be handled by Spring, and injected by Spring in your DAOs. The code of the DAO should look like this:

    Fourth: you should not open a new session, but get the current one, associated to the current transaction by 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);
        }
    }
    

    Read the documentation for more information.

    0 讨论(0)
  • 2020-12-08 01:05

    @Transactional is used upon the method.

    We declare on method level first it opens the transaction, perform the operation and close the transaction.

    If an operation is failed it will be rollback, if an operation is a success it will automatically be committed

    This is about @Transactional annotation finally&short.

    <?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();
        }
    }
    
    0 讨论(0)
提交回复
热议问题