views:

290

answers:

2

Here is my implementation in summary

1) all DAOs implemented using HibernateDAO support/ @Transational annotation is only used in Service layer

2) Use MySQL / HibernateTransactionManager

3) Test using main(String args[]) method (do transactions work using this method? )

Transactions does not get rollbacked and invalid entried can be seen in the database. What am I doing wrong here?

Detailed information is given below.

1) I have configured transactions using @Transactional annotation in service layer as:

@Transactional(readOnly=false, rollbackFor={DuplicateEmailException.class,DuplicateLoginIdException.class,IdentityException.class},propagation=Propagation.REQUIRES_NEW)
    public void createUserProfile(UserProfile profile)
      throws DuplicateEmailException, DuplicateLoginIdException,
      IdentityException {

     //Accessing DAO (implemented using HibernateDAOSupport)
                identityDAO.createPrincipal(profile.getSecurityPrincipal());
     try {
                //Accessing DAO
      userProfileDAO.createUserProfile(profile);
     } catch (RuntimeException e) {
      throw new IdentityException("UseProfile create Error", e);
     }

    }

2) My Transation Manager configuration / datasource is as follows :

<bean id="dataSource"
     class="org.apache.commons.dbcp.BasicDataSource"
     destroy-method="close">
     <property name="driverClassName" value="com.mysql.jdbc.Driver" />
     <property name="url"
      value="jdbc:mysql://localhost:3306/ibmdusermgmt" />
     <property name="username" value="root" />
     <property name="password" value="root" />
     <property name="defaultAutoCommit" value="false"/>  
    </bean>

    <bean id="sessionFactory"
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
     <property name="dataSource" ref="dataSource" />  
     <property name="mappingLocations"
      value="classpath*:hibernate/*.hbm.xml" />
     <property name="hibernateProperties">
       <prop key="hibernate.dialect">
       org.hibernate.dialect.MySQLDialect
       </prop>    
       <prop key="hibernate.query.substitutions">
        true=1 false=0
       </prop>
       <prop key="hibernate.show_sql">true</prop>
       <prop key="hibernate.use_outer_join">false</prop>
      </props>
     </property>
    </bean>

    <bean id="transactionManager"
     class="org.springframework.orm.hibernate3.HibernateTransactionManager">
     <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

3) Test using main() method as follows :

public static void main(String[] args) {

     ApplicationContext cnt=new ClassPathXmlApplicationContext("testAppContext.xml");
     IUserProfileService upServ=(IUserProfileService)cnt.getBean("ibmdUserProfileService");

     UserProfile up=UserManagementFactory.createProfile("testlogin");//  
     up.setAddress("address");
     up.setCompany("company");
     up.setTelephone("94963842");
     up.getSecurityPrincipal().setEmail("[email protected]");
     up.getSecurityPrincipal().setName("Full Name");
     up.getSecurityPrincipal().setPassword("password");
     up.getSecurityPrincipal().setSecretQuestion(new SecretQuestion("Question", "Answer"));

     try {
      upServ.createUserProfile(up);
     } catch(Exception e){
      e.printStackTrace();
     }
+1  A: 

As far as I know, MySQL's default storage engine MyISAM does not support transactions.

MySQL Server (version 3.23-max and all versions 4.0 and above) supports transactions with the InnoDB and BDB transactional storage engines. InnoDB provides full ACID compliance. ... The other nontransactional storage engines in MySQL Server (such as MyISAM) follow a different paradigm for data integrity called “atomic operations.” In transactional terms, MyISAM tables effectively always operate in autocommit = 1 mode

In order to get transactions working, you'll have to switch your storage engine for those tables to InnoDB. You may also want to use Hibernate's MySQLInnodDBDialect if you generate your tables (hdm2ddl) from your mappings:

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>

As mentioned by @gid, it's not a requirement for transactions though.

sfussenegger
+1  A: 

Yes. you can call transactional objects from main().

@sfussenegger is correct in that MyISAM doesn't support transactions, use of the MySQLDialect dialect doesn't exclude the use of transactions it only means that the hdm2ddl table generation will create InnoDB type tables. (which of course could be your issue).

Can you confirm you are using a transactional type table in MySQL?

Assuming this is true the next thing to do is get some debug output from org.springframework.transaction.support.AbstractPlatformTransactionManager. How to do this depends on which logging framework you are using but it should be straight forward.

Gareth Davis
Thanks gid,I configured log4j using <category name="org.springframework.transaction.support.AbstractPlatformTransactionManager"> <priority value="INFO"/> </category>I cannot see any logging like "Creating new transaction with name".?
umanga
Next stop is to check that the IUserProfileService instance you are getting back from the context is a proxy and that proxy has a reference to the TransactionInterceptor, best to do this in a debugger
Gareth Davis