Announcement Announcement Module
Collapse
No announcement yet.
Why is this test case not rolling back? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Why is this test case not rolling back?

    I was wondering if you can help me out. I've just made a new project with spring, hibernate, mysql (innodb), etc. and I'm trying to get my first test cases working against a very simple dao and very simple test class.

    Basically, the transaction is getting rolled back according to the logger each time. In the delete test, the transaction is actually rolled back in the database. With the store, the transaction is not rolled back and there is data left over from the test in the database. This is undesirable. Besides using DBUnit, is there an easy way to fix this?

    Here is my code:
    @RunWith( SpringJUnit4ClassRunner.class )
    @ContextConfiguration( locations = { "file:./war/WEB-INF/applicationContext-local.xml" } )
    @TransactionConfiguration( transactionManager = "transactionManager" )
    @Transactional
    public class UserDaoImplTest {

    @Autowired
    private UserDao userDao;

    @Test
    public void testStoreUserWhenNew() {
    User user = new User( "Bob", "Johnson" );

    userDao.store( user );

    Assert.assertNotNull( user.getId() );
    }

    @Test
    public void testDeleteUser() {
    userDao.delete( 1 );

    Assert.assertNull( userDao.find( 1 ) );
    }

    @Test
    public void testFindUser() {
    User user = userDao.find( 1 );
    Assert.assertEquals( "Mystic", user.getFirstName() );
    Assert.assertEquals( "Rules", user.getLastName() );
    }

    @Test
    public void testFindByFirstName() {
    Collection collection = userDao.findByFirstName( "Mystic" );
    Assert.assertEquals( collection.size(), 1 );
    }

    @Test
    public void testFindByLastName() {
    Collection collection = userDao.findByLastName( "Rules" );
    Assert.assertEquals( collection.size(), 1 );
    }

    }

  • #2
    Ok, I'm at a total loss as to why this is happening. Hibernate is clearly rolling back the transactions because the logging says it is. The spring transaction manager is working. I don't know why the insert is not actually being rolled back...

    The code for the insert is extremely simple:

    public void store( User user ) {
    this.sessionFactory.getCurrentSession().saveOrUpda te( user );
    }


    I'm trying to make this entire test simple just to get it to work before I do anything more complicated

    Is MySQL just terrible at this stuff? I used postgresql before and had no problems with transactions. Do I need to tell Hibernate to behave differently to get this to work? Do I have to setup mysql differently above and beyond using innodb table structure?

    Please help.

    Comment


    • #3
      Try to fresh the Hibernate session to see whether it helps or not.

      Comment


      • #4
        Thanks for the reply. What do you mean by freshen the hibernate session? I've never had to do anything special in the store methods before, and a few years ago, I worked on a massive project with 100 daos, etc.

        The only thing that's new here for me is that I'm not using DBUnit (let's face it, it's too verbose, hard to setup, and hard to maintain) and I've never used the annotations before. I really just want to manually insert data into the test database using a gui editor like phpMyAdmin and run my tests against that without affecting the state of that prepared database. That would make testing SO MUCH easier for me. DBUnit is just a pain after having used it for a large project... and it makes the tests run slower too.

        Running the test just by itself does not fix the transactional behaviour either.

        Since I am not all that familiar with SQL anymore (I have not used it much in 1.5 years, and even then, I never had to do much SQL manually because HQL was what I was working with), is there a good way to test the transactional behaviour of what I'm trying to do inside the mysql client? That way at least I can see if mysql is the actual problem. And if that's the case, I'm dumping it and going to postgres.

        Comment


        • #5
          Ok, just for kicks I setup progresql with the same database and just changed the config in hibernate to postgresql. I had to change the "user" table to "user_account" to avoid an error... but lo-and-behold... the transactions work PERFECTLY.

          My god... is mysql just as crappy as it was 2-4 years ago? Did they not fix their transaction support to work "as intended"? I figured after so many years, transaction support would actually work correctly and you'd get the speed boost over postgresql... but I guess not. That was the big reason I went with postgres - real database operations actually worked. Mysql seemed like a child's toy.

          Please tell me I am just ignorant and that mysql works correctly with a simple fix... or do I just use postgresql?

          Comment


          • #6
            Originally posted by mystic View Post
            Thanks for the reply. What do you mean by freshen the hibernate session?
            Sorry, what I mean is "flush". I believe that shall work. I run into this situation before in a test case.

            Comment


            • #7
              Mysql

              Hello,
              I had the same problem. I thought that there must be some problem with entity manager or tx manager but since you tested it with PostgreSQL and it worked I checked the mysql and I have noticed that it is using MyISAM table type. If you change the table type InnoDB it works :-)

              Now I just have to figure out how to tell JPA to generate ddl with this type of table.

              Comment


              • #8
                I was using innodb...

                Comment


                • #9
                  Umm... I don't think you guys are getting what I'm trying to do... and what Spring is actually doing here.

                  The test harness is putting all the dao tests within a transaction. The transaction code is not in the dao, but inside the tests. At the end of the spring transaction, the code is rolled back to the previous database state. This way, we don't have to wipe the database and reinsert every after every dao method. This approach is much faster than using something like dbunit.

                  Now, this approach works fine with postgres. It worked fine with mysql for deletes too - again, using innodb. However, it does not work for mysql when you insert. I went into phpMyAdmin and the rollbacks worked fine for inserts when I executed manual queries, so there must be an issue with the code somewhere for mysql specifically.

                  I just have no idea what the problem could be.

                  Comment

                  Working...
                  X